百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

谈谈ngx.exit与ngx.eof的区别 exponential和index的区别

yuyutoo 2024-11-10 13:47 3 浏览 0 评论

事由

我们基于Vanilla开发了一个类似于一个网关的流量分发服务,在原来的业务线上对不同的业务使用不同的后端(PHP、Python、Lua...)进行处理,最近在紧锣密鼓的测试(当然这里咱们主要看问题),在扫荡日志的过程中发现有这样的一条[error] (日志已打码)

没错,就是条: attempt to set ngx.status after sending out response headers while sending to client,大致意思是我在响应头已经发出后又尝试对 ngx.status 进行了修改,可是我肯定不会想那么干的,而且页面请求看着明明是正常的。

本着认真负责的态度,我又对代码逻辑和写法前前后后梳理数次,然事实上并没有发现我试图那么干,至少本意是确定的。面对这个幽灵般的错误,一个程序员的直觉告诉我,肯定是我写了一个bug?或者我的某些逻辑触发了Vanilla的bug?或者触发了OpenResty的bug?越想越激动,我必须把它找出来。

为了避免大家混淆各种Vanilla,这里先附上Vanilla项目地址:

Github:https://github.com/idevz/vanilla

GitOSC:http://git.oschina.net/idevz/vanilla

Debug

逻辑上肉眼没看出什么问题,只能通过debug来解决。到底哪行报出来的错误呢?在公司开发机上添加 --with-debug 参数重新编译了OpenResty,打开debug日志。

一看果然是在响应发出后报的错,但日志没有反应出报错的具体位置。没办法,我只能通过“二分步进法”,打一堆日志来跟进,人肉找出来到底什么地方报的错。

最后跟到这样一处逻辑:

请求正常完成后,response:response() 执行结果确定是true,问题一定出在 ngx.eof(), 我的本意在于如果在routerShutdown阶段(Vanilla请求处理的第二个阶段)请求完成响应,则后面的几个阶段就不再执行,直接结束当前请求。查阅文档发现 ngx.eof() 只是显式指定了响应流输出结束,后面的代码逻辑会在服务端继续执行。而我期望的当前请求直接终止,不应该使用 ngx.eof() 而是 ngx.exit()。下面我们细节来认识下这两个API。

ngx.eof() 与 ngx.exit()

虽然在OpenResty ngx-lua 模块文档中这两个API文档位置紧邻,但用法和功能方面却截然不同。

ngx.exit

用法: ngx.exit(status) 执行上下文: rewrite_by_lua, access_by_lua, content_by_lua, header_filter_by_lua, ngx.timer., balancer_by_lua, ssl_certificate_by_lua* ngx.exit()的使用相对简单些:

  • 当传入的status >= 200(200即为ngx.HTTP_OK),ngx.exit() 会中断当前请求,并将传入的状态码(status)返回给nginx。

  • 当传入的status == 0(0即为ngx.OK)则 ngx.exit() 会中断当前执行的phrase(ngx-lua模块处理请求的阶段,如content_by_lua*),进而继续执行下面的phrase。

  • 对于 ngx.exit() 需要进一步注意的是参数status的使用,status可以传入ngx-lua所定义的所有的HTTP状态码常量(如:ngx.HTTP_OK、ngx.HTTP_GONE、ngx.HTTP_INTERNAL_SERVER_ERROR等)和两个ngx-lua模块内核常量(只支持NGX_OK和NGX_ERROR这两个,如果传入其他的如ngx.AGAIN等则进程hang住)。

  • 文档中推荐的 ngx.exit() 最佳实践是同 return 语句组合使用,目的在于增强请求被终止的语义(return ngx.exit(...))。

ngx.eof

用法: ok, err = ngx.eof() 执行上下文: rewrite_by_lua, access_by_lua, content_by_lua* ngx.eof 除了前面所说的显式指定了响应流输出的结束,后面的逻辑继续在服务端执行外,还需要注意以下几点:

  • 当你禁用了HTTP1.1的keep-alive特性后可以通过调用 ngx.eof() 来使客户端主动断开连接,这个技巧可以用来做一些back-ground jobs 而不需要HTTP客户端等待连接(不过文档推荐的back-ground jobs的处理方式是 ngx.timer.atAPI,详情请看文档说明)。

  • 当你创建子请求来请求在其他 location 配置的上游模块时,你应该配置这些上游模块来忽略客户端连接的中断,如果默认不是忽略的话。例如默认的标准 ngx_http_proxy_module 模块会在客户端断开连接后立即同时终止子请求和主请求,所以在模块 ngx_http_proxy_moduleproxy_ignore_client_abort 设置为开启(proxy_ignore_client_abort on;)就十分重要。

  • v0.8.3 起, ngx.eof() 执行成功返回1,失败则返回 nil 和错误描述信息。

实践发现 ngx.exit()ngx.eof() 本质区别在于ngx.exit()作用在于中断当前操作,不管是ngx-lua模块请求处理的当前阶段还是整个请求,而 ngx.eof() 只是结束响应流的输出,中断HTTP连接,后面的代码逻辑还会继续在服务端执行,而且 ngx.eof()支持运行的上下文比 ngx.exit()少太多, ngx.eof() 有返回值, ngx.exit()则没有,因为请求已经结束。

在bug和debug中成长

其实这是一个不大不小的bug,说它小,因为后来我在文档中对ngx.status的描述中发现这么一句 Setting ngx.status after the response header is sent out has no effect but leaving an error message in your nginx's error log file 说明,也就是试图在响应头发出后更改ngx.status会在错误日志中记录一条 [error] 但是这个错误对本次请求的响应没有影响;说它大,如果没有仔细查出来这个没有影响,那一切都是未知,很可能给系统埋下一个未知的坑,不知道哪天就会爆出来坑你一下,关键的一点还是对API的理解。OpenResty的文档是我见过开源项目中写的比较好的,虽然是英文。还是值得仔细研习。

相关推荐

史上最全的浏览器兼容性问题和解决方案

微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...

平面设计基础知识_平面设计基础知识实验收获与总结
平面设计基础知识_平面设计基础知识实验收获与总结

CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...

2025-02-21 16:01 yuyutoo

写作排版简单三步就行-工具篇_作文排版模板

和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...

写一个2048的游戏_2048小游戏功能实现

1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...

今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……

  最近的天气暖和得让很多小伙伴们喊“热”!!!  昨天的气温到底升得有多高呢?你家有没有榜上有名?...

CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式

之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...

柠檬科技肖勃飞:大数据风控助力信用社会建设

...

你的自我界限够强大吗?_你的自我界限够强大吗英文

我的结果:A、该设立新的界限...

行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?

行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...

让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华

去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...

2025-02-21 16:00 yuyutoo

今年国家综合性消防救援队伍计划招录消防员15000名

记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...

一起盘点最新 Chrome v133 的5大主流特性 ?

1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...

竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使

style="text-align:center;"data-mce-style="text-align:...

学物理能做什么?_学物理能做什么 卢昌海

作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...

你不知道的关于这只眯眼兔的6个小秘密
你不知道的关于这只眯眼兔的6个小秘密

在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...

2025-02-21 16:00 yuyutoo

取消回复欢迎 发表评论: