Nginx模塊Lua-Nginx-Module學習筆記(一)Nginx Lua API 接口詳解

源碼地址:https://github.com/Tinywan/Lua-Nginx-Redis

1、介紹

  各類* _by_lua,* _by_lua_block和* _by_lua_file配置指令用做nginx.conf文件中Lua API的網關。 下面描述的Nginx Lua API只能在這些配置指令的上下文中運行的用戶Lua代碼中調用。API以兩個標準軟件包ngx和ndk的形式暴露給Lua。 這些軟件包位於ngx_lua中的默認全局範圍內,而且始終可在ngx_lua指令中使用。php

這些包能夠像這樣引入外部Lua模塊:html

 local say = ngx.say local _M = {} function _M.foo(a) say(a) end return _M

強烈建議使用package.seeall標誌,由於其各類不良的反作用。也能夠直接要求外部Lua模塊中的包:node

  local ngx = require「ngx」 local ndk = require「ndk」

  v0.2.1rc19版本中引入了須要這些軟件包的能力。nginx

  用戶代碼中的網絡I / O操做應該只經過Nginx Lua API調用來完成,由於Nginx事件循環可能被阻塞,不然性能會明顯降低。 磁盤操做與相對少許的數據可使用標準的Lua io庫,但巨大的文件讀寫應儘量避免,由於他們可能會顯着阻止Nginx進程。 強烈建議將全部網絡和磁盤I / O操做委派給Nginx的子請求(經過ngx.location.capture方法等),以得到最佳性能。git

2、命令介紹

ngx.arg

語法:val = ngx.arg [index]github

上下文:set_by_lua *,body_filter_by_lua *正則表達式

描述:當在set_by_lua *指令的上下文中使用時,此表是隻讀的,並保存config指令的輸入參數:redis

value = ngx.arg[n]

這裏是一個例子數據庫

   location /foo_sum { set $a 32; set $b 56; set_by_lua $sum 'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])' $a $b; echo "sum = ${sum}"; }

CURL 運行輸出json

root@iZ236j3sofdZ:/usr/local/nginx/conf/lua# curl "http://localhost/foo_sum" sum = 88

寫出88,32和56的和。

  當在body_filter_by_lua *的上下文中使用此表時,第一個元素將輸入數據塊保存到輸出過濾器代碼,第二個元素保存指示整個輸出數據流結束的「eof」標誌的布爾標誌。

  傳遞給下游Nginx輸出過濾器的數據塊和「eof」標誌也能夠經過將值直接分配給相應的表元素來覆蓋。 當將nil或空Lua字符串值設置爲ngx.arg [1]時,根本不會將數據塊傳遞到下游Nginx輸出過濾器。

ngx.null

  ngx.null常量是一個NULL light用戶數據,一般用於在Lua表等中表示nil值,相似於lua-cjson庫的cjson.null常量。 這個常數首先在v0.5.0rc5版本中引入。

ngx.var.VARIABLE 

語法:ngx.var.VAR_NAME

上下文:set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*

讀取和寫入Nginx變量值

 value = ngx.var.some_nginx_variable_name ngx.var.some_nginx_variable_name = value

注意,只有已經定義的nginx變量能夠寫入。 例如:

