文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

记一次生产环境大面积404问题!

2024-12-03 10:08

关注

作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:https://github.com/sunshinelyz/mykit-delay

写在前面

发布到线上的接口服务一直好端端的,今天突然运营反馈说很多功能无法正常使用。经过排查,发现前端调用后端接口时,部分接口出现404的现象。今天,我到公司比较晚,肯定是哪个小伙伴昨晚下班,走出办公室前没有祈祷服务器不要出问题。要把这个人揪出来,吊在服务器上——祭天!

文章已收录到:

https://github.com/sunshinelyz/technology-binghe

https://gitee.com/binghe001/technology-binghe

问题复现

得知运营的反馈后,我迅速登录服务器排查问题。首先,查看了接口服务的启动进程正常。验证接口服务的ip和端口是否正常,结果也是没啥问题。接下来,通过Nginx转发请求,此时出现了问题,无法访问接口。同时Nginx的access.log文件中输出了如下日志信息。

  1. 192.168.175.120 - - [26/Feb/2021:21:34:21 +0800] "GET /third/system/base/thirdapp/get_detail HTTP/1.1" 404 0 "http://192.168.175.100/api/index.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 
  2. 192.168.175.120 - - [26/Feb/2021:21:34:22 +0800] "GET /third/system/base/thirdapp/get_detail HTTP/1.1" 404 0 "http://192.168.175.100/api/index.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 
  3. 192.168.175.120 - - [26/Feb/2021:21:34:26 +0800] "GET /third/system/base/thirdapp/get_detail HTTP/1.1" 404 0 "http://192.168.175.100/api/index.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 

此时,从Nginx日志中发现,输出的状态为404,未找到后端的接口服务。为了进一步定位问题,我直接在线上环境通过curl命令的方式来访问接口服务,结果是正常的。

经过这一系列的操作之后,我们就可以确定问题是出在Nginx上了。

问题分析

Nginx开启debug模块

既然已经定位到问题了,那我们接下来就要分析下产生问题的具体原因了。既然是Nginx的问题,我第一时间想到的就是调试Nginx查找错误原因。于是我在服务器命令行输入了如下命令来查看安装Nginx时的配置情况。

  1. nginx -V 

注意:这里已经为Nginx配置了系统环境变量,如果没有配置系统环境变量,则需要输入nginx命令所在目录的完整路径,例如:

  1. /usr/local/nginx/sbin/nginx -v 

命令行输出了如下信息。

  1. configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --add-module=/usr/local/src/fastdfs/fastdfs-nginx-module-1.22/src --with-openssl=/usr/local/src/openssl-1.0.2s --with-pcre=/usr/local/src/pcre-8.43 --with-zlib=/usr/local/src/zlib-1.2.11 --with-http_ssl_module 

可以看到,安装Nginx时没有配置Nginx的debug模块。

于是我在服务器上找到了Nginx的安装文件,在命令行输入如下命令重新编译Nginx。

  1. cd /usr/local/src/nginx/  #进入Nginx的安装文件根目录 
  2. make clean                #清除编译信息 
  3. ./configuration --prefix=/usr/local/nginx-1.17.8 --with-http_stub_status_module --add-module=/usr/local/src/fastdfs/fastdfs-nginx-module-1.22/src --with-openssl=/usr/local/src/openssl-1.0.2s --with-pcre=/usr/local/src/pcre-8.43 --with-zlib=/usr/local/src/zlib-1.2.11 --with-http_ssl_module --with-debug  #设置编译Nginx的配置信息 
  4. make     #编译Nginx,切记不要输入make install 

上述命令中,切记不要输入make install 进行安装。

