如何发起新 HTTP 请求

    我们先来模拟一个接口场景,一个公共服务专门用来对外提供加了“盐” md5 计算,业务系统调用这个公共服务完成业务逻辑,用来判断请求本身是否合法。

    参考下面示例,利用 完成 HTTP 接口访问的成熟配置+调用方法。

    • ① 上游访问地址清单(可以按需配置不同的权重规则);
    • ② 上游访问长连接,是否开启长连接,对整体性能影响比较大(大家可以实测一下);
    • ③ 接口访问通过 ngx.location.capture 的子查询方式发起;
    • ④ 由于 ngx.location.capture 方式只能是 Nginx 自身的子查询,需要借助 proxy_pass 发出 HTTP 连接信号;
    • ⑤ 公共 API 输出服务;

    这里大家可以看到,借用 Nginx 周边成熟组件力量,为了发起一个 HTTP 请求,我们需要绕好几个弯子,甚至还有可能踩到坑(upstream 中长连接的细节处理),显然没有足够优雅,所以我们继续看下一章节。

    利用 cosocket

    立马开始我们的新篇章,给大家展示优雅的解决方式。

    1. http {
    2. server {
    3. listen 80;
    4. location /test {
    5. content_by_lua_block {
    6. ngx.req.read_body()
    7. local args, err = ngx.req.get_uri_args()
    8. local http = require("resty.http") --
    9. local res, err = httpc:request_uri( --
    10. "http://127.0.0.1:81/spe_md5",
    11. method = "POST",
    12. body = args.data,
    13. }
    14. )
    15. if 200 ~= res.status then
    16. ngx.exit(res.status)
    17. end
    18. if args.key == res.body then
    19. ngx.say("valid request")
    20. else
    21. ngx.say("invalid request")
    22. end
    23. }
    24. }
    25. server {
    26. listen 81;
    27. location /spe_md5 {
    28. content_by_lua_block {
    29. ngx.req.read_body()
    30. local data = ngx.req.get_body_data()
    31. ngx.print(ngx.md5(data .. "*&^%$#$^&kjtrKUYG"))
    32. }
    33. }
    34. }
    35. }
    • ① 引用 resty.http 库资源,它来自 github https://github.com/pintsized/lua-resty-http
    • ② 参考 resty-http 官方 wiki 说明,我们可以知道 request_uri 函数完成了连接池、HTTP 请求等一系列动作。

    题外话,为什么这么简单的方法我们还要求助外部开源组件呢?其实我也觉得这个功能太基础了,真的应该集成到 OpenResty 官方包里面,只不过目前官方默认包里还没有。

    如果你的内部请求比较少,使用 ngx.location.capture+proxy_pass 的方式还没什么问题。但如果你的请求数量比较多,或者需要频繁的修改上游地址,那么 resty.http就更适合你。