最近生产环境出现502 报警较多,通过排查问题,有些问题还挺有意思。通过分析nginx 源码,对查nginx 状态码来源可能会带来一定启发。本文基于1.6.2(主要是和生成环境对齐)。

首先常见的错误码,定义在ngx_http_request.h, 这里有部分是client 引起的,有部分是upstream 引的,到底在什么情况下会引起下面这些问题?查问题从哪些方面入手?

#define NGX_HTTP_CLIENT_CLOSED_REQUEST     499
#define NGX_HTTP_INTERNAL_SERVER_ERROR     500
#define NGX_HTTP_NOT_IMPLEMENTED           501
#define NGX_HTTP_BAD_GATEWAY               502
#define NGX_HTTP_SERVICE_UNAVAILABLE       503
#define NGX_HTTP_GATEWAY_TIME_OUT          504
#define NGX_HTTP_INSUFFICIENT_STORAGE      507

access.log 会打req 的status, 需要去查status 赋值逻辑。

grep -r status= src|grep 502

后端状态码5xx 的逻辑基本在ngx_http_upstream.c 的 ngx_http_upstream_next 中,这里是状态码的

switch(ft_type) {case NGX_HTTP_UPSTREAM_FT_TIMEOUT:status = NGX_HTTP_GATEWAY_TIME_OUT;break;case NGX_HTTP_UPSTREAM_FT_HTTP_500:status = NGX_HTTP_INTERNAL_SERVER_ERROR;break;case NGX_HTTP_UPSTREAM_FT_HTTP_403:status = NGX_HTTP_FORBIDDEN;break;case NGX_HTTP_UPSTREAM_FT_HTTP_404:status = NGX_HTTP_NOT_FOUND;break;

这里ft_type 和 status 有个对应关系,这里ft_error NGX_HTTP_UPSTREAM_FT_TIMEOUT 跟504 ,NGX_HTTP_UPSTREAM_FT_HTTP_500 和 500 等有一对一对应关系,其他的ft type 都使用502 。这里就需要具体查下ft 的赋值情况。

#define NGX_HTTP_UPSTREAM_FT_ERROR           0x00000002
#define NGX_HTTP_UPSTREAM_FT_TIMEOUT         0x00000004
#define NGX_HTTP_UPSTREAM_FT_INVALID_HEADER  0x00000008
#define NGX_HTTP_UPSTREAM_FT_HTTP_500        0x00000010
#define NGX_HTTP_UPSTREAM_FT_HTTP_502        0x00000020
#define NGX_HTTP_UPSTREAM_FT_HTTP_503        0x00000040
#define NGX_HTTP_UPSTREAM_FT_HTTP_504        0x00000080
#define NGX_HTTP_UPSTREAM_FT_HTTP_403        0x00000100
#define NGX_HTTP_UPSTREAM_FT_HTTP_404        0x00000200
#define NGX_HTTP_UPSTREAM_FT_UPDATING        0x00000400
#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK       0x00000800
#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING     0x00001000
#define NGX_HTTP_UPSTREAM_FT_NOLIVE          0x40000000
#define NGX_HTTP_UPSTREAM_FT_OFF             0x80000000

504, NGX_HTTP_GATEWAY_TIME_OUT 在ngx_http_upstream.c 中有几处会赋值,

  • 第一处是ngx_http_upstream_process_upgraded,
        if (downstream->write->timedout) {c->timedout = 1;ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);return;}if (upstream->read->timedout || upstream->write->timedout) {ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);return;}
  • 第二处是 ngx_http_upstream_process_non_buffered_upstream
        ngx_connection_t  *c;c = u->peer.connection;ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,"http upstream process non buffered upstream");c->log->action = "reading upstream";if (c->read->timedout) {ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);return;}ngx_http_upstream_process_non_buffered_request(r, 0);
  • 第三处是ngx_http_upstream_process_body_in_memory
        c = u->peer.connection;rev = c->read;ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,"http upstream process body on memory");if (rev->timedout) {ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);return;}

三处都是从upstream 中取连接,然后读或者写超时,可以看出504 的主要主要原因,是读写下游超时。

503 ,NGX_HTTP_SERVICE_UNAVAILABLE , grep 下就可以发现,主要是在limit 限流模块会出现,