执行完 make 命令后,会在当前目录的objs目录下生成nginx命令,此时我们需要先停止Nginx服务,备份/usr/local/nginx/sbin/目录下的nginx命令,然后将objs目录下的nginx命令复制到/usr/local/nginx/sbin/目录下,然后启动Nginx服务。

  1. nginx_service.sh stop   #通过脚本停止Nginx服务 
  2. mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak #备份原有nginx命令 
  3. cp ./objs/nginx /usr/local/nginx/sbin/nginx #复制nginx命令 
  4. nginx_service.sh start #通过脚本启动Nginx服务 

注意:这里,在停止Nginx服务前,已经将此Nginx从接入层网关中移除了,所以不会影响线上环境。为了避免使用新编译的nginx命令重启Nginx出现问题,这里通过脚本先停止Nginx服务,然后复制nginx命令后,再启动Nginx服务。

配置Nginx输出debug日志

在Nginx的nginx.conf文件中配置如下信息。

  1. error_log  logs/error.log debug; 

此时,开启了Nginx的debug日志功能,并将debug信息输出到error.log文件中。

分析问题

接下来,在服务器命令行输入如下命令监听error.log文件的输出日志。

  1. tail -F /usr/local/nginx/logs/error.log 

然后模拟访问http接口,可以看到error.log文件中输出如下信息。

  1. 2021/02/26 21:34:26 [debug] 31486#0: *56 http request line: "GET /third/system/base/thirdapp/get_detail HTTP/1.1" 
  2. 2021/02/26 21:34:26 [debug] 31486#0: *56 http uri: "/third/system/base/thirdapp/get_detail" 
  3. 2021/02/26 21:34:26 [debug] 31486#0: *56 http args: "" 
  4. 2021/02/26 21:34:26 [debug] 31486#0: *56 http exten: "" 
  5. 2021/02/26 21:34:26 [debug] 31486#0: *56 posix_memalign: 0000000000FF6450:4096 @16 
  6. 2021/02/26 21:34:26 [debug] 31486#0: *56 http process request header line 
  7. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header: "Host: 10.31.5.66" 
  8. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header: "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 
  9. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header: "Accept: */*" 
  10. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header: "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2" 
  11. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header: "Accept-Encoding: gzip, deflate" 
  12. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header: "Referer: http://192.168.175.100/api/index.html" 
  13. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header: "Connection: keep-alive" 
  14. 2021/02/26 21:34:26 [debug] 31486#0: *56 http header done 
  15. 2021/02/26 21:34:26 [debug] 31486#0: *56 rewrite phase: 0 
  16. 2021/02/26 21:34:26 [debug] 31486#0: *56 test location: "/" 
  17. 2021/02/26 21:34:26 [debug] 31486#0: *56 test location: "file/" 
  18. 2021/02/26 21:34:26 [debug] 31486#0: *56 test location: ~ "/base" 
  19. 2021/02/26 21:34:26 [debug] 31486#0: *56 using configuration "/base" 

从上面的输出日志中,我们可以看到:访问的接口地址为“/third/system/base/thirdapp/get_detail”,如下所示。

  1. 2021/02/26 21:34:26 [debug] 31486#0: *56 http uri: "/third/system/base/thirdapp/get_detail" 

Nginx在进行转发时,分别匹配了“/”,“file/”,“~/base”,最终将请求转发到了“/base”,如下所示。

  1. 2021/02/26 21:34:26 [debug] 31486#0: *56 test location: "/" 
  2. 2021/02/26 21:34:26 [debug] 31486#0: *56 test location: "file/" 
  3. 2021/02/26 21:34:26 [debug] 31486#0: *56 test location: ~ "/base" 
  4. 2021/02/26 21:34:26 [debug] 31486#0: *56 using configuration "/base" 

