首页 > 技术文章 > nginx资源404问题排查

precedeforetime 2021-07-01 10:01 原文

这篇文章本意是写给我司现场技术支持的同事的,顺手就放上来了。

背景

​ 生产环境经常会出现图片访问不到的情况,大部分是由于nginx配置或者说路径指向不对导致的。

​ 本文档仅针对网络正常图片存在的情况,如果说是网络故障(ping不通图片服务器或者说nginx端口未打开)那肯定优先排查网络相关问题;如果说图片根本不存在,那么只能从图片生成的角度去排查问题。

nginx 简介

​ nginx服务器是一个高性能的http服务器,目前市面上大部分的静态资源(例如图片,html文件等)访问都是通过nginx服务器实现的,下文的图片无法访问的排查流程同样适用于其他通过nginx访问的静态资源。简单来说nginx服务器的作用就是将url转换为对应服务器上的一个具体的文件路径,如果url转换后的路径和实际的资源路径不匹配,那么就会发生无法访问对应资源的情况(例如图片裂图,或者直接页面报错404)。

​ nginx也可以作为反向代理服务器,但与本文无关,不作展开。

解决方法

​ 本文接下来会详细讲解在nginx配置文件中通过root或alias关键字修改路径指向配置软链接两种方式来解决问题,这两种方式比较轻量,当然暴力的将具体资源移动到url对应的路径下也可以解决问题,但生产环境一般没有这么理想,所以暂不讨论。

​ nginx配置文件指nginx.conf,一般放在/etc/nginx/nginx.conf,如果没有可以通过find命令查找。

​ 软链接是指linux系统中的一种符号链接,这个文件包含了另一个文件的路径名。可以理解为windows系统中的快捷方式,例如我们在桌面上建立了一个快捷方式,就可以直接通过这个快捷方式进入对应的文件夹,在linux中作用同理,用软链接可以让我们在不移动具体文件资源的情况下,让nginx获得正确的路径指向。

​ 抛开root和alias两个关键字可以实现路径转换,nginx还支持其他更高级的路径转换操作,例如rewrite,本文同样不讨论,有兴趣自行了解。

排查思路

​ 当出现图片无法访问的情况,首先应拿到对应图片的url(可以通过在浏览器页面上点击右键选择检查或者直接复制图片地址),然后再对比图片在服务器存放的实际位置,根据二者的差异选择不同的解决办法。

判断ip和端口是否指向正确

​ 例如图片url为:http://192.168.4.62:50001/ifsrc/engine1/picture/0001/1.jpg,但实际图片存放路径为192.168.4.63服务器上的/picture/0001/1.jpg,那么可以通过nginx配置文件中的proxy_pass配置项解决这个问题。

​ proxy_pass:转发功能,将匹配上的路径转发到指定ip路径。

​ 配置文件如下:

图中表示192.168.4.62的nginx服务器会将http://192.168.4.62:50001/ifsrc/engine1/picture/0001/1.jpg 转换为http://192.168.4.63:80/picture/0001/1.jpg然后自动访问192.168.4.63的nginx服务器。

同时要非常主要图中箭头标注的位置的斜杠,如果不包含斜杠,那么最终的转换结果为http://192.168.4.63:80/ifsrc/engine1/picture/0001/1.jpg

proxy_pass也可以替换路径,有兴趣可以自行了解。

url文件路径和实际路径不符

这种情况解决方法有很多种,比较灵活,本文只介绍配置新的location和软链接两种模式。

配置新的location可以理解为是改变nginx的指向,配置软链接可以理解为是改变了文件的位置。

先简单提一下nginx配置文件,如上图,表示监听192.168.4.62的50001端口,至于location本身支持很多种匹配,详细情况见最后的location关键字详解,此处只讲解location的通用匹配。这里的location /表示默认匹配路径,root /var/www/html表示默认匹配的根路径,例如 http://192.168.4.62/1.jpg,其实际访问的是 /var/www/html/1.jpg这个文件。

比如目前图片的url为http://192.168.4.62:50001/changkou/changkou1/1.jpghttp://192.168.4.62:50001/changkou/changkou2/2.jpg

假设其实际存放的路径如下:

/var
	/www
		/html
			/changkou1
				/1.jpg
			/changkou2
				/2.jpg

如果我们直接拿url去访问,那么其实际访问的地址为/var/www/html/changkou/changkou1/1.jpg/var/www/html/changkou/changkou2/2.jpg,自然会出现404的情况。

修改nginx配置文件

可以通过下图中的两种配置方式来解决。

root或者alias都可以用来配置指向路径,只不过含义有一点区别。

对于root,nginx实际是将root路径 + 匹配的location+匹配的location之后的路径,对于changkou/changkou1/1.jpg这张图片,那么实际nginx访问的路径就是 /var/www/html + /changkou/changkou1 + /1.jpg,与实际文件位置相同,可以正常访问图片。

对于alias,nginx实际是将alias路径 + 匹配的location之后的路径,对于changkou/changkou2/2.jpg这张图片,那么实际nginx访问的路径是/var/www/html/changkou/changkou2/ + 2.jpg。也能达到相同的效果,可以正常访问图片。

配置软链接

同样是上面的问题,如果想要不改nginx配置文件,那么其里面只有一个通用的匹配规则,也就是任何图片都会去/var/www/html/这个目录下面去找,虽然生产环境一般不能直接将文件移动到该位置,但可以通过配置软链接达到相同的效果。

创建软链接的命令为:

sudo ln -s 目标文件夹 软链接名称

在不改变nginx配置文件的前提下,我们可以配置如下软链接

sudo ln -s /var/www/html/ changkou

最终效果为:

经测试图片同样可以正常访问。

在这种情况下,整个图片的访问流程如下

  1. 先根据url http://192.168.4.62:50001/changkou/changkou1/1.jpg,匹配到/var/www/html/changkou/changkou1/1.jpg
  2. 然后去/var/www/html/下面可以找名为 changkou 的软链接或者目录,实际能找到软链接changkou
  3. 最后再根据changkou的软链接定位到/var/www/html/,最后根据changkou1/1.jpg找到具体文件。

nginx配置文件中 location 关键字详解

location 关键字是用来匹配对应的url,以对不同的url进行不同的处理。

location语法规则:

location [=||*|^~] /uri/ { … }

  • = 开头表示精确匹配
  • ^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。以xx开头
  • ~ 开头表示区分大小写的正则匹配 以xx结尾
  • ~* 开头表示不区分大小写的正则匹配 以xx结尾
  • !~!~*分别为区分大小写不匹配及不区分大小写不匹配 的正则
  • / 通用匹配,任何请求都会匹配到。

对于location匹配规则有兴趣可以参考:nginx中location详解 - 苍青浪 - 博客园 (cnblogs.com)

官方文档路径如下:http核心模块-Nginx官方文档

推荐阅读