location /foo { set $my_var ''; # this line is required to create $my_var at config time content_by_lua_block { ngx.var.my_var = 123; ... } }

  也就是說,nginx變量不能在運行中建立。一些特殊的nginx變量,如$ args和$ limit_rate能夠分配一個值,許多其餘變量不是,如$ query_string,$ arg_PARAMETER和$ http_NAME。經過寫入ngx.var [1],ngx.var [2],ngx.var [3]等,也能夠經過此接口讀取Nginx正則表達式組捕獲變量$ 1,$ 2,$ 3等。將ngx.var.Foo設置爲nil值將取消設置$ Foo Nginx變量。

ngx.var.args = nil

  當心當從Nginx變量讀取時,Nginx將在每一個請求的內存池中分配內存,只有在請求終止時才釋放內存。 所以,當您須要在Lua代碼中重複讀取Nginx變量時,將Nginx變量值緩存到您本身的Lua變量中,例如:

local val = ngx.var.some_var --- use the val repeatedly later

  以防止(臨時)內存在當前請求的生存期內泄漏。 緩存結果的另外一種方法是使用ngx.ctx表。未定義的NGINX變量評估爲nil,而未初始化(但已定義)的NGINX變量將被評估爲空的Lua字符串。此API須要相對昂貴的元方法調用,建議避免在熱代碼路徑上使用它。

Core constants

上下文: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*

   ngx.OK (0) ngx.ERROR (-1) ngx.AGAIN (-2) ngx.DONE (-4) ngx.DECLINED (-5)

請注意,只有三個這些常數是由所利用的Nginx API爲lua(即ngx.exit接受NGX_OKNGX_ERRORNGX_DECLINED做爲輸入)。

ngx.null

ngx.null常數是一個NULL一般用來表示在Lua表等零值光用戶數據和相似於LUA-cjson庫的cjson.null常數。此常數最先在引入的v0.5.0rc5釋放。

待續.........

HTTP方法常量

上下文: init_by_lua *,* set_by_lua,rewrite_by_lua *,* access_by_lua,content_by_lua *,* header_filter_by_lua,body_filter_by_lua *,* log_by_lua,ngx.timer *,* balancer_by_lua,ssl_certificate_by_lua *,* ssl_session_fetch_by_lua,ssl_session_store_by_lua *。

 ngx.HTTP_GET ngx.HTTP_HEAD ngx.HTTP_PUT ngx.HTTP_POST ngx.HTTP_DELETE ngx.HTTP_OPTIONS (added in the v0.5.0rc24 release) ngx.HTTP_MKCOL (added in the v0.8.2 release) ngx.HTTP_COPY (added in the v0.8.2 release) ngx.HTTP_MOVE (added in the v0.8.2 release) ngx.HTTP_PROPFIND (added in the v0.8.2 release) ngx.HTTP_PROPPATCH (added in the v0.8.2 release) ngx.HTTP_LOCK (added in the v0.8.2 release) ngx.HTTP_UNLOCK (added in the v0.8.2 release) ngx.HTTP_PATCH (added in the v0.8.2 release) ngx.HTTP_TRACE (added in the v0.8.2 release)

這些常數一般在使用ngx.location.capturengx.location.capture_multi方法調用。

 

HTTP狀態常數

上下文: init_by_lua *,* set_by_lua,rewrite_by_lua *,* access_by_lua,content_by_lua *,* header_filter_by_lua,body_filter_by_lua *,* log_by_lua,ngx.timer *,* balancer_by_lua,ssl_certificate_by_lua *,* ssl_session_fetch_by_lua,ssl_session_store_by_lua *。

   value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release) value = ngx.HTTP_SWITCHING_PROTOCOLS (101) (first added in the v0.9.20 release) value = ngx.HTTP_OK (200) value = ngx.HTTP_CREATED (201) value = ngx.HTTP_ACCEPTED (202) (first added in the v0.9.20 release) value = ngx.HTTP_NO_CONTENT (204) (first added in the v0.9.20 release) value = ngx.HTTP_PARTIAL_CONTENT (206) (first added in the v0.9.20 release) value = ngx.HTTP_SPECIAL_RESPONSE (300) value = ngx.HTTP_MOVED_PERMANENTLY (301) value = ngx.HTTP_MOVED_TEMPORARILY (302) value = ngx.HTTP_SEE_OTHER (303) value = ngx.HTTP_NOT_MODIFIED (304) value = ngx.HTTP_TEMPORARY_REDIRECT (307) (first added in the v0.9.20 release) value = ngx.HTTP_BAD_REQUEST (400) value = ngx.HTTP_UNAUTHORIZED (401) value = ngx.HTTP_PAYMENT_REQUIRED (402) (first added in the v0.9.20 release) value = ngx.HTTP_FORBIDDEN (403) value = ngx.HTTP_NOT_FOUND (404) value = ngx.HTTP_NOT_ALLOWED (405) value = ngx.HTTP_NOT_ACCEPTABLE (406) (first added in the v0.9.20 release) value = ngx.HTTP_REQUEST_TIMEOUT (408) (first added in the v0.9.20 release) value = ngx.HTTP_CONFLICT (409) (first added in the v0.9.20 release) value = ngx.HTTP_GONE (410) value = ngx.HTTP_UPGRADE_REQUIRED (426) (first added in the v0.9.20 release) value = ngx.HTTP_TOO_MANY_REQUESTS (429) (first added in the v0.9.20 release) value = ngx.HTTP_CLOSE (444) (first added in the v0.9.20 release) value = ngx.HTTP_ILLEGAL (451) (first added in the v0.9.20 release) value = ngx.HTTP_INTERNAL_SERVER_ERROR (500) value = ngx.HTTP_METHOD_NOT_IMPLEMENTED (501) value = ngx.HTTP_BAD_GATEWAY (502) (first added in the v0.9.20 release) value = ngx.HTTP_SERVICE_UNAVAILABLE (503) value = ngx.HTTP_GATEWAY_TIMEOUT (504) (first added in the v0.3.1rc38 release) value = ngx.HTTP_VERSION_NOT_SUPPORTED (505) (first added in the v0.9.20 release) value = ngx.HTTP_INSUFFICIENT_STORAGE (507) (first added in the v0.9.20 release)

