摘要:众所周知,Nginx是目前最流行的Web Server之一,也广泛应用于负载均衡、反向代理等服务,但使用过程中可能因为对Nginx工作原理、变量含义理解错误,或是参数配置不当导致Nginx工作异常。本文介绍的就是福建开机广告Nginx的参数location处理静态文件配置不当引发的nginx日志骤增到14G的问题排期过程。

一、问题现象及系统介绍

现象:12月15日 21:02分,正在外面吃宵夜,手机收到监控平台的一条“服务器磁盘空间<20%”报警短信。

系统介绍:为了看此文的童鞋更好理解我下面介绍的东西,这里我先简单介绍下福建开机广告系统。

整个系统可以分为管理平台与API两个部分:

管理平台完成素材(包括下面提到素材图片名也是有放到缓存里的)、广告、策略、排期制作和下发等工作,提供接口将广告策略、用户分组等信息同步到API;

API向机顶盒/EPG提供广告接口,采集广告请求日志,当STB访问EPG,EPG调用广告请求接口获取广告策略(地区、分组、平台、黑白名单等策略),并在匹配到策略的时候进行展示;

API节点我们是放在其中6台服务器的23个tomcat里面,使用nginx实现负载请求分发;图片服务器我们是放在另外的3台服务器,也是使用的nginx实现的负载请求分发。相信大家对nginx都不陌生,这里我就不在赘述。

二、问题排查过程

2.1 初步分析

判断一:可能是crontab未执行

一看是Nginx所在服务器,初步判断可能是crontab异常,没有定期清除5天以前的日志导致(这里说明下:我们线上的nginx日志是每天凌晨切割access.log日志,然后通过crontab实现只保留最近五天日志)。

2.2 深入分析:

判断二:可能图片同步出问题

回到家,打开SHH客户端 查看/data/nginx_log目录查看,发现access.log只有近五天的日志,「排除原以为是crontab异情况」。

然后发现error_log很大,命令du -h error_log一看都有14G了,tail -200 error_log发现全是“/usr/local/nginx/html/resources/material/img/1511488532192.JPG”图片请求失败的记录,于是赶紧清空error_log,排除短信空间报警。

心想,难道是图片没有同步?

为验证我的猜想,我打开浏览器访问这张图片:http://IP:port/resources/material/img/1511488532192.JPG(上面IP指的是nginx所在服务器IP,port是nginx.conf配置图片分发端口),请求几次返回都是404。

于是切换到主图片服务器查看,发现这张大写图片存在,切换到其他两台从图片服务器,发现也是存在的(这里说明下:我们系统的素材图片都是通过管理平台以接口的形式下发主图片服务器,主图片服务器再通过inotify+sync同步到其他两台从图片服务器),「排除图片同步异常情况」。

判断三:可能是请求不到大写后缀图片导致

因为看到图片服务器目录下,唯有这几张大写后缀图片是请求异常的,那改成小写会怎么样呢?接着改了下三台图片服务器的图片大写后缀为小写后缀。再打开浏览器请求,发现请求正常了,继而判断可能运营人员在管理平台制作广告的时候上传了大写后缀的格式的图片,同步到API和数据库的缓存,那么导致有广告请求的从缓存查询到的图片地址也就是大写的了。

顺着这个思路,我先到登录到数据库改了下素材表图片大写后缀为小写后缀,再登录redis,准备改缓存,info命令一看,傻眼了,136万的key数量,而我又不记得具体广告策略key,

由于没办法查找,那就只能flushall清空缓存,重启ad-cache工程(这里说明下:ad-cache工程的作用主要就是两个,一是把当前符合要求的用户、广告策略等相关信息初始加载到缓存,另一个是启一个定时任务,每小时加载当前时段的策略到缓存),然后在查看tail -f error_log查看日志,发现还在增加之前那种大写后缀图片请求失败的错误,「排除图片后缀大写情况」。

判断四:可能是nginx配置不当导致

