1. 概述
你们都知道Nginx有不少功能模块,好比反向代理、缓存等,这篇文章总结下咱们这些年实际环境中那些有用的Nginx规则和模块,大部分是用法的归纳及介绍,具体细节在实际配置时再自行google。javascript
2. 内置语法
先介绍Nginx默认已支持的内置功能,靠这些基本就知足大部分的web服务需求。php
2.1 proxy代理
proxy经常使用于两类应用场景,一类是中转,如异地科学的上网方式,另一类是到后端服务的负载均衡方案。css
用反向代理时候,须要特别注意里面的域名默认是在nginx启动时候就解析了,除非reload不然一直用的是当初解析的域名,也就是说不能动态解析。html
但这个问题是能够经过别的模块或者用内置字典变量方式来解决。前端
resolver 114.114.114.114; server { location / { set $servers github.com; proxy_pass http://$servers; } }
2.1.1 中转
针对某个域名进行中转:java
server { listen 172.16.10.1:80; server_name pypi.python.org; location ~ /simple { proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://pypi.python.org; } }
注意若是是先后端域名不同的话须要处理proxy_redirect的301跳转之类的显示,不然在跳转时候会跳转到proxy_pass的域名。python
另外能够直接代理全部80端口的http流量:android
server { listen 80; server_name _; resolver 114.114.114.114; set $URL $host; location / { proxy_pass http://$URL; } }
若是是想代理https的站点也不是不可能,只是须要自行处理CA证书导入便可,并且通过https中转的流量对nginx是透明的,也就是有证书的时候作窃听和劫持的状况。nginx
2.1.2 负载均衡
这是代理的另一个常见用法,经过upstream到多个后端,能够经过weight来调节权重或者backup关键词来指定备份用的后端,一般默认就能够 了,或者能够指定相似ip_hash这样的方式来均衡,配置很简单,先在http区域添加upstream定义:git
upstream backend { ip_hash; server backend1.example.com weight=5; server backend2.example.com weight=5;; }
而后在server里面添加proxy_pass:
location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ""; }
作负载均衡的时候能够智能识别后端服务器状态,虽然能够智能地proxy_next_upstream到另外的后端,但仍是会按期损失一些正常的“尝试性”的链接,好比过了max_fails 次尝试以后,休息fail_timeout时间,过了这个时间以后又会去尝试,这个时候可使用第三方的upstream_check模块来在后台按期地自动探索,相似这样:
check interval=3000 rise=2 fall=5 timeout=2000 type=http;
这样替代用户正常的链接来进行尝试的方式进一步保障了高可用的特性。
还有就是在作前端代理的时候也是这样的方式,直接proxy_pass到后端便可,好比CDN的场景。
2.2 防盗链
普通的防盗链是经过referer来作,好比:
location ~* \.(gif|jpg|png|bmp)$ { valid_referers none blocked *.example.com server_names ~\.google\. ~\.baidu\.; if ($invalid_referer) { return 403; } }
再精细一点的就是URL加密,针对一些用户IP之类的变量生成一个加密URL一般是针对文件下载时候用到,能够经过openresty来写lua脚本或者是accesskey之类的模块来实现。
2.3 变量
nginx里面支持正则匹配和变量配置,默认的变量好比remote_addr、request_filename、query_string、server_name之类的,这些组合在一块儿能够作不少规则,或者还有日志里面status、http_cookie等。
还有在进行多域名配置时候能够用通配符,好比:
server_name ~^(www\.)?(.+)$; root /data/web/$2;
这样就实现了自动进行域名的目录指派。
变量方面,好比配置变量a=1:
set $a 1;
下面这个案例配合if判断来作有更大的用处。
2.4 if判断
nginx里面支持一些简单的if判断,可是没有多重逻辑的语法,多个判断条件用起来须要结合变量的方式来实现,好比容许ip地址为10.10.61段和和192.168.100段的用户访问,其他的拒绝,返回405状态码:
set $err 0; if ( $remote_addr ~ 10.10.61.){ set $err 0; } if ( $remote_addr ~ 192.168.100.){ set $err 0; } if ( $err = 1){ return 405; }
这样经过一个err变量比较巧妙实现了需求。
2.5 error_page
有用到后端proxy的地方须要加上这句话才能够传到状态码到nginx:
fastcgi_intercept_errors on;
具体配置通常是配置到具体的错误URL页面,好比:
#返回具体状态码 error_page 404 403 /4xx.html #返回200状态码 error_page 404 403 =200 /error.html
或者采用callback的方式统一作处理:
error_page 404 403 = @fallback; location @fallback { proxy_pass http://backend; access_log /data/logs/404_error.log access; }
这样在重定向时不会改变URL,而后把404页面直接返回。
2.6 rewrite
rewrite作一些30一、302之类的跳转,同时也能够在CDN前端作“去问号”缓存的效果。
location /db.txt { rewrite (.*) $1? break; include proxy.conf; }
另外最多见的跳转写法:
rewrite ^/game/(.*) /$1;
把/game/test跳转为/test的效果,注意这样是没有状态码的,若是访问正常就直接返回200状态码。
能够在后面加个permanent参数,就变为了301 Moved Permanently,或者添加redirect改成302跳转。
同理,还能够进行多个正则匹配进行URL重组,好比:
rewrite ^/download/(.*)/lastest/(.*)$ /file/$1?ver=$2 break;
2.7 日志字段
想针对每一个链接进行日志留档,能够在nginx日志那里配置好字段,好比记录cookie之类的数据。
在log_format字段里面加入$http_cookie变量便可。
另外post的数据能够永久保留在文件里面,好比用来作http的日志备份,包括get和post的原始数据,把这个值开启便可:
client_body_in_file_only on;
而后post的数据就会保存在nginx/client_body_temp文件夹里面。
2.8 internal关键词
这个关键词不多见,但有时候是颇有用的,好比在有不少规则时候,忽然须要针对某个目录转为nginx内部处理。
location ^~ /upload/down/ { alias /data/web/dts/dtsfile/down/; internal; }
2.9 try_files
字面意思是尝试,后面能够接多个目录或者文件,好比kohana框架:
try_files $uri /index.php?$query_string;
先看是否有URL这个文件,没有的话再调用index.php来处理,或者支持状态码处理:
try_files /foo /bar/ =404;
没有这两个文件的话返回404状态。
2.10 auth认证
能够作简单的用户登陆认证方式,其中的passwd_file得经过apache的htpasswd命令来生成。
auth_basic "Restricted"; auth_basic_user_file passwd_file;
认证经过以后每次访问会在头部添加Authorization字段包含用户名密码的base64加密密文给服务端。
2.11 gzip
普通的线上web站点gzip压缩是必需要开的,压缩一些文本类型的文件再返回给用户。
注意必须手动指定全须要压缩的类型,好比css、js之类的,线上配置以下:
gzip on; gzip_min_length 2048; gzip_buffers 4 16k; gzip_vary on; gzip_http_version 1.1; gzip_types text/plain text/css text/xml application/xml application/javascript application/x-javascript ;
2.12 mime配置
好久之前基本是忽略这个配置,但手游流行以后就发现异常了,须要让手机浏览器知道返回的apk后缀是什么类型,不然相似IE浏览器会以zip后缀返回,须要加上:
application/vnd.android.package-archive apk; application/iphone pxl ipa;
2.13 限速
限速包括限制请求的并发数和请求的下载速度。
简单的限制某个线程的下载速度就直接加上一句话就能够了:
limit_rate 1024k;
要限制某个IP的并发数之类的就须要用ngx_http_limit_req_module和ngx_http_limit_conn_module模块了,不过是默认就编译好的。
好比使用一个 10M 大小的状态缓存区,针对每一个IP每秒只接受20次的请求:
limit_req_zone $binary_remote_addr zone=NAME:10m rate=20r/s;
2.14 location匹配
location匹配有多种方式,常见的好比
location = / location / location ^~ /test{
是有优先级的,直接 ”=” 的优先级是最高的,通常就用”~”这个符号来匹配php就行了,不过是区分了大小写的:
location ~ .*\.php$
2.15 文件缓存
返回给用户的文件通常都配置了过时时间,让浏览器缓存起来。
好比缓存14天:
expires 14d;
针对某些特殊的文件就须要location匹配以后进行禁止缓存配置:
add_header Cache-Control no-cache; add_header Cache-Control no-store; expires off;
2.16 缓存文件
nginx能够做为ATS这样的缓存服务器来缓存文件,配置也比较简单,不过咱们不多用,除非一些特殊的场合,参考配置:
3. 内置模块#先在全局下面定义好缓存存放的目录 proxy_cache_path /data/cache/ levels=1:2 keys_zone=cache_one:10m inactive=7d max_size=10g; proxy_temp_path /data/cache/proxy_temp_path; proxy_cache_key $host$uri$is_args$args; #而后在server里面的location匹配好目的文件,加入下一段便可 proxy_cache cache_one; proxy_cache_valid 200 304 24h; proxy_cache_valid any 10m; proxy_pass https://$host; proxy_cache_key $host$uri$is_args$args; add_header Nginx-Cache "$upstream_cache_status";
3. 内置模块
nginx含有大量的模块能够支持多种复杂的需求,好比源码目录src/http/modules里面就有不少c模块的代码,或者直接经过./configure –help|grep module来查看有哪些内置模块,编译时候直接加上就能够了。
除了nginx内置的模块,网络上还有不少第三方的模块,能够经过编译时候加参数–add-module=PATH指定模块源码来编译。
下面介绍一些咱们线上用过并且比较赞的内置模块。
3.1 stream
端口转发的模块,从nginx1.9版本才开始支持,包含tcp和udp的支持,和IPTABLES相比这个虽然是应用层,会监听端口,可是配置起来很方便,比IPTABLES灵活,在tcp模块下面添加相似vhost的server就能够了,方便自动化管理,参考配置:
server { listen PORT; proxy_pass IP:PORT; access_log /data/logs/tcp/PORT.log; }
3.2 http_realip_module
nginx反向代理以后,如何让后端web直接获取到的IP不是反向代理的iP,而是直接获取到用户的真实IP呢,就须要这个模块了,不须要代码那里再作相似X-Real-IP的变量特殊判断。
3.3 http_slice_module
在作CDN时候能够用到,让一个大文件分片,分红多个小文件经过206断点续传到后端,而后再组合起来,避免大文件直接回源致使多副本和屡次回源的问题。
3.4 http_secure_link_module
前面说到的防盗链能够用这个来作,可是这个通常是针对那种文件下载时候用到的,好比从网页下载时候,服务端生成一个加密URL给用户,而后这个URL有过时时间之类的,避免此URL被屡次分享出去,不过普通的素材加载仍是用普通的防盗链便可。
3.5 http_sub_module
替换响应给用户的内容,相对于sed以后再返回,好比能够在须要临时全局修改网站背景或者title时候能够一次性处理好。
4. 扩展项目
简单介绍下大名鼎鼎的两个基于nginx的扩展项目,也是咱们线上有不少地方用到的。
4.1 openresty
集成lua脚本,几乎能够完成任何普通web相关的需求。
好比URL加密进行防劫持和防盗链,服务端动态生成一串aes加密的URL给CDN,CDN的openresty解密以后用普通的URL转发到后端,而后再返回给用户正确的内容。
4.2 tengine
淘宝的nginx修改版,实现了不少nginx的收费功能或者是特殊功能,好比动态加载、concat合并请求,动态解析等。
咱们python开发的后台基本都是用的这个版本,主要是利用了concat的合并素材的功能。
5. 结语
Nginx是个很是实用软件,部分功能已经超越了普通的web服务定位,同时它具有开源、轻量、自动化等特性,能有效解决实际工做中不少特殊场景的需求。