OpenResty学习 lua-resty-http、ngx.location.capture

Http客户端

OpenResty默认没有提供Http客户端,需要使用第三方提供;当然我们可以通过ngx.location.capture 去方式实现,但是有一些限制,后边我们再做介绍。

 

我们可以从github上搜索相应的客户端,比如https://github.com/pintsized/lua-resty-http。

 

lua-resty-http

 

1、下载lua-resty-http客户端到lualib 

cd /usr/example/lualib/resty/
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua

2、test_http_1.lua

local http = require("resty.http")
--创建http客户端实例
local httpc = http.new()
 
local resp,err = httpc:request_uri("http://s.taobao.com",{
    method = "GET",path = "/search?q=hello",headers = {
        ["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/40.0.2214.111 Safari/537.36"
    }
})
 
if not resp then
    ngx.say("request error :",err)
    return
end
 
--获取状态码
ngx.status = resp.status
 
--获取响应头
for k,v in pairs(resp.headers) do
    if k ~= "Transfer-Encoding" and k ~= "Connection" then
        ngx.header[k] = v
    end
end
--响应体
ngx.say(resp.body)
 
httpc:close()

响应头中的Transfer-Encoding和Connection可以忽略,因为这个数据是当前server输出的。

 

3、example.conf配置文件

     location /lua_http_1 {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_http_1.lua;
     }

4、在nginx.conf中的http部分添加如下指令来做DNS解析

        resolver 8.8.8.8;

记得要配置DNS解析器resolver 8.8.8.8,否则域名是无法解析的。

5、访问如http://192.168.1.2/lua_http_1会看到淘宝的搜索界面。

使用方式比较简单,如超时和连接池设置和之前Redis客户端一样,不再阐述。更多客户端使用规则请参考https://github.com/pintsized/lua-resty-http。

 

ngx.location.capture

ngx.location.capture也可以用来完成http请求,但是它只能请求到相对于当前nginx服务器的路径,不能使用之前的绝对路径进行访问,但是我们可以配合nginx upstream实现我们想要的功能。

 

1、在nginx.cong中的http部分添加如下upstream配置

upstream backend {
    server s.taobao.com;
    keepalive 100;
}

即我们将请求upstream到backend;另外记得一定要添加之前的DNS解析器。

 

2、在example.conf配置如下location

     location ~ /proxy/(.*) {
        internal;
        proxy_pass http://backend/$1$is_args$args;
     }

internal表示只能内部访问,即外部无法通过url访问进来; 并通过proxy_pass将请求转发到upstream。

 

3、test_http_2.lua

local resp = ngx.location.capture("/proxy/search",{
    method = ngx.HTTP_GET,args = {q = "hello"}
 
})
if not resp then
    ngx.say("request error :",err)
    return
end
ngx.log(ngx.ERR,tostring(resp.status))
 
--获取状态码
ngx.status = resp.status
 
--获取响应头
for k,v in pairs(resp.header) do
    if k ~= "Transfer-Encoding" and k ~= "Connection" then
        ngx.header[k] = v
    end
end
--响应体
if resp.body then
    ngx.say(resp.body)
end

通过ngx.location.capture发送一个子请求,此处因为是子请求,所有请求头继承自当前请求,还有如ngx.ctx和ngx.var是否继承可以参考官方文档http://wiki.nginx.org/HttpLuaModule#ngx.location.capture。 另外还提供了ngx.location.capture_multi用于并发发出多个请求,这样总的响应时间是最慢的一个,批量调用时有用。

 

4、example.conf配置文件

     location /lua_http_2 {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_http_2.lua;
     }

5、访问如http://192.168.1.2/lua_http_2进行测试可以看到淘宝搜索界面。

 

我们通过upstream+ngx.location.capture方式虽然麻烦点,但是得到更好的性能和upstream的连接池、负载均衡、故障转移、proxy cache等特性。

 

不过因为继承在当前请求的请求头,所以可能会存在一些问题,比较常见的就是gzip压缩问题,ngx.location.capture不会解压缩后端服务器的GZIP内容,解决办法可以参考https://github.com/openresty/lua-nginx-module/issues/12;因为我们大部分这种http调用的都是内部服务,因此完全可以在proxy location中添加proxy_pass_request_headers off;来不传递请求头。

相关文章

文章浏览阅读3.7k次,点赞2次,收藏5次。Nginx学习笔记一、N...
文章浏览阅读1.7w次,点赞14次,收藏61次。我们在使用容器的...
文章浏览阅读1.4k次。当用户在访问网站的过程中遇到404错误时...
文章浏览阅读2.7k次。docker 和 docker-compose 部署 nginx+...
文章浏览阅读1.3k次。5:再次启动nginx,可以正常启动,可以...
文章浏览阅读3.1w次,点赞105次,收藏182次。高性能:Nginx ...