这么操作完还是不行,当时着实有点懵逼,我心想当时已经把广告请求所有涉及到会查询图片大写后缀的地方改过来了,为什么还是会有大写后缀图片请求失败的记录?但转念一想会不是nginx的配置有问题?

为验证我的判断,我先sz命令从图片服务器上下载了一张名为“1511488578911.JPG”的大写后缀格式的图片,然后通过管理平台上传这个“1511488578911.JPG”图片素材,发现这张图片是可以预览的。由此更加确信就是nginx某些参数配置不当导致。vim命令查看配置nginx.conf,当定位到图片请求配置这里的时候,

发现location ~是表示区分大小写的,而后面全是配置小写后缀格式,于是加上JPG,使用/usr/local/nginx/sbin/nginx -s reload命令重载nginx的配置,打开浏览器发现可以查看到这张图片了,再切换到nginx日志目录,tail -f error_log,发现日志没有再增加,至此问题终于解决。

三、问题反思

反思一:要做到知其然并且知其所以然

对Nginx工作原理、参数含义理解不深,从而参数配置不当,导致产生nginx日志骤增这种问题产生。

反思二:缺少一个快速定位问题的系统或工具,导致排查的时间比较长。

当时在作出判断三的时候,因为没在公司,不记得广告策略缓存key,导致不得不直接执行flushall命令直接清空缓存,再重新刷入缓存,这样做其实是有风险的,因为把广告策略、用户、分组等信息从缓存清空之后,用户的广告请求只能直接去查询数据库,这样响应的时间肯定会慢了,而且缓存中还存了广告请求的日志记录,直接flushall就会丢失部分的广告请求数据,影响到PV、UV统计。所以当时也是想就是有一个系统,在浏览器直接输入一个用户名或是图片名,就能从数据库和缓存查询到中涉及到相关联的数据,以可视化的形式在页面展示,这样定位问题也就可以更快定位问题了。

四、引申

语法规则: location [=|~|~*|^~] /uri/ { … }

= 开头表示精确匹配

^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。

~ 开头表示区分大小写的正则匹配

~* 开头表示不区分大小写的正则匹配

!~和!~*分别为区分大小写不匹配及不区分大小写不匹配 的正则

/ 通用匹配,任何请求都会匹配到。

多个location配置的情况下匹配顺序为(参考资料而来,还未实际验证,试试就知道了,不必拘泥,仅供参考):

首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

例子,有如下匹配规则:

[plain] view plain copy

location = / {

#规则A

}

location = /login {

#规则B

}

location ^~ /static/ {

#规则C

}

location ~ \.(gif|jpg|png|js|css)$ {

#规则D

}

location ~* \.png$ {

#规则E

}

location !~ \.xhtml$ {

#规则F

}

location !~* \.xhtml$ {

#规则G

}

location / {

#规则H

}

那么产生的效果如下:

访问根目录/, 比如http://localhost/ 将匹配规则A

访问 http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H

访问 http://localhost/static/a.html 将匹配规则C

访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,而 http://localhost/static/c.png 则优先匹配到 规则C

访问 http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写。

访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。

访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。