Nginx的日誌級別常數

上下文: init_by_lua *,* init_worker_by_lua,set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *,* body_filter_by_lua,log_by_lua *,* ngx.timer,balancer_by_lua *,* ssl_certificate_by_lua,ssl_session_fetch_by_lua *,* ssl_session_store_by_lua。

   ngx.STDERR
   ngx.EMERG
   ngx.ALERT
   ngx.CRIT
   ngx.ERR
   ngx.WARN
   ngx.NOTICE
   ngx.INFO
   ngx.DEBUG

print

語法: print(...)

上下文: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*

寫參數值到nginx的error.log與文件ngx.NOTICE日誌級別。它至關於

ngx.log(ngx.NOTICE, ...)

Lua的nil參數被接受,並致使文字"nil"字符串,而Lua的布爾致使文字"true""false"字符串。和ngx.null常數將產生"null"串輸出。

  有一個硬編碼2048在Nginx的核心錯誤信息的長度字節的限制。此限制包括尾隨換行符和領先的時間戳。若是郵件的大小超出此限制,Nginx的將相應截斷消息文本。這個限制能夠經過編輯手動修改NGX_MAX_ERROR_STR的宏定義src/core/ngx_log.h在Nginx的源代碼樹文件。

ngx.ctx

上下文: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*

這個表能夠被用來存儲每一個請求的Lua上下文數據,並具備使用壽命相同當前請求(與Nginx的變量)。考慮下面的例子,

 location /test { rewrite_by_lua_block { ngx.ctx.foo = 76 } access_by_lua_block { ngx.ctx.foo = ngx.ctx.foo + 3 } content_by_lua_block { ngx.say(ngx.ctx.foo) } }

而後GET /test將產生的輸出:79

即,ngx.ctx.foo條目橫跨重寫,訪問和請求的內容相存在。每一項要求,其中包括子請求,有它本身的表的副本。例如:

location /sub { content_by_lua_block { ngx.say("sub pre: ", ngx.ctx.blah) ngx.ctx.blah = 32 ngx.say("sub post: ", ngx.ctx.blah) } } location /main { content_by_lua_block { ngx.ctx.blah = 73 ngx.say("main pre: ", ngx.ctx.blah) local res = ngx.location.capture("/sub") ngx.print(res.body) ngx.say("main post: ", ngx.ctx.blah) } }

而後GET /main會給輸出:

 main pre: 73 sub pre: nil sub post: 32 main post: 73

在此,改性ngx.ctx.blah的子請求條目不會影響所述一個在父請求。這是由於他們有兩個獨立的版本ngx.ctx.blah。內部重定向會破壞原來的請求ngx.ctx數據(若是有的話)和新要求將有一個空ngx.ctx表。例如:

 location /new { content_by_lua_block { ngx.say(ngx.ctx.foo) } } location /orig { content_by_lua_block { ngx.ctx.foo = "hello" ngx.exec("/new") } }

而後GET /orig會給:nil

而不是原來的"hello"值。任意的數據值,包括Lua的關閉和嵌套表,能夠插入到這個「神奇」的表。它還容許自定義元方法的註冊。覆蓋ngx.ctx用一個新的Lua表也支持,例如:

ngx.ctx = { foo = 32, bar = 54 }

當在上下文中使用init_worker_by_lua *,此表只是有當前的Lua處理程序的壽命相同。

  在ngx.ctx查找須要相對昂貴元方法的調用,這是否是明確傳遞每一個請求的數據沿着本身的函數參數慢得多。因此,不要濫用這個API保存你本身的函數的參數,由於它一般具備很有些性能的影響。由於魔元方法的,歷來沒有「本地」的ngx.ctx上因爲Lua的模塊級的Lua的功能範圍以外的表工做者級的數據共享例如,如下是壞:

-- mymodule.lua
 local _M = {} -- the following line is bad since ngx.ctx is a per-request
 -- data while this <code>ctx</code> variable is on the Lua module level
 -- and thus is per-nginx-worker.
 local ctx = ngx.ctx function _M.main() ctx.foo = "bar"
 end

 return _M

改用如下內容:

 -- mymodule.lua
 local _M = {} function _M.main(ctx) ctx.foo = "bar"
 end

 return _M

也就是說,讓調用者經過ctx代表確地經過一個函數的參數。

 

ngx.location.capture

語法: res = ngx.location.capture(uri, options?)

上下文: rewrite_by_lua *,* access_by_lua,content_by_lua *

是一個同步非阻塞的NGINX子請求uri

NGINX的子請求提供了一個很是強大的方式去實現非阻塞的內部請求,或者其餘的C模塊,好比 ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle, 甚至ngx_lua本身等等。

固然,這些子請求僅僅是模擬HTTP請求,可是並無額外的 HTTP/TCP,全部的進程都是C級別的

子請求徹底不一樣與HTTP 301/302。

這裏有個基本的例子:

res = ngx.location.capture(uri)

返回與4插槽,一個Lua表:res.statusres.headerres.body,和res.truncated

res.status 用於保存子請求響應的響應狀態代碼。

res.header持有子請求的響應頭,這是一個正常的Lua表。對於多值響應頭,該值是保存全部的順序它們出現的值的Lua(陣列)表。例如,若是子請求響應報頭包含如下幾行:

返回一個LUA的TABLE,三個值(res.status, res.header, and res.body)。

res.header包含了全部的子請求的頭的信息,它是一個普通的LUA TABLE。好比多個值的相應頭,他們以數組的形式按照順序返回出現。例如:子請求包含了以下信息:

 Set-Cookie: a=3 Set-Cookie: foo=bar Set-Cookie: baz=blah

而後res.header["Set-Cookie"]將被評估,以表中的值 {"a=3", "foo=bar", "baz=blah"}

  res.body持有子請求的響應體數據,這些數據可能會被截斷。你老是須要檢查res.truncated布爾標誌,看是否res.body包含截斷數據。這裏的數據截斷只能由那些不可恢復的錯誤在你的子請求同樣,遠端停止在響應體數據流的中間,或當你的子請求接收從響應體數據的讀取超時發生過早的鏈接的狀況下形成的遙控器。URI查詢串能夠串聯到的URI自己,例如:

res = ngx.location.capture('/foo/bar?a=3&b=4')

像名爲位置@foo不容許因爲nginx的核心的限制。使用與組合正常位置internal指令準備僅供內部使用的位置。

可選選項表能夠喂的第二個參數,它支持的選項:

  • method 指定子請求的請求方法,只接受常量同樣ngx.HTTP_POST
  • body 指定子請求的請求體(僅字符串值)。
  • args 指定子請求的URI查詢參數(這兩個字符串值和Lua表被接受)
  • ctx 指定一個Lua表是ngx.ctx爲子請求表。它能夠是當前請求的ngx.ctx表,這有效地使母體和其子請求共享徹底相同的上下文表。此選項最初是在引進v0.3.1rc25發行。
  • vars 採起持有的值設置指定的Nginx變量在子請求做爲此選項的值一個Lua表。此選項最初是在引進v0.3.1rc31發行。
  • copy_all_vars 指定是否在當前請求所討論的子請求的全部的Nginx變量值複製。在子請求nginx的變量的修改將不會影響當前(父)的請求。此選項最初是在引進v0.3.1rc31發行。
  • share_all_vars 指定是否共享的子請求與當前(父)要求全部的Nginx變量。在子請求Nginx的變量的修改將影響當前(父)的請求。啓用此選項可能會致使因不良反作用難以調試問題,被認爲是很差的,有害的。只有啓用該選項,當你徹底知道本身在作什麼。
  • always_forward_body 當設置爲true,當前(父)的請求的請求體老是會被轉發到,若是建立的子請求body未指定選項。不管是經過讀取請求體()ngx.req.read_bodylua_need_request_body上會被直接轉發到子請求不建立子請求(不管請求體數據在內存中緩存或臨時文件緩存)時複製整個請求體數據。默認狀況下,這個選項是false和時body沒有指定選項時,當前的(父)請求的請求體,當子請求取只轉發PUTPOST請求方法。

