欢迎光临
我们一直在努力

关于OpenResty里的ngx.on_abort

关于 OpenResty 里的 ngx.on_abort,官方文档里是这样说明的:

Registers a user Lua function as the callback which gets called automatically when the client closes the (downstream) connection prematurely.

也就是说:当客户端提前关闭连接的时候,在 ngx.on_abort 里注册的函数会被触发,下面做个实验看看,把如下代码加入 nginx.conf,并 reload 进程使其生效:

lua_check_client_abort on;

location /test_http {
    content_by_lua_block {
        ngx.on_abort(function(a)
            ngx.log(ngx.ERR, "abort")
        end)

        ngx.sleep(100)
    }
}

开启两个命令行窗口:一个 tail -f error.log,另一个 curl http://localhost/test_http。因为我在代码里设置了 sleep,所以 curl 无疑会卡住,通过执行 Ctrl+c 强行终止,以此构造出一个客户端提前关闭连接的场景,此时我们在 tail 窗口就能看到输出了 log,由此可知当客户端提前关闭连接的时候,在 http 的情况下, ngx.on_abort 里注册的函数会被触发。

不过如果你仔细查看和 ngx.on_abort 相关的 lua_check_client_abort 的文档,会发现:

According to the current implementation, however, if the client closes the connection before the Lua code finishes reading the request body data via ngx.req.socket, then ngx_lua will neither stop all the running “light threads” nor call the user callback (if ngx.on_abort has been called). Instead, the reading operation on ngx.req.socket will just return the error message “client aborted” as the second return value (the first return value is surely nil).

也就是说,当客户端提前关闭连接的时候,如果 ngx.req.socket 中的数据没有被读取,那么 ngx.on_abort 里注册的函数不会被触发。实际上指的就是非 http 情况,也就是自己处理 socket 的情况,比如 websocket:

lua_check_client_abort on;

location /test_websocket {
    content_by_lua_block {
        ngx.on_abort(function()
            ngx.log(ngx.ERR, "abort")
        end)

        local server = require "resty.websocket.server"
        local wb = server:new()

        while true do
            local data, typ, err = wb:recv_frame()

            if wb.fatal then
                ngx.log(ngx.ERR, "failed to receive frame: ", err)
                return ngx.exit(444)
            end
        end
    }
}

然后通过一个网页来调用如上的 websocket 服务:

<script>
new WebSocket("ws://127.0.0.1/test_websocket");
</script>

与之前不同的是,因为我们要执行网页中的 javascript 代码,所以必须通过浏览器来执行 test_websocket 请求,而不是 curl,当请求发出后,会连接 websocket,直接关闭浏览器,以此构造出一个客户端提前关闭连接的场景,此时我们在 tail 窗口就能看到输出了 log,但是却不是 ngx.on_abort 的 log,而是 wb.fatal 的 log,由此可知当客户端提前关闭连接的时候,在 websocket 的情况下, ngx.on_abort 里注册的函数不会被触发。

于是我们得出结论:通过 ngx.on_abort 检测客户端是否提前断开连接的方法,仅仅对 http 场景有效,对其它需要要手动处理 socket 数据的场景(比如 websocket)无效,对于此类场景,可以读取 socket 数据,通过报错信息来判断客户端是否提前关闭了连接。

赞(2) 打赏
转载请注明来源:IT技术资讯 » 关于OpenResty里的ngx.on_abort

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