记一次生产环境Nginx日志骤增的问题排查过程的更多相关文章

  1. 记一次生产环境nginx图片上传不了的问题

    在server节点目录下配置: client_max_body_size 8M; client_body_buffer_size 8M; 不过还是不能上传就执行下面这条命令: cd /var/lib/ ...

  2. Nginx 日志分析及性能排查

    Nginx 日志分析及性能排查 2017-03-04 Linux爱好者 (点击上方公众号,可快速关注) 作者:-外星人- my.oschina.net/362228416/blog/844713 如有 ...

  3. 记一次生产环境thrift服务的配置问题

    问题现象 有客户反馈我们的产品有时反应很慢,处理会出现超时. 问题分析过程 1.第一反应可能是用户增加,并发量太大了,询问了运营,最近用户注册数据并没有猛增. 2.分析access日志,发现有隔一段时 ...

  4. 记一次生产环境axis2服务特别慢的问题。

    情况如下: 某服务,在测试环境测试的时候整个响应过程也就0.5s左右,测试环境和生产环境axis2版本一致,tomcat版本一致,但是生产环境需要差不多20S. 后来,越来越慢,导致服务一起来,整个生 ...

  5. 记一次生产环境tomcat线程数打满情况分析

    前言 旨在分享工作中遇到的各种问题及解决思路与方案,与大家一起学习. -- 学无止境, 加油 ! Just do it ! 问题描述 运行环境描述 tomcat-8.5 单节点(该应用集群20个节点) ...

  6. 生产环境nginx配置文件(带https安全认证)

    #user www www; worker_processes 2; error_log logs/error.log info; pid /usr/local/nginx/nginx.pid; wo ...

  7. 生产环境nginx上传文件报错413 Request Entity Too Large

    修改nginx配置文件/etc/nginx/nginx.conf 在http{}中添加 client_max_body_size 100m; 意思是设置上传文件大小

  8. 记一次生产环境presto删表失败的问题

    场景,开发用java程序连接presto创建一个表,这个表在hdfs的权限为: 然后用presto去删除这个表 报错,没有权限删除,查看上一级目录权限,发现权限正常 直连hive删表 发现正常. 然后 ...

  9. 生产环境-jvm内存溢出-jprofile问题排查

    首先线上开启了dump的参数 dump的内容有2G,先进行压缩打包,传输至本地(scp) tar -czvf dump.tar java_pid4824.hprof  使用Jprofile打开dump ...

随机推荐

  1. 利用可变参数模拟Printf()函数实现一个my_print()函数和调用可变参数注意的陷阱!

    可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 例如,对于函数: void test(char a ...

  2. 通过ELK快速搭建一个你可能需要的集中化日志平台

    在项目初期的时候,大家都是赶着上线,一般来说对日志没有过多的考虑,当然日志量也不大,所以用log4net就够了,随着应用的越来越多,日志散 落在各个服务器的logs文件夹下,确实有点不大方便,这个时候 ...

  3. Spring框架——IOC依赖注入

    本来想把IOC和AOP一起介绍的,但是AOP内容太多了,所以就分开了,最后的结果就是这一篇只剩下一点点了.这不是第一次写关于IOC的文章了,之前写过Java反射,Java注解,也写过通过XML解析实现 ...

  4. 读Kafka Consumer源码

    最近一直在关注阿里的一个开源项目:OpenMessaging OpenMessaging, which includes the establishment of industry guideline ...

  5. 【原创精品】程序员最强大的利器——电子笔记本的思考(1)(ver0.3)

    [原创精品]程序员最强大的利器,本文以下内容全都是作者EverStenis(胡佳吉)的原创,未经授权不得转载,抄袭必究. 我想问大家一个问题,对于我们程序员来说,在我们的武器工具库中,最强大的一件利器 ...

  6. django框架中的中间件

    什么是中间件 中间件就是在url进入路由之前进行检测的一个类 也就是说,每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对 ...

  7. HDU 1394 逆序数 线段树单点跟新 | 暴力

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  8. SVN如何commit(提交)项目代码

    在本地代码做出变更之后,我们就需要通过svn commit命令提交到远程服务端 工具/原料   SVN客户端 方法/步骤   选中需要更新的代码文件夹或目录,点击右键,选择"Tortoise ...

  9. 企业级LNMP架构搭建实例(基于Centos6.x)

    1.1 部署LNMP架构说明 1.1.1 LNMP架构内容 01.部署linux系统 02.部署nginx网站服务 03.部署mysql数据库服务 04.部署php动态解析服务 1.1.2 配置LNM ...

  10. Chrome浏览器读写系统剪切板

    IE浏览器支持直接读写剪切板内容: window.clipboardData.clearData(); window.clipboardData.setData('Text', 'abcd'); 但是 ...