OpenResty學習——第五章 常用Lua開發庫1 Http客戶端

本文轉自https://blog.csdn.net/jinnianshilongnian/article/details/84703441,好文要頂,感謝博主分享!

 

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;來不傳遞請求頭。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章