当前位置: 首页 > 科技观察

说说那些实用的Nginx规则

时间:2023-03-21 14:42:43 科技观察

1。概述大家都知道Nginx有很多功能模块,比如反向代理、缓存等,本文总结了这些年在我们实际环境中有用的Nginx规则和模块。其中一部分是对用法的概括和介绍,具体细节可以在实际配置时自行google。2.内置语法首先介绍一下Nginx默认支持的内置函数,基本可以满足大部分的web服务需求。2.1ProxyProxy常用于两类应用场景,一是中转,如远程科学上网,二是对后端服务的负载均衡解决方案。在使用反向代理时需要特别注意的是,nginx启动时默认解析其中的域名。除非重新加载,否则会一直使用原来解析的域名,也就是说不能动态解析。但是这个问题可以通过其他模块或者使用内置的字典变量来解决。resolver114.114.114.114;server{location/{set$serversgithub.com;proxy_passhttp://$servers;}}2.1.1中转域名:server{listen172.16.10.1:80;server_namepypi.python.org;location~/simple{proxy_set_headerHost$http_host;proxy_redirectoff;proxy_passhttp://pypi.python.org;}}注意如果前后端域名不同,需要处理proxy_redirect的301跳转等显示,否则它会在跳转的时候,跳转到proxy_pass的域名。另外可以直接代理所有80端口的http流量:server{listen80;server_name_;resolver114.114.114.114;set$URL$host;location/{proxy_passhttp://$URL;}}如果你想代理httpssite不是不可能的,只需要自己处理CA证书导入,通过https传输的流量对nginx是透明的,即有证书的时候可以窃听和劫持。2.1.2负载均衡这是代理的另一个常见用途。通过upstream到多个backend,可以通过weight调整权重或者使用backup关键字指定backend进行备份。通常默认就够了,也可以指定ip_hash之类的用来平衡,配置很简单,先在http区添加upstream定义:upstreambackend{ip_hash;serverbackend1.example.comweight=5;serverbackend2.example。comweight=5;;}然后在服务器中添加proxy_pass:location/{proxy_passhttp://backend;proxy_http_version1.1;proxy_set_headerConnection"";}做负载均衡时,可以智能识别后端服务器的状态。虽然它可以智能地将_next_upstreamproxy_next_upstream到另一个后端,但它仍然会定期丢失一些正常的“尝试”,例如,在max_fails次尝试后,暂停fail_timeout并在该时间后重试。这时候可以使用第三方的upstream_check模块在后台定时自动探索,像这样:checkinterval=3000rise=2fall=5timeout=2000type=http;这种尝试代替用户正常连接的方式进一步保证了高可用性特性。另外在做前端代理的时候也是一样的,直接proxy_pass给后端就好了,比如CDN场景。2.2防盗链普通的防盗链是通过referer做的,例如:location~*\.(gif|jpg|png|bmp)${valid_referersnoneblocked*.example.comserver_names~\.google\.~\.baidu\.;if($invalid_referer){return403;}}更细化的是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$a1;下面的case结合if判断会更有用。2.4if判断Nginx支持一些简单的if判断,但是没有针对多种逻辑的语法。多个判断条件需要结合变量来实现。例如允许ip地址为10.10.61和192.168.100的用户访问,其余拒绝,返回405状态码:set$err0;if($remote_addr~10.10.61.){set$err0;}if($remote_addr~192.168.100.){set$err0;}if($err=1){return405;}这样通过一个err变量巧妙的实现了需求。2.5error_page对后端代理有用,需要加上这句将状态码传给nginx:fastcgi_intercept_errorson;具体配置一般配置到具体的错误URL页面,例如:#返回具体的状态码error_page404403/4xx.html#返回200状态码error_page404403=200/error.html或者使用回调方法统一处理:error_page404403=@fallback;location@fallback{proxy_passhttp://backend;access_log/data/logs/404_error.logaccess;}重定向的时候不改变url,直接返回404页面。2.6rewriterewrite做一些301、302等跳转,也可以做CDN前端“去问号”缓存的效果。location/db.txt{rewrite(.*)$1?break;includeproxy.conf;}另外最常见的跳转写法:rewrite^/game/(.*)/$1;把/game/test改成/test注意,这种方式没有状态码。如果访问正常,则直接返回200状态码。后面可以加一个permanent参数改成301MovedPermanently,或者加redirect改成302jump。同样,也可以使用多个正则匹配来重组URL,如:rewrite^/download/(.*)/latest/(.*)$/file/$1?ver=$2break;2.7日志字段要针对每个连接的日志文件,可以在nginx日志中配置字段,比如记录cookies等数据。将$http_cookie变量添加到log_format字段。另外,post数据可以一直保存在文件中,比如http的日志备份,包括get和post的原始数据,只需要开启这个值:client_body_in_file_onlyon;然后发布数据将保存在文件夹内的nginx/client_body_temp中。2.8internal关键字这个关键字很少见,但有时却很有用。比如规则比较多的时候,突然需要对某个目录切换到nginx内部处理。location^~/upload/down/{alias/data/web/dts/dtsfile/down/;internal;}2.9try_files字面意思是尝试,后面跟着多个目录或文件,比如kohana框架:try_files$uri/index。php?$query_string;首先检查是否有url文件,如果没有,则调用index.php进行处理,或者支持状态码处理:try_files/foo/bar/=404;如果没有这两个文件,返回404状态。2.10auth认证可以作为简单的用户登录认证方式,passwd_file必须通过apache的htpasswd命令生成。auth_basic“受限”;auth_basic_user_filepasswd_file;认证通过后,每次访问都会将Authorization字段中包含用户名和密码的base64加密密文添加到服务器。2.11gzip普通在线网站必须开启gzip压缩,将一些文本类型的文件压缩后返回给用户。注意,必须手动指定所有需要压缩的类型,如css、js等,网上配置如下:gzipon;;2.12mime配置很久以前基本忽略这个配置,但是手游流行之后发现异常。需要让手机浏览器知道返回的是什么类型的apk后缀,否则类似的IE浏览器会返回一个zip后缀,需要添加:application/vnd.android.package-archiveapk;application/iphonepxlipa;2.13限速限速包括限制并发请求数和请求下载速度。简单的加一句限制某个线程的下载速度:limit_rate1024k;限制某个IP的并发数,需要用到ngx_http_limit_req_module和ngx_http_limit_conn_module模块,但是默认是编译好的。比如使用10M的状态缓存区,每个IP每秒只接受20个请求:limit_req_zone$binary_remote_addrzone=NAME:10mrate=20r/s;2.14位置匹配位置匹配的方式有很多种,比如location=/location/location^~/test{优先,直接“=”的优先级最高。一般用符号“~”来匹配php就好了,但是要区分大小写:location~.*\.php$2.15文件缓存返回给用户的文件一般都会配置一个过期时间,这样的话浏览器可以缓存它们。比如缓存14天:expires14d;对于一些特殊的文件,需要在位置匹配后关闭缓存配置:add_headerCache-Controlno-cache;add_headerCache-Controlno-store;到期;2.16缓存文件nginx可以作为ATS等缓存服务器进行缓存文件和配置都比较简单,但是我们很少用到,除非一些特殊场合,参考配置:#首先在全局proxy_cache_path下定义缓存存放目录/data/cache/levels=1:2keys_zone=cache_one:10minactive=7dmax_size=10g;proxy_temp_path/data/cache/proxy_temp_path;proxy_cache_key$host$uri$is_args$args;#然后服务器中的位置匹配目标文件,并且你可以添加下一段proxy_cachecache_one;proxy_cache_valid20030424h;proxy_cache_validany10m;proxy_passhttps://$host;proxy_cache_key$host$uri$is_args$args;add_headerNginx-Cache"$upstream_cache_status";3.内置模块c模块的代码很多,也可以直接通过./configure–help|grepmodule查看内置模块,编译时直接添加即可。除了nginx自带的模块外,网上还有很多第三方模块,可以在编译的时候加上参数--add-module=PATH指定模块的源码来编译。下面是一些我们在网上用过并且喜欢的内置模块。3.1流端口转发模块只从nginx1.9版本开始支持,包括对tcp和udp的支持。和IPTABLES相比,虽然是应用层,会监听端口,但是配置起来非常方便,比IPTABLES更加灵活。在tcp模块下面添加一个类似vhost的server,方便自动管理。参考配置:server{listenPORT;proxy_passIP:PORT;access_log/data/logs/tcp/PORT.log;}直接获取的IP不是反向代理的IP,而是直接获取用户的真实IP。这个模块是需要的,代码中不需要像X-Real-IP这样对变量做特殊判断。3.3http_slice_module可以在做CDN的时候使用。让一个大文件切片,分成多个小文件通过206个断点继续传给后端,然后合并,避免大文件的多次拷贝和多次回源直接回源的问题。3.4http_secure_link_module上面提到的防盗链可以用来做这个,不过这个一般用于下载那种文件。例如,从网页下载时,服务器为用户生成一个加密的URL,该URL有一个过期时间。防止这个网址被多次分享,但是对于普通的素材加载,还是可以使用普通的防盗链。3.5http_sub_module替换响应给用户的内容。与sed相比,它返回??得更晚。例如,需要临时全局修改网站背景或标题时,可以一次性处理。4.扩展项目简单介绍一下两个著名的基于nginx的扩展项目,网上也有很多地方用到。4.1openresty集成了lua脚本,几乎可以满足所有常见的web相关需求。例如,URL加密用于防止劫持和盗链。服务器动态生成一串指向CDN的AES加密URL。CDN的openresty解密后,用正常的URL转发给后端,然后将正确的内容返回给用户。4.2tengine淘宝nginx修改版实现了nginx的很多收费功能或者特殊功能,比如动态加载,concat合并请求,动态分析等,我们python开发的后台基本都是用这个版本,主要是利用concat的功能来实现合并材料。5.结语Nginx是一个非常实用的软件。有些功能已经超越了普通的web服务定位。同时具有开源、轻量、自动化等特点,可以有效解决实际工作中很多特殊场景的需求。祝Nginx全球份额不断攀升~