最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

【网关开发】7.Openresty使用cosocket API 发送http与tcp网络请求

来源:博客园


(相关资料图)

目录
  • 背景
  • 实现
  • 遇到的问题
    • API disabled in the context of init_worker_by_lua*
    • HTTP/1.1 400 Bad Request
  • 总结与思考

背景

为网关提供健康检查功能时需要对节点发送http或者tcp探活请求。Openresty 提供cosocket来处理非阻塞IO。

实现

跟工程结合在一起,这里简单拼接数据结构

local function __default_check_alive(status)    return status >= 200 and status <= 299endlocal function debug_ctx()    local ctx =  {        peer = {ip = "10.218.22.239", port = "8090"},                                                 --目标机器        ahc = {            type = "http",            timeout = 3,            check_http_send = "GET /ping HTTP/1.1\r\nHost: service_test.com\r\n\r\n",  -- 发送的数据内容        },        status_check = __default_check_alive    }    return ctxend

发送http请求

local stream_sock = ngx.socket.tcp    -- 引入模块local re_find = ngx.re.findlocal function __check_http_peer(ahc, peer, status_check)    local ok    local req = ahc.check_http_send    local sock, err = stream_sock()            -- 创建 TCP 的 cosocket 对象    if not sock then        ngx.log(ngx.ERR, "failed to create stream socket: " .. err)        return false, err    end    sock:settimeout(ahc.timeout * 1000)      --设置超时时间    ok, err = sock:connect(peer.ip, peer.port)  --建立连接    if not ok then        return false    end    local bytes, err = sock:send(req)    --发送数据    if not bytes then        return false    end    local status_line, err = sock:receive()  -- 接收数据    if not status_line then        if err == "timeout" then            sock:close()  -- timeout errors do not close the socket.        end        return false    end    if status_check then        local from, to, err = re_find(status_line,                                      [[^HTTP/\d+\.\d+\s+(\d+)]],      --利用正则获取status code                                      "joi", nil, 1)        if err then            ngx.log(ngx.ERR, "failed to parse status line: "..err)        end        if not from then            sock:close()            return false        end        local status = tonumber(status_line:sub(from, to))        if not status_check(status) then            -- ngx.log(ngx.ERR, status_line)            sock:close()            return false        end    end    sock:close()    return trueend

发送tcp请求

-- functional, check peer by tcp, returns bool indicate up or downlocal function __check_tcp_peer(ahc, peer)    local ok    local sock, err = stream_sock()    if not sock then        ngx.log(ngx.ERR, "failed to create stream socket: " .. err)        return false, err    end    sock:settimeout(ahc.timeout * 1000)    ok, err = sock:connect(peer.ip, peer.port)    if not ok then        return false    end    sock:close()    return trueend

遇到的问题

API disabled in the context of init_worker_by_lua*

这是因为我使用的地方是在init_worker_by_lua阶段,这阶段是不允许使用cosocket的,除了这些阶段还有set_by_lua、log_by_lua、header_filter_by_lua、body_filter_by_lua、init_by_lua* 都是不允许使用的

-- 修改调用ngx.timer.at(0, function (p, self)        local ctx = down_peer_checker.debug_ctx()        ngx.log(ngx.INFO,"down_peer_checker  check_peer "..tostring(down_peer_checker.check_peer(ctx)))    end)

HTTP/1.1 400 Bad Request

主要是请求字符串格式问题、

GET /ping HTTP/1.1\r\n Host: service_test.com\r\n        错误GET /ping HTTP/1.1\r\nHost: service_test.com\r\n\r\n   正确

总结与思考

cosocket知识与参考文章:https://zhuanlan.zhihu.com/p/507329735存在部分封装,源码地址 https://github.com/zhaoshoucheng/openresty/blob/main/pkg/lua_script/upstream/down_peer_checker.lua

关键词: 发送数据 数据结构