發出一個POST子請求,例如,能夠作以下:

 res = ngx.location.capture( '/foo/bar', { method = ngx.HTTP_POST, body = 'hello, world' } )

看到比其餘POST HTTP方法的常量方法。該method選項是ngx.HTTP_GET默認。

args選項能夠指定額外的URI參數,例如:

 ngx.location.capture('/foo?a=1', { args = { b = 3, c = ':' } } )

至關於

ngx.location.capture('/foo?a=1&b=3&c=%3a')

也就是說,該方法將根據規則URI參數逃脫鍵和值一塊兒將它們鏈接起來成爲一個完整的查詢字符串。對於做爲經過的Lua表的格式args參數是相同於使用的格式ngx.encode_args方法。該args選項也能夠採起簡單的查詢字符串:

 ngx.location.capture('/foo?a=1', { args = 'b=3&c=%3a' } } )

這在功能上等同於前面的例子。

share_all_vars選項控制是否將當前請求和子請求之間共享nginx的變量。若是此選項設置爲true,那麼當前請求和相關的子請求將共享相同的Nginx變量的做用域。所以,經過一個子請求更改了Nginx的變量將影響到當前的請求。

應當心使用此選項,變量的做用域共享能夠有意想不到的反作用。argsvarscopy_all_vars選項一般優於代替。這個選項被設置爲false默認

location /other { set $dog "$dog world"; echo "$uri dog: $dog"; } location /lua { set $dog 'hello'; content_by_lua_block { res = ngx.location.capture("/other", { share_all_vars = true }); ngx.print(res.body) ngx.say(ngx.var.uri, ": ", ngx.var.dog) } }

訪問位置/lua給:

/other dog: hello world /lua: hello world

copy_all_vars選項提供父請求的Nginx的變量的副本子請求時這樣子請求發出。由這樣子請求對這些變量所作的更改不會影響父請求或任何其餘子請求共享父請求的變量。

 location /other { set $dog "$dog world"; echo "$uri dog: $dog"; } location /lua { set $dog 'hello'; content_by_lua_block { res = ngx.location.capture("/other", { copy_all_vars = true }); ngx.print(res.body) ngx.say(ngx.var.uri, ": ", ngx.var.dog) } }

請求GET /lua將給輸出

/other dog: hello world /lua: hello

請注意,若是二者share_all_varscopy_all_vars都設置爲true,則share_all_vars優先。

除了上述兩個設置,有可能使用在子請求變量的值vars選項。這些變量的變量共享或複製已評估後設置,而且提供了對編碼它們以URL參數,並在Nginx的配置文件反向轉義它們傳遞特定值應用於一個子請求的更有效的方法:

 location /other { content_by_lua_block { ngx.say("dog = ", ngx.var.dog) ngx.say("cat = ", ngx.var.cat) } } location /lua { set $dog ''; set $cat ''; content_by_lua_block { res = ngx.location.capture("/other", { vars = { dog = "hello", cat = 32 }}); ngx.print(res.body) } }

訪問/lua將產生的輸出:

dog = hello cat = 32

ctx選項可用於指定自定義的Lua表做爲ngx.ctx爲子請求表。

 location /sub { content_by_lua_block { ngx.ctx.foo = "bar"; } } location /lua { content_by_lua_block { local ctx = {} res = ngx.location.capture("/sub", { ctx = ctx }) ngx.say(ctx.foo); ngx.say(ngx.ctx.foo); } }

而後請求GET /lua 輸出:

bar nil

另外,也可使用這個ctx選項共享同一ngx.ctx電流(父)請求和子請求之間的表:

 location /sub { content_by_lua_block { ngx.ctx.foo = "bar"; } } location /lua { content_by_lua_block { res = ngx.location.capture("/sub", { ctx = ngx.ctx }) ngx.say(ngx.ctx.foo); } }

請求GET /lua產生的輸出:bar

  注意,經過發出子請求ngx.location.capture默認繼承當前請求的全部請求頭,而這可能對子請求響應意想不到的反作用。例如,使用標準時,ngx_proxy模塊服務子請求,「接受編碼:gzip」中的主要請求頭,可能會致使不能在Lua代碼正確處理gzip壓縮的響應。原始請求頭,應經過設置被忽略 proxy_pass_request_headersoff的子請求的位置。

