问题

通过浏览器访问服务器时,图片显示的非常慢,在浏览器中都无法完全加载出来。下载文件时,文件根本就无法完全下载下来。

问题定位

经过排查,最终定位到是Nginx的问题。访问大图片请求时,Nginx日志出如下错误信息:

[error] 28423#0: *5 connect() failed (111: Connection refused) while connecting to upstream

基本确定是Nginx的配置问题。

当下载大的附件,或是页面中有大图片时,就会下载中断或是图片无法显示。如果没发生,那是因为没有大文件,或没有大到使用Nginx的默认配置加载不出来。

Nginx的配置实例如下:

location /file {
  root /home/file;
  index index.html index.htm;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Host $host;
  proxy_pass http://127.0.0.1:8080 ;
  client_max_body_size  100m;
  client_body_buffer_size 128k;
  proxy_connect_timeout 600;
  proxy_read_timeout  600;
  proxy_send_timeout  600;
  proxy_buffer_size  32k;
  proxy_buffers   4 64k;
  proxy_busy_buffers_size 64k;
  proxy_temp_file_write_size 64k;
}

其中几个重要的参数如下所示。

  • proxy_connect_timeout 600; :nginx跟后端服务器连接超时时间(代理连接超时)
  • proxy_read_timeout 600; :连接成功后,后端服务器响应时间(代理接收超时)
  • proxy_send_timeout 600; :后端服务器数据回传时间(代理发送超时)
  • proxy_buffer_size 32k; :设置代理服务器(nginx)保存用户头信息的缓冲区大小
  • proxy_buffers 4 32k; :proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
  • proxy_busy_buffers_size 64k; :高负荷下缓冲大小(proxy_buffers*2)
  • proxy_temp_file_write_size 16k; :设定缓存文件夹大小,大于这个值,将从upstream服务器传。

问题出现在Nginx下面的配置:

proxy_temp_file_write_size 16k;

而服务器上的图片基本都在100K~5M之间。

问题就出在proxy_temp_file_write_size上,当服务器上的文件超过该参数设置的大小时,Nginx会先将文件写入临时目录(缺省为Nginx安装目下/proxy_temp目录),缺省Nginx是以nobody身份启动的。

用ls -al 命令查看proxy_temp目录nobody是proxy_temp目录的所有者,没权限。再查看proxy_temp的父目录即Nginx安装目录。发现nobody没权限,怪不得会出现上面的问题。

解决问题

定位到问题,可以使用两种方式解决这个问题,如下所示。

  • 设置任何人都可以写 proxy_temp目录,重启 Nginx 即可解决。
  • 直接更改proxy_temp_file_write_size的值,将其修改为大于图片和文件的大小,重启Nginx。

如果是以第一种方式解决问题的话,比如我的proxy_temp目录是/usr/local/nginx/proxy_temp,用如下命令将/usr/local/nginx/proxy_temp目录设置为任何人都可以写,问题解决。

chmod -R 777 /usr/local/nginx/proxy_temp/ 

如果是使用第二种方式,修改nginx.conf文件,如下所示。

location /file {
	 root /home/file;
	 index index.html index.htm;
	 proxy_set_header X-Real-IP $remote_addr;
	 proxy_set_header Host $host;
	 proxy_pass http://127.0.0.1:8080 ;
	 client_max_body_size  100m;
	 client_body_buffer_size 256k;
	 proxy_connect_timeout 1200;
	 proxy_read_timeout  1200;
	 proxy_send_timeout  6000;
	 proxy_buffer_size  32k;
	 proxy_buffers   4 64k;
	 proxy_busy_buffers_size 128k;
	 proxy_temp_file_write_size 10m;
}

至此,关于nginx图片显示过慢问题的解决完毕。

图片过大加载慢解决方法汇总

1)判断用户的设备(主要用在移动端)、网络等,分别加载不同质量的图片(例如高端 iPhone wifi 情况下,就可以加载双倍高清图等,蜂窝网络下面,就加载个单倍或者有损压缩过的)。或者先加载低质量的图片,让浏览者可以看到,然后再在后台加载更高清的,等加载完了,浏览者还在观看,就插入替换掉。或者先加载低质量小图片列表,然后让用户点击,触发类似 fancybox 的效果,弹窗出现大图片。或者利用资源预加载(三个 HTML5 不常见特性简介)当用户还没打开的时候,就开始加载。还有好多思路,后面想到再补充。

2)压缩,预加载,缓存,图床。

3)使用缓存、使用CDN加速、使用jq延迟加载图片、加大服务器宽带、检查服务器硬盘读取速度。

4)要尽可能的压缩,看用户的忍受程度。jpg 可以用很多方法压缩,png 推荐使用 工具(不过正文图片,显然要选择 jpg 格式的)。



nginx解决图片显示过慢,下载不完全的问题插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.choupangxia.com/2022/12/27/nginx-load-images/