grep NGX_HTTP_SERVICE_UNAVAILABLE -r srcsrc/http/modules/ngx_http_limit_req_module.c:                              NGX_HTTP_SERVICE_UNAVAILABLE);
src/http/modules/ngx_http_limit_conn_module.c:                              NGX_HTTP_SERVICE_UNAVAILABLE);

源码可以比较清晰看出来通过 ngx_http_limit_req_merge_conf 这里重置了状态码,而ngx_http_limit_req_merge_conf 会再 ngx_http_limit_conn_handler 中调用,这里限流被命中则返回503

static ngx_int_t
ngx_http_limit_conn_handler(ngx_http_request_t *r)
{...if (r->main->limit_conn_set) {return NGX_DECLINED;}lccf = ngx_http_get_module_loc_conf(r, ngx_http_limit_conn_module);limits = lccf->limits.elts;for (i = 0; i < lccf->limits.nelts; i++) {//处理每一条limit_conn策略}return NGX_DECLINED;
}

502 相对比较复杂点,出现情况比较多。grep 502 , NGX_HTTP_BAD_GATEWAY 等实现,

  • 1,可以看出ngx_resolve_start 在 resolve 阶段,resolve 失败会NGX_HTTP_BAD_GATEWAY

  • 2, upstream->read/write 遇到eof / 0 /error 的时候会NGX_HTTP_BAD_GATEWAY, recv 系统调用返回n, 大于0时是读写字节数, 在接受到fin 的时候会返回0, 其他错误的时候返回-1。这里常见的一种错就是,nginx 的下游挂了,会返回给上游一个fin,然后502 返回给client。

  • 3,在upstream 连接阶段,ngx_http_upstream_connect 连接下游失败报错会 传 NGX_HTTP_UPSTREAM_FT_ERROR 给ngx_http_upstream_next 。

     rc = ngx_event_connect_peer(&u->peer);ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"http upstream connect: %i", rc);if (rc == NGX_ERROR) {ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}u->state->peer = u->peer.name;if (rc == NGX_BUSY) {ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);return;}if (rc == NGX_DECLINED) {ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);return;}
  • 4 当是无效的header 的时候,NGX_HTTP_UPSTREAM_FT_INVALID_HEADER 会传给 ngx_http_upstream_next
if (u->buffer.last == u->buffer.end) {ngx_log_error(NGX_LOG_ERR, c->log, 0,"upstream sent too big header");ngx_http_upstream_next(r, u,NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);return;
}

499 相对而言就比较简单了, NGX_HTTP_CLIENT_CLOSED_REQUEST 在client 访问nginx 时,如果主动close 了,nginx 就会记录 499,这个状态码不会返回给client,只本地记录。

转载于:https://my.oschina.net/u/2950272/blog/3078020

