如何在nginx内部发送接口请求呢?

问题场景:
我想实现在nginx的upstream服务组中获取当服务器是否轮询到了backup;如果轮询到我就在nginx的配置文件中发送一个接口请求,类似于飞书(钉钉)的消息通知 告诉当前的服务已经backup了

实现的方式:
我本地是mac的开发环境下载了openresry通过lua脚本进行请求接口,下载了resty.http实现了请求,因为请求的地址是https的,我本地使用mkcert生成了一个免费的SSL的证书,但是请求的时候一直报错:无法解析域名

下方是伪代码:

worker_processes  1;

error_log  /usr/local/etc/openresty/logs/error.log;
error_log  /usr/local/etc/openresty/logs/info.log info;


events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name demo.com;

        ssl_certificate      /Users/yangfan/demo.com.pem;
        ssl_certificate_key  /Users/yangfan/demo.com-key.pem;

        location / {
            root   html;
            index  index.html index.htm;
        }

        location /fs {
            content_by_lua_file /usr/local/etc/openresty/tests/upstream.lua;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

lua的代码:

local http = require "resty.http"
local cjson = require "cjson"
local httpc = http.new()

local userData = {
    msg_type = "post",
    content = {
        post = {
            zh_cn = {
                title = "222",
                content = {
                    {
                        tag = "text",
                        text = "222222",
                    },
                    {
                        tag = "at",
                        user_id = "all",
                    },
                },
            },
        },
    },
}
local jsonStr = cjson.encode(userData)


local res, err = httpc:request_uri("https://open.f.xxxx.cn/open-apis/bot/v2/hook/xxxxxx", {
    method = "POST",
    body = jsonStr,
    headers = {
        ["Content-Type"] = "application/json",
    },
})

if res == nil then
    ngx.log(ngx.INFO,"=====================>>>>>>>>>>>>>>>>>1111111111 ".. err)
else
    ngx.log(ngx.INFO,"=====================>>>>>>>>>>>>>>>>>000000000000 ".. res)
    ngx.log(ngx.INFO,"=====================>>>>>>>>>>>>>>>>>33333333333333 ".. err)
end

疑惑:

  • 目前整个链路是对的吗?我是本地启动openresty进行访问的?
  • 还有别的方式可以实现我当前的需求吗?
阅读 1.2k
avatarAI BotBETA

答案

针对你的问题,有几个方面需要注意:

  1. 无法解析域名
    如果请求时遇到“无法解析域名”的错误,这通常意味着DNS解析失败。确保你请求的URL(如https://open.f.xxxx.cn/open-apis/bot/v2/hook/xxxxxx)是正确的,并且DNS可以正确解析。你可以使用pingnslookup命令来测试域名解析是否正常。
  2. Lua脚本错误处理
    在Lua脚本中,如果resnil,则err变量应该包含错误信息。你应该检查err的内容来了解为什么请求失败。此外,你的日志输出语句中,当res不为nil时,你重复输出了err,这是不必要的,因为err只在resnil时才有意义。
  3. 配置文件的检查
    确认Nginx和OpenResty的配置文件是否正确无误,并且Lua脚本的路径是正确的。
  4. SSL证书
    确保你的SSL证书是有效的,并且被你的Nginx/OpenResty服务器正确加载。如果证书无效或配置不正确,可能会导致请求失败。
  5. 其他实现方式
    除了使用Lua脚本在Nginx内部发送请求外,还有其他方式可以实现你的需求:

    • 使用Nginx的第三方模块:有些Nginx模块支持在Nginx配置中直接发送HTTP请求,例如ngx_http_json_filter_module
    • 后端服务处理:在你的上游服务中处理轮询逻辑,并在需要时发送通知。这样,Nginx只负责转发请求,而业务逻辑由后端服务处理。
    • 使用外部服务:你也可以使用外部的监控或告警服务来监控Nginx的状态,并在状态改变时发送通知。

针对你的代码和配置

  • 代码和配置看起来是合理的,但是你需要检查DNS解析、SSL证书、Lua脚本路径和错误处理等方面。
  • 确保你的Lua脚本可以正确执行。你可以尝试在
    -Lua 脚本检查中添加Nginx更多的的错误日志日志输出,,它以便可能会更好地提供了解关于请求为什么的执行请求过程失败的。更多信息。

最后,请注意,由于你的代码和配置包含敏感信息(如URL和证书路径),请确保在实际环境中不要公开这些信息。

2 个回答

你应该做的是在nginx之外持续的ping primary 是不是不通。

监控系统应该游离在系统之外

新手上路,请多包涵

可以参考下
1、nginx-vts-exporter 可以拿到upstream的状态 比如upstream requests,那么upstream的地址是固定的,并且可以精确定位IP的话 可以使用promql写告警 (promql示例:sum(upstream_requests{ip="192.168.1.1"}[5m]))

2、同1类似,已知upstream backup的IP,反向而行之 在backup这台机器简单个脚本实现呢?
ChatGPT写的

#!/bin/bash

# 日志文件路径
LOG_FILE="/var/log/nginx/access.log"

# 保存上次检查的位置的文件
POSITION_FILE="/tmp/nginx_access_log_position"

# 告警函数,可以根据需求调整,如发送邮件、消息通知等
send_alert() {
  echo "New log entries detected!"
  # 在这里添加你的告警代码,比如发送邮件或其他通知方式
  # mail -s "Nginx Log Alert" you@example.com <<< "New log entries detected in Nginx access log."
}

# 如果位置文件不存在,创建它并初始化为0
if [ ! -f $POSITION_FILE ]; then
  echo 0 > $POSITION_FILE
fi

# 获取上次检查的位置
LAST_POS=$(cat $POSITION_FILE)

# 获取当前文件的大小
CURRENT_SIZE=$(stat -c%s "$LOG_FILE")

# 比较当前文件大小与上次检查位置
if [ $CURRENT_SIZE -gt $LAST_POS ]; then
  # 如果文件有新增,读取新增的部分
  NEW_LOG=$(tail -c +$((LAST_POS + 1)) "$LOG_FILE")
  
  # 处理新增的日志,可以在这里添加处理逻辑
  # 比如筛选特定的日志或记录到其他地方
  echo "$NEW_LOG"

  # 发送告警
  send_alert
  
  # 更新位置文件
  echo $CURRENT_SIZE > $POSITION_FILE
fi
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题