高可扩展性、高性能、大数据量、高并发、分布式的系统架构---nginx浅谈 weir 2015-06-12 10:07:16.0 java,分布式 3181 关于nginx对于互联网公司都不是什么陌生的事情,至于nginx的历史发展这些在网上看看就行了,我们只需要知道的是它能干什么优势是什么,在没有回答这个问题之前我们先想想这理解一下面向互联网的网站的发展历程。 什么叫做面向互联网的网站,通俗一点说就是任何人可以通过网络连接到的网站都属于面向互联网的网站。此类网站有什么特点呢?恐怕最大的特点就是用户有可能很多可能相当的多,你说你弄一台应用服务器够用么,肯定不行,接下来很自然的就像弄两台三台N台来满足用户的访问。你弄了这么多应用服务器怎么访问管理呀?duang duang duang nginx闪亮登场,当然你可能说还有apache呢也很强大呀,那么关于这两个web服务器的有略比较我就不在这里说了,自己找找看看就行了。 Nginx最大的优势就是负载均衡和反向代理,虽然他还有诸多的用途,发挥每一个工具的最大优势才能达到我们想要的最大化需求。这就像一个人一样也要发挥他的最大优势才能产生最大的价值。 更多图文并茂的展示可以查看另外一篇文章:高可扩展性、高性能、大数据量、高并发、分布式的系统架构---开篇 在nginx里面最常用的配置文件就是nginx.conf,换句话说这个配置文件才是nginx的核心文件,里面做的各种灵活的配置决定了你的网站访问是否流畅速度快,nginx的优化也是在这里进行,总之一句话搞定了这个文件就搞定了nginx。 ##运行用户 [用户组] user root; ##nginx进程数,建议设置为等于CPU总核心数 worker_processes 1; ##全局错误日志定义类型,[ debug | info | notice | warn | error | crit ] error_log logs/error.log crit; #error_log logs/error.log notice; #error_log logs/error.log info; ##进程文件 pid logs/nginx.pid; ##一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除, ##但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。 worker_rlimit_nofile 1024; events { ##参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型, ##如果跑在FreeBSD上面,就用kqueue模型。 use epoll; ##单个进程最大连接数(最大连接数=连接数*进程数) worker_connections 1024; } ##设定http服务器 http { ##文件扩展名与文件类型映射表 include mime.types; ##反向代理配置 include ccproxy.conf; ##默认文件类型 default_type application/octet-stream; ##设置日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; ##日志输出位置 access_log logs/access.log main; ##服务器名字的hash表大小 server_names_hash_bucket_size 256; ##设置读取客户端请求正文的缓冲容量.如果请求正文大于缓冲容量,整个正文或者正文的一部分将写入临时文件。 ##缓冲大小默认等于两块内存页的大小,在x86平台、其他32位平台和x86-64平台,这个值是8K。在其他64位平台,这个值一般是16K。 client_body_buffer_size 128k; ##设置读取客户端请求头部的缓冲容量。 对于大多数请求,1K的缓冲足矣。 但如果请求中含有的cookie很长,或者请求来自WAP的客户端,可能请求头不能放在1K的缓冲中。 ##如果从请求行,或者某个请求头开始不能完整的放在这块空间中,那么nginx将按照 large_client_header_buffers指令的配置分配更多更大的缓冲来存放。 directive. client_header_buffer_size 8k; ##设置允许客户端请求正文的最大长度。请求的长度由“Content-Length”请求头指定。 如果请求的长度超过设定值, ##nginx将返回错误413 (Request Entity Too Large)到客户端。 请注意浏览器不能正确显示这个错误。 将size设置成0可以使nginx不检查客户端请求正文的长度。 client_max_body_size 50m; ##定义读取客户端请求头部的超时。如果客户端在这段时间内没有传送完整的头部到nginx, nginx将返回错误408 (Request Time-out)到客户端。 client_header_timeout 1m; ##定义读取客户端请求正文的超时。超时是指相邻两次读操作之间的最大时间间隔,而不是整个请求正文完成传输的最大时间。 ##如果客户端在这段时间内没有传输任何数据,nginx将返回408 (Request Time-out)错误到客户端。 client_body_timeout 1m; ##设置读取客户端请求超大请求的缓冲最大number(数量)和每块缓冲的size(容量)。 HTTP请求行的长度不能超过一块缓冲的容量, ##否则nginx返回错误414 (Request-URI Too Large)到客户端。 每个请求头的长度也不能超过一块缓冲的容量,否则nginx返回错误400 (Bad Request)到客户端。 ##缓冲仅在必需是才分配,默认每块的容量是8K字节。 即使nginx处理完请求后与客户端保持入长连接,nginx也会释放这些缓冲。 large_client_header_buffers 4 8k; ##设置向客户端传输响应的超时。超时仅指两次相邻写操作之间的时间间隔,而非整个响应的传输时间。 如果客户端在这段时间中没有收到任何数据,连接将关闭。 send_timeout 3m; ##开启或关闭使用sendfile()调用。 sendfile on; ##第一个参数设置客户端的长连接在服务器端保持的最长时间(在此时间客户端未发起新请求,则长连接关闭)。 ##第二个参数为可选项,设置“Keep-Alive: timeout=time”响应头的值。 可以为这两个参数设置不同的值。 ##“Keep-Alive: timeout=time”响应头可以被Mozilla和Konqueror浏览器识别和处理。 MSIE浏览器在大约60秒后会关闭长连接。 keepalive_timeout 120; ##开启或关闭nginx使用TCP_NODELAY选项的功能。 这个选项仅在将连接转变为长连接的时候才被启用。(译者注,在upstream发送响应到客户端时也会启用)。 tcp_nodelay on; ##开启或者关闭nginx在FreeBSD上使用TCP_NOPUSH套接字选项, 在Linux上使用TCP_CORK套接字选项。 选项仅在使用sendfile的时候才开启。 开启此选项允许 ##在Linux和FreeBSD 4.*上将响应头和正文的开始部分一起发送; ##一次性发送整个文件。 tcp_nopush on; ##开启或者关闭gzip模块 gzip on; ##设置允许压缩的页面最小字节数,页面字节数从header头中的Content-Length中进行获取。 ##默认值是0,不管页面多大都压缩。 ##建议设置成大于1k的字节数,小于1k可能会越压越大。 即: gzip_min_length 1024 gzip_min_length 1k; ##设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。 例如 4 4k 代表以4k为单位,按照原始数据大小以4k为单位的4倍申请内存。 ##4 8k 代表以8k为单位,按照原始数据大小以8k为单位的4倍申请内存。 ##如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。 gzip_buffers 4 16k; ##识别http的协议版本。由于早期的一些浏览器或者http客户端,可能不支持gzip自解压,用户就会看到乱码,所以做一些判断还是有必要的。 ##注:21世纪都来了,现在除了类似于百度的蜘蛛之类的东西不支持自解压,99.99%的浏览器基本上都支持gzip解压了,所以可以不用设这个值,保持系统默认即可。 gzip_http_version 1.1; ##gzip压缩比,1 压缩比最小处理速度最快,9 压缩比最大但处理最慢(传输快但比较消耗cpu)。 gzip_comp_level 2; ##匹配MIME类型进行压缩,(无论是否指定)"text/html"类型总是会被压缩的。 gzip_types text/plain application/x-javascript text/css application/xml; ##和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩 gzip_vary on; ##upstream模块来实现简单的负载均衡(*****) upstream cctest1.com { #server 127.0.0.1:9080 weight=5; server 127.0.0.1:8080 weight=5; #server 127.0.0.1:1111; } ##设置虚拟主机的配置 server { ##端口 listen 80; ##设置虚拟主机名 server_name ccserver1; #charset koi8-r; ##日志记录路径 main是上面定义好的格式 access_log logs/host.access.log main; ##默认要访问的页面,按顺序访问 index index.html index.htm index.jsp; ##为请求设置根目录 root /root/weir/apache-tomcat-8.0.15/webapps/ROOT/; ##静态资源配置 location ~* .*\.(jpg|jpeg|gif|png|swf|ico)$ { if (-f $request_filename) { #expires 15d; break; } } location ~* .*\.(html|htm|js|css)$ { #expires 1d; } ##匹配根下面的所有请求 location / { proxy_pass http://cctest1.com; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { internal; root errors/html; } } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443; # server_name localhost; # ssl on; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_timeout 5m; # ssl_protocols SSLv2 SSLv3 TLSv1; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} } 如果说一上去让你弄nginx的配置文件你肯定就蒙了,感觉好高端好高大上我觉得这东西就像windows与linux一样,我们的感觉是linux高大上,为什么? 从发展的角度来说我们希望我们所用到的工具越简单越好,为什么什么东西放到了linux上面就觉得比较难原因就在于此,因为在linux上面操作东西不够简单明了。从这里再引申出另外一个问题,为什么在linux上面的各种服务相对的要比在windows上面稳定性和性能上面要好一些,这些问题都是计算机信息领域最根本的问题最能影响我们使用它的原因。比如磁盘的读取速度,比如二进制的问题,所以计算机的革命性的运动还没有发生,当然我们也要看到计算机的发展毕竟才几十年,能发展到现在的水平已经相当的不容易了。 我们回到正题,nginx其实不难操作和理解,它的用处就是为了负载均衡和反向代理,我只要把我的各个应用服务器让nginx来管理就行了,就像这样: ##upstream模块来实现简单的负载均衡(*****) upstream cctest1.com { #server 127.0.0.1:9080 weight=5; server 127.0.0.1:8080 weight=5; #server 127.0.0.1:1111; } 这个东西你可以配置多个呀,你这里配置多个server 地址就行了负载均衡就这么简单的解决了,这里面最难的是什么?是各种配置参数而且还是英文而且还没有中文翻译,你知道中国的程序员最悲哀的是什么么?那就是没有一个自己做的好东西。无论从计算机底层还是到软件应用层全是外国的东西,任重而道远呀。 就这一点阻碍了多少仁人志士的奋斗激情,却被无情的卡在了语言上面无法进步,这真的不能不说是悲剧。 中文文档:http://www.nginx.cn/doc/ http://tengine.taobao.org/nginx_docs/cn/docs/ 这两个算是比较靠谱的,切换着看。 如果你也想在你们的服务器上面用nginx虽然不是大型的分布式集群,搞一个小型的负载均衡集群也是可以的,然后做一下动静分离的配置,及UI轩昂我面配置里面的: ##静态资源配置 location ~* .*\.(jpg|jpeg|gif|png|swf|ico)$ { if (-f $request_filename) { #expires 15d; break; } } location ~* .*\.(html|htm|js|css)$ { #expires 1d; } 把一些静态资源文件都交给nginx直接处理,这里其实还是用到了反向代理,还可以把静态资源做一下缓存,还可以让静态资源缓存到每一客户端做浏览器缓存,这些nginx都比较擅长。 通过这个架构nginx也可以弄出来多台那你的访问量将得到迅速的提升。 对于nginx来说还是那句话充分发挥它的优势,我就做负载均衡和反向代理,其他功能我不用,因为还会有更好的东西去处理,比如对静态资源的管理我们就可以使用varnish,虽然nginx也可以处理但是它还是没有Varnish 强悍,他甚至还可以缓存一些jsp之类的动态资源这是varnish的强项,下一篇我们将会对varnish做介绍,敬请期待。