作者个人研发在高并发场景下提供了一个简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。开源半年多以来,已成功为十几家中小企业提供精准定时调度解决方案,经受住了生产环境的考验。为了造福更多的童鞋,这里放上开源框架的地址:https://github.com/sunshinelyz/mykit-delay网上贴的接口服务一直都不错。今天操作反馈突然说很多功能不能正常使用。使用。经过排查,发现前端调用后端接口时,部分接口出现404现象。今天,我迟到了公司。肯定是昨晚有朋友下班了,下班前没有祈祷服务器没有问题。找出这个人,挂在服务器上——劫天!文章已收录于:https://github.com/sunshinelyz/technology-binghehttps://gitee.com/binghe001/technology-binghe问题重现收到运营反馈后,赶紧登录服务器排查问题。首先检查接口服务的启动过程是否正常。验证接口服务的ip和端口是否正常,结果没有问题。接下来,通过Nginx转发请求。这时候出现问题,无法访问接口。同时在Nginx的access.log文件中输出如下日志信息。192.168.175.120--[26/Feb/2021:21:34:21+0800]"GET/third/system/base/thirdapp/get_detailHTTP/1.1"4040"http://192.168.175.100/api/index.html""Mozilla/5.0(WindowsNT10.0;Win64;x64;rv:85.0)Gecko/20100101Firefox/85.0"192.168.175.120--[26/Feb/2021:21:34:22+0800]"GET/third/system/base/thirdapp/get_detailHTTP/1.1"4040"http://192.168.175.100/api/index.html""Mozilla/5.0(WindowsNT10.0;Win64;x64;rv:85.0)Gecko/20100101Firefox/85.0"192.168。175.120--[26/Feb/2021:21:34:26+0800]"GET/third/system/base/thirdapp/get_detailHTTP/1.1"4040"http://192.168.175.100/api/index.html""Mozilla/5.0(WindowsNT10.0;Win64;x64;rv:85.0)Gecko/20100101Firefox/85.0”此时从Nginx日志中发现输出状态为404,找不到后端接口服务。为了进一步定位问题,我直接在线上环境下通过curl命令访问接口服务,结果正常。经过这一系列的操作,我们可以确定是Nginx的问题。问题分析Nginx开启了debug模块既然问题已经定位到了,那我们接下来分析具体的问题原因。既然是Nginx的问题,首先想到的就是调试Nginx,找出错误的原因。于是在安装Nginx时在服务器命令行输入如下命令查看配置。nginx-V注意:这里已经为Nginx配置了系统环境变量。如果没有配置系统环境变量,需要输入nginx命令所在目录的完整路径,例如:/usr/local/nginx/sbin/nginx-v命令行输出如下信息。配置参数:--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。cd/usr/local/src/nginx/#进入Nginx安装文件根目录makeclean#清除编译信息./configuration--prefix=/usr/local/nginx-1.17.8--with-http_stub_status_module--add-模块=/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的配置信息make#编译Nginx,记得不要进入makeinstall以上命令中,切记不要输入makeinstall进行安装。执行make命令后,会在当前目录的objs目录下生成nginx命令。这时候我们需要先停止Nginx服务,备份/usr/local/nginx/sbin/目录下的nginx命令,然后将objs目录下的nginx命令复制到/usr/local/nginx/sbin/目录,然后启动Nginx服务。nginx_service.shstop#通过脚本停止Nginx服务mv/usr/local/nginx/sbin/nginx/usr/local/nginx/sbin/nginx.bak#备份原来的nginx命令cp./objs/nginx/usr/local/nginx/sbin/nginx#复制nginx命令nginx_service.shstart#通过脚本启动Nginx服务注意:这里,在停止Nginx服务之前,这个Nginx已经从接入层网关移除,所以不会影响线上环境。为了避免新编译的nginx命令重启Nginx出现问题,这里我们先通过脚本停止Nginx服务,然后复制nginx命令,再启动Nginx服务。配置Nginx输出调试日志,在Nginx的nginx.conf文件中配置如下信息。error_loglogs/error.logdebug;此时,Nginx的调试日志功能被开启,调试信息输出到error.log文件中。分析问题接下来在服务器命令行输入如下命令,监控error.log文件的输出日志。tail-F/usr/local/nginx/logs/error.log然后模拟访问http接口,可以在error.log文件中看到如下信息输出。2021/02/2621:34:26[调试]31486#0:*56httprequestline:"GET/third/system/base/thirdapp/get_detailHTTP/1.1"2021/02/2621:34:26[调试]31486#0:*56httpuri:"/third/system/base/thirdapp/get_detail"2021/02/2621:34:26[调试]31486#0:*56httpargs:""2021/02/2621:34:26[调试]31486#0:*56httpexten:""2021/02/2621:34:26[调试]31486#0:*56posix_memalign:0000000000FF6450:4096@162021/02/2621:34:26[调试]31486#0:*56httpprocessrequestheaderline2021/02/2621:34:26[调试]31486#0:*56httpheader:"主机:10.31.5.66"2021/02/2621:34:26[调试]31486#0:*56httpheader:"用户代理:Mozilla/5.0(WindowsNT10.0;Win64;x64;rv:85.0)Gecko/20100101Firefox/85.0"2021/02/2621:34:26[调试]31486#0:*56httpheader:"接受:*/*"2021/02/2621:34:26[debug]31486#0:*56httpheader:"接受语言: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"2021/02/2621:34:26[调试]31486#0:*56httpheader:"接受编码:gzip,deflate"2021/02/2621:34:26[调试]31486#0:*56httpheader:"Referer:http://192.168.175.100/api/index.html"2021/02/2621:34:26[调试]31486#0:*56httpheader:“连接:保持活动”2021/02/2621:34:26[调试]31486#0:*56httpheaderdone2021/02/2621:34:26[调试]31486#0:*56重写阶段:02021/02/2621:34:26[调试]31486#0:*56testlocation:"/"2021/02/2621:34:26[调试]31486#0:*56testlocation:"文件/"2021/02/2621:34:26[debug]31486#0:*56testlocation:~"/base"2021/02/2621:34:26[debug]31486#0:*56usingconfiguration"/base"从上面的输出日志,我们可以看到:访问接口的地址是“/third/system/base/thirdapp/get_detail”,如下图2021/02/2621:34:26[debug]31486#0:*56httpuri:"/third/system/base/thirdapp/get_detail”Nginx在转发时分别匹配了“/”、“file/”、“~/base”,最终将请求转发到“/base”,如下图。2021/02/2621:34:26[调试]31486#0:*56testlocation:"/"2021/02/2621:34:26[调试]31486#0:*56testlocation:"文件/"2021/02/2621:34:26[debug]31486#0:*56testlocation:~"/base"2021/02/2621:34:26[debug]31486#0:*56usingconfiguration"/base"我们再来看看Nginx的配置,打开nginx.conf文件,找到如下配置。location~/base{proxy_passhttp://base;proxy_set_headerHost$host:$server_port;}location~/third{proxy_passhttp://third;proxy_set_headerHost$host:$server_port;}那么问题来了,访问接口明明是"/third/system/base/thirdapp/get_detail”,你为什么在“/base”下面?说到这里,相信细心的小伙伴们已经发现问题了,没错,又是运维的锅!!问题解决看完Nginx的配置,相信很多朋友应该知道如何解决问题了。对,就是在nginx.conf中配置如下。location~/base{proxy_passhttp://base;proxy_set_headerHost$host:$server_port;}location~/third{proxy_passhttp://third;proxy_set_headerHost$host:$server_port;}修改如下图。location/base{proxy_passhttp://base;proxy_set_headerHost$host:$server_port;}location/third{proxy_passhttp://third;proxy_set_headerHost$host:$server_port;}只需删除“~”符号。接下来再次模拟访问http接口,接口可以正常访问了。接下来关闭Nginx的debug功能,即把error_loglogs/error.logdebug注释掉;在nginx.conf文件中配置,如下图。#error_loglogs/error.logdebug;重新加载nginx.conf文件。nginx_service.shreload最后在接入层网关添加Nginx,问题解决。科普Nginx转发规则Nginxlocation语法location[=|~|~*|^~]/uri/{...}=严格匹配。如果请求与该位置匹配,将停止搜索并立即处理请求~区分大小写匹配(正则表达式可用)~*不区分大小写匹配(正则表达式可用)!~区分大小写不匹配!~*不区分大小写不匹配^~如果这个前缀用于正则字符串,它告诉nginx如果路径匹配则不要测试正则表达式示例1:location/{}匹配任何请求示例2:location~*.(gif|jpg|jpeg)${rewrite.(gif|jpg|jpeg)$/logo.png;}不区分大小写地匹配任何以gif、jpg、jpeg结尾的请求,并将请求重定向到/logo.png请求示例3:location~^.+\.txt${root/usr/local/nginx/html/;}区分大小写匹配以.txt结尾的请求,设置该位置的路径为/usr/local/nginx/html/。即以.txt结尾的请求会访问/usr/local/nginx/html/路径下的txt文件。alias和root的区别是实际访问文件路径会和URL中的路径别名拼接。URL中不会拼接实际访问文件路径。路径示例如下:location^~/binghe/{alias/usr/local/nginx/html/binghetic/;}请求:http://test.com/binghe/binghe1.html实际访问:/usr/local/nginx/html/binghetic/binghe1.html文件位置^~/binghe/{root/usr/local/nginx/html/;}请求:http://test.com/binghe/binghe1.html实际访问:/usr/local/nginx/html/binghe/binghe1.html文件中last和break关键字的区别(1)当last和break出现在location外时,两者的功能是一致的,没有任何区别(2)当last和break出现在location内部时:last使用最后一条指令,改写后会跳出location作用域,然后重新开始执行之前的行为break使用break指令,改写后不会跳转超出location范围,它的整个生命周期都在当前location中间。permanent和redirect关键字的区别rewrite…permanent永久重定向,请求日志中的状态码为301rewrite…redirect临时重定向,请求日志中的状态码为302定向到固定页面例如:我们需要重定向将正则表达式“/test/(\d+)/[\w-.]+”匹配到固定页面的URL。匹配这个正则表达式的页面可能是:http://test.com/test/12345/abc122.html、http://test.com/test/456/11111cccc.js等。从中可以看出以上介绍,这里我们可以使用rewrite重定向或者alias关键字来达到我们的目的。因此,这里可以这样做:(1)使用rewrite关键字location~^.+\.txt${root/usr/local/nginx/html/;}location~*^/test/(\d+)/[\w-\.]+${rewrite^/test/(\d+)/[\w-\.]+$/testpage.txtlast;}这里重写所有符合条件的url(PS:不区分大小写)指向/testpage.txt请求,也就是/usr/local/nginx/html/testpage.txt文件(2)使用别名关键字location~*^/test/(\d+)/[\w-\.]+${alias/usr/local/nginx/html/binghetic/binghe1.html;}这里将所有符合条件的URL(不区分大小写)重定向到/usr/local/nginx/html/binghetic/binghe1.html本文转载自微信公众号“银禾科技”,可通过以下二维码关注。转载本文请联系冰川科技公众号。
