Nginx 快速上手
根据实际的应用需要,学习要用到的 Nginx 的知识,以快速上手、理解并掌握 Nginx 六:学习反向代理、动静分离、负载均衡、Geo 和 GeoIP 模块七:学习 Rewrite 模块和更多其它模块的功能 八:学习更多常见功能的片断配置 九:Nginx 的配置优化建议
Http 反向代理 Nginx 通常被用作后端服务器的反向代理,这样就可以很方便的实现动静分离,以及负载均衡,从而大大提高服务器的处理能力。
Http Proxy 模块,功能很多,最常用的是 proxy_pass,最好还是都看看。
如果要使用 proxy_cache 的话,需要集成第三方的 ngx_cache_purge 模块,用来清除指定的 URL 缓存。这个集成需要在安装 nginx 的时候去做,形如:./configure –add-module=../ngx_cache_purge-1.0 ……
动静分离 Nginx 实现动静分离,其实就是在反向代理的时候,如果是静态资源,那么就直接从 Nginx 发布的路径去读取,而不需要从后台服务器获取了。
但是要注意:这种情况下需要保证后端跟前端的程序保持一致,可以使用 Rsync 做服务端自动同步或者使用 NFS、MFS 分布式共享存储。
负载均衡 Nginx 通过 upstream 模块来实现简单的负载均衡在 upstream 块内,定义一个服务器列表,默认的方式是轮询,如果要确定同一个访问者发出的请求总是由同一个后端服务器来处理,可以设置 ip_hash,如:upstream cctest1.com {ip_hashserver 127.0.0.1:9080 weight=5;server 127.0.0.1:8080 weight=5;server 127.0.0.1:1111;} 请注意:这个方法本质还是轮询,而且由于客户端的 ip 可能是不断变化的,比如动态 ip,代理,翻墙等等,因此 ip_hash 并不能完全保证同一个客户端总是由同一个服务器来处理。
更多指令和配置,请参考 Nginx 的 http 负载均衡模块
Geo 和 GeoIP 模块这两个模块主要用于做全局的负载均衡,可以根据不同的客户端 ip 来访问不同的服务器,示例如下:http{geo $geo{default default;202.103.10.1/24 A;179.9.0.3/24 B;}upstream default.server{server 192.168.0.100;}upstream A.server{server 192.168.0.101;}upstream B.server{server 192.168.0.102;}server{listen 80;location / {proxy_pass http://$geo.server$request_uri;}}}Rewrite 模块配置 -1Rewrite 模块:用来执行 URL 重定向。这个机制有利于去掉恶意访问的 url,也有利于搜索引擎优化 (SEO)。
Nginx 使用的语法源于 Perl 兼容正则表达式(PCRE)库,基本语法如下:^:必须以 ^ 后的实体开头 $:必须以 $ 前的实体结尾.:匹配任意字符 []:匹配指定字符集内的任意字符 1:匹配任何不包括在指定字符集内的任意字符串 |:匹配 | 之前或之后的实体 ():分组,组成一组用于匹配的实体,通常会有 | 来协助
捕获子表达式,可以捕获放在()之间的任何文本,比如:^(.*)(hello|sir)$ 字符串为“hi sir”捕获的结果:$1=hi $2=sir 这些被捕获的数据,在后面就可以当变量一样使用了
Rewrite 模块配置 - 2 内部请求外部请求是客户端的 url,内部请求是 Nginx 通过特殊的指令触发。比如:error_page、index、rewrite、try_files、include 等等
内部请求分成两种类型 1:内部重定向:URI 被改变,可能会匹配到其他的 Location2:子请求:比如使用 Addition 模块,指令 add_after_body 允许你在原始的 URI 之后指定一个 URI,会把该 URI 被处理后的结果,插入到原始的 URI 的 body 中。内部重定向示例 server {server_name xxxxx.com;location /abc/ {rewrite ^/abc/(.*)$ /bcd/$1}location /bcd/{internal;root pages;}}
Rewrite 模块配置 - 3 条件结构的基本语法:1:没有操作符:指定的字符串或者变量不为空,也不为 0 开始的字符串,取 true2:=,!=,例:if($request_method = POST){…}3:~,~,!~,!~,例:if($uri ~*“\.jsp$”){…}4:-f,!-f : 用来测试指定文件是否存在,例:if(-f $request_filename){…}5:-d,!-d:用来测试指定目录是否存在 6:-e,!-e:用来测试指定文件、目录或者符号链接是否存在 7:-x,!-x:用来测试指定文件是否存在和是否可以执行 8:break:跳出 if 块 9:return:终止处理,并返回一个指定的 http 状态码 10:set:初始化或者重定义一个变量
其它模块 -1Http Index 模块,都看看 Http Referer 模块,都看看,可用于防盗链 Http Limit Zone 模块,都看看,可用于会话的连接数控制,如限制每个 IP 的并发连接数等 Http Access 模块,用于简单的访问控制,都看看 Http Charset 模块,重点看看:charsetGzip 模块,可以都看看 Http Browser 模块,用于按照请求头中的“User-agent”来创建一些变量,好为不同的浏览器创建不同的内容,暂时了解即可 Memcached 模块,这是把 Nginx 当作 Memcached 的客户端,用来连接 Memcached 的模块。暂时不用看 Http Addition 模块,可以在当前 location 内容之前或后添加内容,暂时不用看其它模块 -2Http Empty Gif 模块,这个模块在内存中保存一个能够很快传递的 1×1 透明 GIF,暂时不用看 Http Auth Basic 模块,基于 Http Basic 认证的方式来保护虚拟主机或目录,暂时不用看 Http AutoIndex 模块,用于提供自动目录列表,该模块只有在找不到默认的 index 文件的时候才启用,暂时不用看 Http Fcgi 模块,用于与 FastCGI 进程交互,暂时不用看 FLV Stream 模块,支持当 Http 下载方式播放 Flv 时,可以支持进度条拖放,暂时不用看。SSL 模块,暂时不用看邮件模块,暂时不用看还有很多的模块,这里就不再一一介绍了
常见功能的配置片断 -1server 配置为监听 ip 和端口 server{listen 127.0.0.1:9080;server_name 127.0.0.1;}server 配置为监听域名和端口 server{listen 80;server_name www.xxx.com xxx.com *.xxx.com;} 向后台服务器传递客户端的真实 iplocation ~ .(jsp|action|mvc)$ {proxy_set_header Host $host;proxy_set_header X-Forwarded-For $remote_addr;proxy_pass http://xxx.com;}
常见功能的配置片断 - 2 在负载均衡里面,实现后端服务器故障转移的配置 location ~ .(jsp|action|mvc)$ {proxy_next_upstream http_502 http_504 timeout;proxy_set_header Host $host;proxy_set_header X-Forwarded-For $remote_addr;proxy_pass http://server_pool;} 简单的防盗链 location / {……valid_referers blocked xxx.com *.xxx.com;if($invalid_referer){rewrite ^/ http://xxx.com;}} 简单的限制下载速度 location / {limit_rate 256K;}
常见功能的配置片断 - 3 使用 proxy_cache 的配置 http{# 下面这两个 path 指定的路径必须在同一个分区 proxy_temp_path /cachetemp/proxy_temp_path;
设置名称为 mycache,内存缓存 100m,自动清除 1 天未使用的内容,硬盘缓存空间 1g
proxy_cache_path /cachetemp/proxy_cache_path levels=1:2 keys_zone=mycache:100minactive=1d max_size=1g;server{location ~ .*.(gif|jpg|html|js|css)$ {proxy_cache mycache; #使用名称为 mycache 的缓存
对不同的 Http 状态码设置不同的缓存时间
proxy_cache_valid 200 304 24h;proxy_cache_valid 301 302 10m;proxy_cache_valid any 1m;
设置缓存的 key 值
proxy_cache_key $host$uri$is_args$args;}}}
Nginx 的配置优化 - 1 如果没有足够的实力和必要去自己改写 Nginx,那么 Nginx 的优化主要就是:优化 Nginx 的配置,做到合理高效的使用优化的方向和目标,无外乎:1:尽量提高单台机器处理效率 2:尽量降低单台机器的负载 3:尽量降低磁盘 I /O4:尽量降低网络 I /O5:尽量减少内存使用 6:尽量高效利用 CPU 生产环境下,应该使 Nginx 模块最小化,就是用到哪几个就开哪几个,这个需要在编译安装 Nginx 的时候做。
Nginx 的配置优化 - 2 用户和组,生产环境下,最好是专为 Nginx 创建用户和组,并单独设置权限,这样会更安全。例如:user nginx nginx
worker_processes : 通常配置成 cpu 的总核数,或者其 2 倍,性能会更好。这可以减少进程间切换带来的消耗。还可以同时使用 worker_cpu_affinity 来绑定 cpu,使得每个 worker 进程独享一个 cpu,实现完全的并发,性能更好,不过这个只对 linux 系统有效。events 里面的事件模型,Linux 推荐使用 epoll 模型,FreeBSD 推荐采用 kqueueworker_rlimit_nofile:描述一个 nginx 进程打开的最多的文件数目。配置成跟 linux 内核下文件打开数一致就可以了。可以通过 ulimit -n 来查看,新装的系统默认是 1024,CentOS 中可以如下方式进行修改:在 /etc/security/limits.conf 最后增加:
soft nofile 65535
hard nofile 65535
soft nproc 65535
hard nproc 65535
Nginx 的配置优化 -3worker_connections:每个进程允许的最多连接数,默认是 1024,可以设置大一些。理论上并发总数是 worker_processes 和 worker_connections 的乘积,worker_connections 值的设置跟物理内存大小有关,因为系统可以打开的最大文件数和内存大小成正比,一般 1GB 内存的机器上可以打开的文件数大约是 10 万左右,所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置。keepalive_timeout:设置到 65 左右就可以 client_header_buffer_size:设置请求的缓存,设置为 4k,通常为系统分页大小的整数倍,可以通过 getconf PAGESIZE 来查看系统分页大小。对打开文件设置缓存 open_file_cache max= 建议设置成和每个进程打开的最大文件数一致 inactive=60s;open_file_cache_valid 90s;open_file_cache_min_uses 2;open_file_cache_errors on; 尽量开启 Gzip 压缩,gzip_comp_level 通常设置成 3 -5,高了浪费 CPUError 日志优化:运行期间设置为 crit,可以减少 I /O
Nginx 的配置优化 -4access 日志优化:如果使用了其他统计软件,可以关闭日志,来减少磁盘写,或者写入内存文件,提高 I / O 效率。sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,通常应设置成 on,如果是下载等应用磁盘 IO 重负载应用,可设置为 offBuffers size 优化:如果 buffer size 太小就会到导致 nginx 使用临时文件存储 response,这会引起磁盘读写 IO,流量越大问题越明显。client_body_buffer_size 处理客户端请求体 buffer 大小。用来处理 POST 提交数据,上传文件等。client_body_buffer_size 需要足够大以容纳需要上传的 POST 数据。同理还有后端的 buffer 数据。worker_priority 进程优先级设置:Linux 系统中,优先级高的进程会占用更多的系统资源,这里配置的是进程的静态优先级,取值范围 -20 到 +19,-20 级别最高。因此可以把这个值设置小一点,但不建议比内核进程的值低(通常为 -5)合理设置静态资源的浏览器缓存时间,尽量用浏览器缓存负载均衡锁 accept_mutex,建议开启,默认就是开启的如果使用 SSL 的话,而且服务器上有 SSL 硬件加速设备的话,请开启硬件加速。
↩