Nginx几乎是当下绝大多数公司在用的web应用服务,熟悉Nginx的配置,对于咱们平常的运维工做是相当重要的,下面就Nginx的location配置进行梳理:php
1)location匹配的是nginx的哪一个变量?css
$request_uri
2)location的匹配种类有哪些?html
格式:location [ 空格 | = | ~ | ~* | !~ | !~* | @ ] /uri/ {} 解释: = 表示精确匹配,若是找到,当即中止搜索并当即处理此请求。 ~ 表示执行一个正则匹配,区分大小写匹配 ~* 表示执行一个正则匹配,不区分大小写匹配 !~ 区分大小写不匹配 !~* 不区分大小写不匹配 ^~ 即表示只匹配普通字符(空格)。使用前缀匹配,^表示“非”,即不查询正则表达式。若是匹配成功,则再也不匹配其余location。 @ 指定一个命名的location,通常只用于内部重定向请求。例如 error_page, try_files / 表示通用匹配,任何请求都会匹配到 ------------------------------------------------------------------------ 对应示例说明: 1)= server { server_name wangshibo.com; location = /abcd { […] } } 匹配状况: http://wangshibo.com/abcd # 正好彻底匹配 http://wangshibo.com/ABCD # 若是运行 Nginx server 的系统自己对大小写不敏感,好比 Windows ,那么也匹配 http://wangshibo.com/abcd?param1?m2 # 忽略查询串参数(query string arguments),这里就是 /abcd 后面的 ?param1?m2 http://wangshibo.com/abcd/ # 不匹配,由于末尾存在反斜杠(trailing slash),Nginx 不认为这种状况是彻底匹配 http://wangshibo.com/abcde # 不匹配,由于不是彻底匹配 2)(None) 能够不写 location modifier ,Nginx 仍然能去匹配 pattern 。这种状况下,匹配那些以指定的 patern 开头的 URI,注意这里的 URI 只能是普通字符串,不能使用正则表达式。 server { server_name website.com; location /abcd { […] } } 匹配状况: http://wangshibo.com/abcd # 正好彻底匹配 http://wangshibo.com/ABCD # 若是运行 Nginx server 的系统自己对大小写不敏感,好比 Windows ,那么也匹配 http://wangshibo.com/abcd?param1?m2 # 忽略查询串参数(query string arguments),这里就是 /abcd 后面的 ?param1?m2 http://wangshibo.com/abcd/ # 末尾存在反斜杠(trailing slash)也属于匹配范围内 http://wangshibo.com/abcde # 仍然匹配,由于 URI 是以 pattern 开头的 3)~ 这个 location modifier 对大小写敏感,且 pattern 须是正则表达式 server { server_name wangshibo.com; location ~ ^/abcd$ { […] } } 匹配状况: http://wangshibo.com/abcd # 彻底匹配 http://wangshibo.com/ABCD # 不匹配,~ 对大小写是敏感的 http://wangshibo.com/abcd?param1?m2 # 忽略查询串参数(query string arguments),这里就是 /abcd 后面的 ?param1?m2 http://wangshibo.com/abcd/ # 不匹配,由于末尾存在反斜杠(trailing slash),并不匹配正则表达式 ^/abcd$ http://wangshibo.com/abcde # 不匹配正则表达式 ^/abcd$ 注意:对于一些对大小写不敏感的系统,好比 Windows ,~ 和 ~* 都是不起做用的,这主要是操做系统的缘由。 4)~* 与 ~ 相似,但这个 location modifier 不区分大小写,pattern 须是正则表达式 server { server_name website.com; location ~* ^/abcd$ { […] } } 匹配状况: http://wangshibo.com/abcd # 彻底匹配 http://wangshibo.com/ABCD # 匹配,这就是它不区分大小写的特性 http://wangshibo.com/abcd?param1?m2 # 忽略查询串参数(query string arguments),这里就是 /abcd 后面的 ?param1?m2 http://wangshibo.com/abcd/ # 不匹配,由于末尾存在反斜杠(trailing slash),并不匹配正则表达式 ^/abcd$ http://wangshibo.com/abcde # 不匹配正则表达式 ^/abcd$ 5)^~ 匹配状况相似 2. (None) 的状况,以指定匹配模式开头的 URI 被匹配,不一样的是,一旦匹配成功,那么 Nginx 就中止去寻找其余的 Location 块进行匹配了(与 Location 匹配顺序有关) 6. @ 用于定义一个 Location块,且该块不能被外部Client 所访问,只能被Nginx内部配置指令所访问,好比try_files 或 error_page location @resize { rewrite ^/(.*)/cache/(.*)?(.*)$ /resize.php?dir=$1&path=$2$3; rewrite ^/(.*)/orgi/cert/(.*)?(.*)$ /pass/resize?dir=$1&type=cert&path=$2$3&is_orgi=true; rewrite ^/(.*)/orgi/card/(.*)?(.*)$ /pass/resize?dir=$1&type=card&path=$2$3&is_orgi=true; rewrite ^/(.*)/orgi/(.*)/(.*)?(.*)$ /pass/resize?dir=$1&type=$2&path=$3$4&is_orgi=true; include fastcgi_params; }
以下示例:nginx
#通用匹配 location / { root /var/www/web/; autoindex on; autoindex_exact_size off; autoindex_localtime on; access_log /var/www/log/nginx/access.log; error_log /var/www/log/nginx/error.log; } #正则匹配 #proxy the php scripts to php-fpm location ~ \.php(.*)$ { root /var/www/web/; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; include fastcgi_params; fastcgi_read_timeout 300; } #精确匹配 location = /hello.php { root /var/www/web/; rewrite ^(.*)$ http://www.wangshibo.com redirect; } 产生的效果以下: 访问根目录/,匹配到location / 访问除hello.php以外的其它php程序,匹配到location ~ \.php$,而且用php5-fpm去运行 访问hello.php,匹配到location = /hello.php,访问被重定向到http://www.wangshibo.com
3)location搜索优先级顺序如何?web
精确匹配 > 字符串匹配( 长 > 短 [ 注: ^~ 匹配则中止匹配 ]) > 正则匹配( 上 > 下 ) ========================================================================================================================== 在nginx的location和配置中location的顺序没有太大关系。正location表达式的类型有关。 相同类型的表达式,字符串长的会优先匹配。 优先级排列(下面是在location匹配的内容是同样长度的path内容的状况下,好比匹配的path都是images的状况下): 1)等号类型(=)的精确匹配优先级最高,精确匹配只能命中一个。一旦匹配成功,则再也不查找其余匹配项。 2)^~类型表达式,即字符串匹配,使用匹配最长的最为匹配结果。一旦匹配成功,则再也不查找其余匹配项。 3)正则表达式类型(~ ~*)的优先级次之。若是有多个location的正则能匹配的话,则使用正则表达式最长的那个。 4)常规字符串匹配类型。按前缀匹配。 特别注意: 字符串匹配优先搜索,可是只是记录下最长的匹配 (若是 ^~ 是最长的匹配,则会直接命中,中止搜索正则),而后继续搜索正则匹配, 若是有正则匹配,则命中正则匹配,若是没有正则匹配,则命中最长的字符串匹配. -------------------------------------------------------------------------------------- 结论: 去分和不区分大小写的正则匹配优先级相同,以前后顺序来决定匹配哪个. =的优先级比~高 =的优先级比 ^~高 ^~的优先级比~高 ^~优先匹配的是从根开始的匹配 不加的优先级比~低 ~与*~正则匹配的优先级按前后次序来决定的 -------------------------------------------------------------------------------------- 即nginx匹配的优先级顺序为: [不加] < [~/~*] < [^~] < [=] -------------------------------------------------------------------------------------- 下面经过示例进行验证: 1)先来测试下区分大小写和不区分大小写的优先级.以下: location ~ /5b.txt { return 501; } location ~* /5b.txt { return 504; } 测试结果为: http://192.168.1.80/5b.txt ------------501 http://192.168.1.80/5B.txt ------------504 将顺序反下,将~*放前面 location ~* /5b.txt { return 501; } location ~ /5b.txt { return 504; } 测试结果为: http://192.168.1.80/5b.txt ------------501 http://192.168.1.80/5B.txt ------------501 结论: 去分和不区分大小写的正则匹配优先级相同,以前后顺序来决定匹配哪个. 2)再来比较=与~的优先级 location = /5b.txt { return 502; } location ~ /5b.txt { return 504; } 测试结果为: http://192.168.1.80/5b.txt -------------502 结论:=的优先级比~高 3)再来比较下 ^~ 与 ~的优先级 location ~ /5b.txt { return 502; } location ^~ /5b.txt { return 504; } 测试结果为: http://192.168.1.80/5b.txt --------------504 结论:^~的优先级比~高 4)再测试 ^~ 与 = 的优先级 location ^~ /5b.txt { return 502; } location = /5b.txt { return 504; } 测试结果: http://192.168.1.80/5b.txt --------------504 结论:=的优先级比 ^~高 5)再来测试^~同级之间的优先级 location ^~ 5b.txt { return 502; } location ^~ /5b.txt/ { return 504; } 测试结果: http://192.168.1.80/5b.txt --------------504 结论 :^~优先匹配的是从根开始的匹配 6)再来看空格(即什么都不加)与~的优先级比较 location /5b.txt { return 502; } location ~ /5b.txt { return 504; } 测试结果为: http://192.168.1.80/5b.txt --------------504 结论:空格的优先级比~低 优先级排序为: 空格(即不加) ~与*~正则匹配的优先级按前后次序来决定的 ^~同级之间的匹配是按照根目录顺序来的 ------------------------------------------------------------------------------------------ 再来看看下面的例子 (这里为了方面测试内容输出,使用了echo-nginx-module): 1)精确匹配,即“=” location = /images/test.png { echo 'config1'; } location /images/test.png { echo 'config2'; } location \/images\/test\.png$ { echo 'config3'; } 若是此时请求 http://127.0.0.1/images/test.png 输出的内容是config1, 毋容置疑,精确匹配优先级最高! 2)精确匹配的特殊状况 location = / { index index.html; } location / { echo 'config2'; } 此时输入http://127.0.0.1 输出的内容是config2, 怎么精确匹配的优先级不灵了呢? 是这样的,精确匹配仍是起做用了,请求目录(非具体文件),nginx会将请求内部定向到index文件, 既此时真正的请求是http://127.0.0.1/index.html, 这是config2则被命中! 因此精确匹配不要用来匹配/ 3)字符串搜索与正则搜索 location /images/test.png { echo 'config1'; } location ^~ /images/ { echo 'config2'; } location ~ \/images\/test\.png$ { echo 'config3'; } location ~ \/images\/ { echo 'config4'; } 若是此时请求http://127.0.0.1/images/test.png 输出的内容是config3,正则命中。 (虽然config1为最长匹配的字符串,此时只作记录,后面还要搜索正则匹配,则config3正则匹配命中), 仔细观察能够发现config4也被匹配成功了,可是正则的匹配顺序是按照location的定义顺序匹配的,因此config3命中(注意示例中带了"\"的正则的转义符). 4)字符串匹配优先级的提高( ^~ ) location /images/ { echo 'config1'; } location ^~ /images/test.png { echo 'config2'; } location ~ /images/test\.png$ { echo 'config3'; } location ~ \/images\/ { echo 'config4'; } 若是此时请求 http://127.0.0.1/images/test.png 输出的内容是config2, 首部匹配命中。 (由于字符串匹配是优先搜索的,此时发现config2 为最长的字符串匹配且为^~匹配方式,因此中止搜索正则,直接命中!) 因此这里的 ^~ 符号比较特殊,就是为了提升字符串匹配的优先级,优先于正则匹配. ------------------------------------------------------------------ / 通用匹配,任何请求都会匹配到。 多个location配置的状况下,须要遵循: 首先匹配= 其次匹配^~ 再其次按照配置文件的顺序进行正则匹配、 最后是交给/进行通用匹配 注意:当有匹配成功时,马上中止匹配,按照当前匹配规则处理请求 看看下面匹配规则: #规则A location = / { } #规则B location = /login { } #规则C location ^~ /static/ { } #规则D location ~ \.(gif|jpg|png|js|css)$ { } #规则E location ~* \.png$ { } #规则F location !~ \.xhtml$ { } #规则G location !~* \.xhtml$ { } #规则H location / { } 那么产生的效果以下: 1)访问根目录/, 好比http://localhost/ 将匹配规则A 2)访问 http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H 3)访问 http://localhost/static/a.html 将匹配规则C 4)访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,可是规则D顺序优先,规则E不起做用,而 http://localhost/static/c.png 则优先匹配到规则C 5)访问 http://localhost/a.PNG 则匹配规则E,而不会匹配规则D,由于规则E不区分大小写。 6)访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,由于不区分大小写。规则F,规则G属于排除法,符合匹配规则可是不会匹配到,因此想一想看实际应用中哪里会用到。 7)访问 http://localhost/category/id/1111 则最终匹配到规则H,由于以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,好比FastCGI(php),tomcat(jsp),nginx做为方向代理服务器存在。 注意:在实际使用中,至少清楚下面匹配规则 1)直接匹配网站根,经过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。 2)这里是直接转发给后端应用服务器了,也能够是一个静态首页 第一个必选规则: location = / { proxy_pass http://tomcat:8080/index } 第二个必选规则是处理静态文件请求,这是nginx做为http服务器的强项 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用 location ^~ /static/ { root /webroot/static/; } location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ { root /webroot/res/; } 第三个规则就是通用规则,用来转发动态请求到后端应用服务器 非静态文件请求就默认是动态请求,本身根据实际把握 毕竟目前的一些框架的流行,带.php,.jsp后缀的状况不多了 location / { proxy_pass http://tomcat:8080/ }
看看下面几个设置正则表达式
# 重写跳转 rewrite "^/conference/([^/]+)$" /con_detail.php?con_title=$1 last; rewrite "^/conference/([^/]+)/$" /con_detail.php?con_title=$1 last; #屏蔽爬虫 if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot") { return 403; } #favicon.ico不用打日志 location = /favicon.ico { log_not_found off; access_log off; } #不容许访问隐藏文件 location ~ /\. { deny all; access_log off; log_not_found off; } #访问图片,flash文件等不用打日志 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 7d; #文件返回的过时时间是7天 access_log off; } #访问js和css文件不用打日志 location ~ .*\.(js|css)?$ { expires 1d; #文件返回的过时时间是1天 access_log off; } #设置php-cgi location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; #拦截不存在的php页面请求 if (!-f $document_root$fastcgi_script_name) { return 404; } }