若是body沒有指定選項,且always_forward_body選項爲false(默認值),POST以及PUT子請求將繼承父請求(若是有的話)的請求主體。

  上有可能爲每個主要請求併發子請求的數目的硬編碼上限。在舊版本Nginx的,下限爲50並行子請求,並在最近的版本中,Nginx的1.1.x開始,這是提升到200併發子請求。當超過此限制時,如下錯誤消息被添加到error.log文件中:

[error] 13983#0: *1 subrequests cycle while processing "/uri"

  極限能夠根據須要經過編輯的定義手動修改NGX_HTTP_MAX_SUBREQUESTS宏中nginx/src/http/ngx_http_request.h在Nginx的源樹文件。請同時參閱限制捕獲由配置位置的其餘模塊的子請求指示

 

ngx.location.capture_multi

ngx.status

ngx.header.HEADER

ngx.resp.get_headers

 

ngx.req.is_internal

 

ngx.req.start_time

語法: secs = ngx.req.start_time()

上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*

返回表示時間戳(包括毫秒做爲小數部分)已建立當前請求時一個浮點數。下面的例子模擬了$request_time變量值(由提供ngx_http_log_module純LUA):

 local request_time = ngx.now() - ngx.req.start_time()

ngx.req.http_version

語法:  num = ngx.req.http_version()

背景: set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *

返回當前請求做爲Lua的數字的HTTP版本號。

當前可能的值是2.0,1.0,1.1和0.9。返回nil了沒法識別的值。

ngx.req.raw_header

語法:  str = ngx.req.raw_header(no_request_line?)

背景: set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *

返回由Nginx的服務器接收到的原始原始的HTTP協議頭。

默認狀況下,請求行和尾隨CR LF終止也將包括在內。例如,

 ngx.print(ngx.req.raw_header())

給出這樣的事情:

GET /t HTTP/1.1 Host: localhost Connection: close Foo: bar

你能夠指定可選的 no_request_line參數做爲true排除從結果的請求行的值。例如

ngx.print(ngx.req.raw_header(true))

輸出是這樣的:

Host: localhost
Connection: close
Foo: bar

此方法不會在HTTP / 2請求工做還沒有

 



CDN 反向代理LiveNode節點,經過Lua腳本操做Redis數據庫實現轉發



URL訪問地址:http://127.0.0.1/hls/4953.m3u8

nginx.conf 配置

     location ~ \/.+\/.+\.(m3u8|ts) { #設置nginx變量 if ($uri ~ \/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)(|-).*\.(m3u8|ts)) { set $app_name $1; set $a $2; } set $stream_id ""; default_type 'text/html'; lua_code_cache on; rewrite_by_lua_file /home/www/lua-tinywan/set_by_file.lua; #echo "stream_id :" $stream_id; proxy_buffering off; proxy_redirect off; proxy_connect_timeout 10; proxy_send_timeout 30; proxy_read_timeout 30; proxy_pass $stream_id; }
set_by_file.lua 添加一下內容:
-- 接受Nginx傳遞進來的參數$1 也就是SteamName
local stream_a = ngx.var.a local redis = require("resty.redis"); -- 建立一個redis對象實例。在失敗,返回nil和描述錯誤的字符串的狀況下
local redis_instance = redis:new(); --設置後續操做的超時(以毫秒爲單位)保護,包括connect方法
redis_instance:set_timeout(1000) --創建鏈接
local ip = '127.0.0.1'
local port = 6379
--嘗試鏈接到redis服務器正在偵聽的遠程主機和端口
local ok,err = redis_instance:connect(ip,port) if not ok then ngx.say("connect redis error : ",err) return err end

-- 權限驗證
local res,err = redis_instance:auth('tinywanredis') if not res then ngx.say("failed to authenticate: ", err) return
end

--數據庫選擇 
redis_instance:select(2) --調用API獲取數據 
local resp, err = redis_instance:hget("StreamLiveNodeInnerIp:"..stream_a,'livenode') if not resp then ngx.say("get msg error : ", err) return err end

--獲得的數據爲空處理 
if resp == ngx.null then ngx.say("this is not redis_data")
    return nil
end ngx.var.stream_id = resp -- ngx.say("reds get result : ", resp)

 思路圖片:

相關文章
相關標籤/搜索