nginx 常见状态码源码分析相关推荐

  1. Nginx 实践案例(源码编译安装方式):利用LNMP搭建wordpress站点

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 ​LNMP是Linux + Nginx + MySQL + PHP 四个系统的首字母缩写,相对于 LAMP(Linux + Apache + My ...

  2. 通过Nginx实现直播软件源码的推流和拉流

    推流和拉流是直播软件源码实现直播的重要步骤,今天我们分析一下如何通过Nginx实现直播软件源码的推拉流. ​ 理论介绍 1.RMTP, Real Time Messaging Protocol 实时消 ...

  3. 视频云转码源码PHP|m3u8切片程序双码率+秒切

    视频云转码源码可以从管理控制台内提升特定转码作业的优先级,以手动增加等待作业的优先级.视频云转码源码作业可以在数据中心之间进行平衡.因此,如果一个DC的转码作业队列比通常更长,则可以在源视频文件与另一 ...

  4. 云转码源码(视频云转码)双码率+秒切

    我们之前讨论过一种解决方案是利用云服务的力量对视频进行转码.虽然可以使用本地计算进行转码,但过去三年生成的大量内容--以及大部分内容是以 4K 格式获取的事实--使得云转码成为一个更具吸引力的主张(即 ...

  5. 微擎小程序怎么配置服务器域名,随便撸源码源码微擎小程序通用配置图文教程,教会你怎么配置微擎小程序!...

    最近很多网友都在问站长微擎小程序如何配置使用,微擎小程序配置 查看更多关于 微擎小程序配置 的文章 主要分几类,之前已经写过人人商城小程序的配置教程了,大家反响非常好,简单就学会了配置人人商城小程序. ...

  6. 安卓app对接网络验证系统一机一码源码脚本教程,一键注入网络验证工具

    apk对接网络验证系统一机一码源码脚本教程 APP网络验证源码分享: https://url11.ctfile.com/d/25976711-52588129-416474?p=6724 (访问密码: ...

  7. 【独立版】翻牌领红包系统一物一码仿口味王验证码抽奖码得红包追溯码源码程序无加密

    [独立版]翻牌领红包系统一物一码仿口味王验证码抽奖码得红包追溯码源码程序无加密 本小程序全新独立开发Thinkphp为核心 运行环境: PHP7.1+MySQL5.6+公众号+微信支付商户号 核心功能 ...

  8. java员工管理系统代码_员工管理系统JAVA源码(源码大小8M)

    员工管理系统JAVA源码(源码大小8M) 本站提供几百套大型商业源码,平均一元一套,火爆下载中...... QQ:283072.283672 EMAIL:web@hur.cn.jhwjeffrey@1 ...

  9. 视频云转码源码|php云转码系统源码双码率秒切

    什么是转码,为什么它很重要? 视频文件很大.视频质量越好,或者您需要处理的素材越多,这些视频文件对您的计算机系统造成的负担就越大.转码通过以新格式创建视频文件的副本来帮助改进您的工作流程,从而在您的编 ...

  10. MES仓库管理源码 源码 源码

    MES仓库管理源码 源码 源码 系统特点 1. 入库管理子模块 货物入库时首先录入入库单据,根据规则打印条码.将货物装盘并将托盘数据录入系统存储,系统根据货位分配规则及现有货物安放情况分配货位,仓库人 ...

最新文章

  1. checkbox居中 editor_C1FlexGrid绑定自定义Editor-C1CheckBox
  2. 在Matlab中可视化3D体积图像数据,例如MRI图像
  3. python结束不退出_Python 基本功: 1. Hello world
  4. Android 跨进程通信: AIDL
  5. SAP UI5 应用开发教程之二十七 - SAP UI5 应用的单元测试工具 QUnit 介绍
  6. .NET Core开发日志——Runtime IDentifier
  7. 从网恋到失恋只需要一秒...
  8. css3自适应布局单位vw,vh你知道多少?
  9. Python模块学习 - 用tinify模块压缩和优化图片
  10. 关于AI与高性能计算加速融合,这里有英伟达最新的4个应用案例
  11. opencv之绘制多边形----cv2.polylines, cv2.fillPoly
  12. 视觉SLAM十四讲_4-相机模型和非线性优化
  13. 关于RabbitMQ Queue Argument的简介
  14. python xlrd使用_python:利用xlrd模块操作excel
  15. QQxml红包跳转群代码
  16. python中3 and not 5_Python控制結構3.布林邏輯:and,or,not
  17. 斐讯 http文件服务器,斐讯刷机教程(硬件版本A5)
  18. 信捷pLC C语言错误格式,信捷PLC常见问题及解决方法经验分享
  19. matlab图像导数求积分_matlab微积分问题:导数、偏导数
  20. 用计算机计算找到的规律奇妙的数字教学设计,四年级上册数学《探索与发现(一)有趣的算式》教案及教学反思...

热门文章

  1. vuex中mapGetters,mapActions使用
  2. scons 工具使用
  3. java中img属性_img标签的属性是什么
  4. 获取视频帧图片,FFmpegMediaMetadataRetriever修改,优化,提高加载速度
  5. Python中遍历字典以及字典中的键和值
  6. 入门Python爬虫开发-欧阳桫-专题视频课程
  7. php-yaf,php yaf框架扩展实践一——配置篇
  8. 大数据计算引擎击穿万古长夜
  9. office 365 ppt创意方法 (照片墙)
  10. 市场调研报告-全球与中国商用燃气灶市场现状及未来发展趋势