我们再来看看Nginx的配置,打开nginx.conf文件,找到下面的配置。

  1. location ~/base { 
  2.   proxy_pass                  http://base; 
  3.   proxy_set_header Host $host:$server_port; 
  4. location ~/third { 
  5.   proxy_pass                  http://third; 
  6.   proxy_set_header Host $host:$server_port; 

那么问题来了,访问的接口明明是“/third/system/base/thirdapp/get_detail”,为啥会走到“/base”下面呢?

说到这里,相信细心的小伙伴已经发现问题了,没错,又是运维的锅!!

解决问题

看了Nginx的配置后,相信很多小伙伴应该都知道如何解决问题了,没错那就是把nginx.conf中的如下配置。

  1. location ~/base { 
  2.   proxy_pass                  http://base; 
  3.   proxy_set_header Host $host:$server_port; 
  4. location ~/third { 
  5.   proxy_pass                  http://third; 
  6.   proxy_set_header Host $host:$server_port; 

修改为如下所示。

  1. location /base { 
  2.   proxy_pass                  http://base; 
  3.   proxy_set_header Host $host:$server_port; 
  4. location /third { 
  5.   proxy_pass                  http://third; 
  6.   proxy_set_header Host $host:$server_port; 

去掉“~”符号即可。

接下来,再次模拟访问http接口,能够正常访问接口。

接下来,将Nginx的debug功能关闭,也就是将nginx.conf文件中的 error_log logs/error.log debug; 配置注释掉,如下所示。

  1. # error_log  logs/error.log debug; 

重新加载nginx.conf文件。

  1. nginx_service.sh reload 

最终,将Nginx加入到接入层网关,问题解决。

科普Nginx的转发规则

Nginx的location语法

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

示例1:

  1. location  / { } 

匹配任意请求

示例2:

  1. location ~* .(gif|jpg|jpeg)$ { 
  2.     rewrite .(gif|jpg|jpeg)$ /logo.png; 
  3. } 

不区分大小写匹配任何以gif、jpg、jpeg结尾的请求,并将该请求重定向到 /logo.png请求

示例3:

  1. location ~ ^.+\.txt$ { 
  2.     root /usr/local/nginx/html/; 

区分大小写匹配以.txt结尾的请求,并设置此location的路径是/usr/local/nginx/html/。也就是以.txt结尾的请求将访问/usr/local/nginx/html/ 路径下的txt文件

alias与root的区别

示例如下:

  1. location ^~ /binghe/ {   
  2.    alias /usr/local/nginx/html/binghetic/;   
  1. location ^~ /binghe/ {   
  2.    root /usr/local/nginx/html/;   

last 和 break关键字的区别

(1)last 和 break 当出现在location 之外时,两者的作用是一致的没有任何差异

(2)last 和 break 当出现在location 内部时:

permanent 和 redirect关键字的区别

综合实例

将符合某个正则表达式的URL重定向到一个固定页面

比如:我们需要将符合“/test/(\d+)/[\w-.]+” 这个正则表达式的URL重定向到一个固定的页面。符合这个正则表达式的页面可能是:http://test.com/test/12345/abc122.html、http://test.com/test/456/11111cccc.js等

从上面的介绍可以看出,这里可以使用rewrite重定向或者alias关键字来达到我们的目的。因此,这里可以这样做:

(1)使用rewrite关键字

  1. location ~ ^.+\.txt$ { 
  2.     root /usr/local/nginx/html/; 
  3. location ~* ^/test/(\d+)/[\w-\.]+$ { 
  4.     rewrite ^/test/(\d+)/[\w-\.]+$ /testpage.txt last

这里将所有符合条件的URL(PS:不区分大小写)都重定向到/testpage.txt请求,也就是 /usr/local/nginx/html/testpage.txt 文件

(2)使用alias关键字

  1. location ~* ^/test/(\d+)/[\w-\.]+$ { 
  2.     alias /usr/local/nginx/html/binghetic/binghe1.html; 

这里将所有符合条件的URL(不区分大小写)都重定向到/usr/local/nginx/html/binghetic/binghe1.html 文件

本文转载自微信公众号「冰河技术」,可以通过以下二维码关注。转载本文请联系冰河技术公众号。

 

来源:冰河技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