• nginx配置遇到的一个大坑


    鄙人负责的项目即将上线,今天团队伙伴反应网站上的图片,有的可以显示有的不可以显示报404,找我看看问题。

    我心想啊,404,应该是没有文件才出的,于是,我直接上nginx服务器上查看,检查路径下是否有相应的文件,文件是存在的。那为何还是报404呢????

    一时间,我也觉得非常的奇怪,这种问题还是头一回呢。。。。

    问题的现象如下图:

    但是,我再136这个服务器上的相关路径下找了文件:

    仅仅这个,大伙可能还觉得不能说明问题,我的nginx配置如下:

     1 。。。。 此前的部分省略了。。。。
     2         location /uploadfiles {
     3              root html/TK_ROOT;
     4              allow all;
     5          }
     6 
     7          #shi suan shihuc added 2017-01-20
     8          rewrite ^/product/src/(.*)$ /pc/src/$1;
     9          rewrite ^/product/dist/(.*)$ /pc/dist/$1;
    10          location ~ /(pc|hera_insure) {
    11              proxy_pass http://10.137.146.93:80;
    12              proxy_set_header Host $host:$server_port;
    13              proxy_set_header Remote_Addr $remote_addr;
    14              proxy_set_header X-Real-IP $remote_addr;
    15              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    16              proxy_intercept_errors on;
    17          }
    18 。。。。此后的部分省略了。。。。

    上面图片报404了,但是在nginx的logs目录下的error.log中却找不到错误记录,这个就是非常奇怪的事情了。。。。

    莫非,莫非这个url的请求没有进入这个服务器的worker进程处理,莫非真是这样,不知道,猜测的,猜测!

    我的配置,关于uploadfiles的目录关系是没有问题的。因为其他的文件显示是正常的,例如下面的:

    我再次测试正常的图片,将图片改一个扩展名(png-》pngx),就上图,效果如下图:

    重点看红框中的nginx版本号信息,这个信息是我找到问题root cause的关键。因为我的nginx系统软件版本就是1.9的,还记得最上面那个图么,错误版本号是1.7

    1 [nginx@t0-xxxxxx-nginx01 sbin]$ sudo ./nginx -V
    2 [sudo] password for nginx:
    3 nginx version: openresty/1.9.3.2
    4 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
    5 built with OpenSSL 1.0.1e-fips 11 Feb 2013
    6 TLS SNI support enabled
    7 configure arguments: --prefix=/u02/nginx//nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.2.19 --add-module=../echo-nginx-module-0.58 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.29 --add-module=../form-input-nginx-module-0.11 --add-module=../encrypted-session-nginx-module-0.04 --add-module=../srcache-nginx-module-0.30 --add-module=../ngx_lua-0.9.19 --add-module=../ngx_lua_upstream-0.04 --add-module=../headers-more-nginx-module-0.28 --add-module=../array-var-nginx-module-0.04 --add-module=../memc-nginx-module-0.16 --add-module=../redis2-nginx-module-0.12 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/u02/nginx/luajit/lib --add-module=/u02/nginx/install/nginx-sticky-module-master --with-http_ssl_module
    8 [nginx@t0-xxxxxx-nginx01 sbin]$

    是不是很神奇,哪里来的版本1.7的nginx呢????

    问题一定出在nginx的配置上了,回到nginx.conf文件,这个1.7的版本,应该来自反向代理服务器。基于这个分析,就想到了反向代理服务的配置,重点在下面的这部分:

    1          location ~ /(pc|hera_insure) {
    2              proxy_pass http://10.137.146.93:80;
    3              proxy_set_header Host $host:$server_port;
    4              proxy_set_header Remote_Addr $remote_addr;
    5              proxy_set_header X-Real-IP $remote_addr;
    6              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    7              proxy_intercept_errors on;
    8          }

    的确,我发现出现错误的图片的名称是以pc字符开头的。。。

    欧了,问题就是发生在这里,在nginx中有这么一个规则,location后面~的优先级高于什么都不写的模式(局部匹配),即location ~ /(pc|hera_insure) 这个匹配规则优先级高于 location /uploadfiles这个规则。

    我们期望URL中以/uploadfiles起始的请求都进入到 location /uploadfiles规则, 以/pc开头或者/hera_insure开头的url请求都进入到location ~ /(pc|hera_insure)规则。所以,就可以解决问题了,只需要将location ~ /(pc|hera_insure)规则修改一下:

    1          location ~ ^/(pc|hera_insure) {
    2              proxy_pass http://10.137.146.93:80;
    3              proxy_set_header Host $host:$server_port;
    4              proxy_set_header Remote_Addr $remote_addr;
    5              proxy_set_header X-Real-IP $remote_addr;
    6              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    7              proxy_intercept_errors on;
    8          }

    主要是加了正则限定,必须以/pc或者/hera_insure开头,才进入反向代理。。。

    好了,修改了nginx.conf的配置,再次访问最开始出问题的图片:

    到此,可以总结一下,这个问题的根本内容其实很简单,就是location匹配规则的应用问题。注意:我的问题中url是比较长的(/uploadfiles/images/productPic/384/pc2b9471e-fe7_150_150.jpg)

    1. location ~ url {...}的优先级高于location url {...}。【局部匹配情况下】

    2. location ~ url {...}是正则匹配,只要url满足正则规则,就会进入相关匹配段。

    3. location    url {...}是起始匹配,只要url的起始部分和location中指定的url匹配,就会进入相关的匹配段。【注意,这个no modifier的规则,url不支持正则表达】

    nginx的官方配置文件,要细读,深入理解,才能避免这些坑啊。下面,附上官方文档中关于nginx搜索匹配的先后顺序:

    The order you established in the configuration file is irrelevant. Nginx will search for matching patterns in a
    specific order:
    1. location blocks with the = modifier: If the specified string exactly matches
    the requested URI, Nginx retains the location block.
    2. location blocks with no modifier: If the specified string exactly matches the
    requested URI, Nginx retains the location block.
    3. location blocks with the ^~ modifier: If the specified string matches the
    beginning of the requested URI, Nginx retains the location block.
    4. location blocks with ~ or ~* modifier: If the regular expression matches the
    requested URI, Nginx retains the location block.
    5. location blocks with no modifier: If the specified string matches the
    beginning of the requested URI, Nginx retains the location block.

    注意理解2,5这两条的差别。就能理解我这个问题的解决思路。

  • 相关阅读:
    EF里如何定制实体的验证规则和实现IObjectWithState接口进行验证以及多个实体的同时验证
    EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态
    使用EF自带的EntityState枚举和自定义枚举实现单个和多个实体的增删改查
    EF里单个实体的增查改删以及主从表关联数据的各种增删改查
    EF和MVC系列文章导航:EF Code First、DbContext、MVC
    EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载
    EF里的继承映射关系TPH、TPT和TPC的讲解以及一些具体的例子
    Git敏捷开发--rebase命令
    浏览器远程编写python代码--jupyter web server
    C++学习--编译优化
  • 原文地址:https://www.cnblogs.com/shihuc/p/6374551.html
Copyright © 2020-2023  润新知