更新時(shí)間:2020-10-13 來(lái)源:黑馬程序員 瀏覽量:
和一般的Web 
Server類似,我們需要接收請(qǐng)求、處理并輸出響應(yīng)。而對(duì)于請(qǐng)求我們需要獲取如請(qǐng)求參數(shù)、請(qǐng)求頭、Body體等信息;而對(duì)于處理就是調(diào)用相應(yīng)的Lua代碼即可;輸出響應(yīng)需要進(jìn)行響應(yīng)狀態(tài)碼、響應(yīng)頭和響應(yīng)內(nèi)容體的輸出。因此我們從如上幾個(gè)點(diǎn)出發(fā)即可。
獲取nginx變量:ngx.var
 server {
        listen 8080;
        location / {
        	#定義nginx變量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
            	local var = ngx.var; -- 獲取nginx變量
				ngx.say("ngx.var.b : ", var.b, "<br/>")
				ngx.var.b = 2; -- 設(shè)置變量值
				ngx.say("ngx.var.b : ", var.b, "<br/>")
				ngx.say("<br/>")
            }
        }
    }
獲取請(qǐng)求頭:ngx.req.get_headers()
server {
        listen 8080;
        location / {
        	#定義nginx變量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
				local headers = ngx.req.get_headers()
				ngx.say("headers begin", "<br/>")
				ngx.say("Host : ", headers["Host"], "<br/>")
				ngx.say("user-agent : ", headers["user-agent"], "<br/>")
				ngx.say("user-agent : ", headers.user_agent, "<br/>")
				ngx.say("=======================================","</br>")				
				for k,v in pairs(headers) do
					if type(v) == "table" then
						ngx.say(k, " : ", table.concat(v, ","), "<br/>")
					else
						ngx.say(k, " : ", v, "<br/>")
					end
				end
				ngx.say("headers end", "<br/>")
				ngx.say("<br/>")
            }
        }
    }get請(qǐng)求uri參數(shù):ngx.req.get_uri_args()
server {
        listen 8080;
        location / {
        	#定義nginx變量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
				ngx.say("uri args begin", "<br/>")
				local uri_args = ngx.req.get_uri_args()
				ngx.say("param:username=",uri_args['username'], "<br/>")
				ngx.say("param:password=",uri_args['password'], "<br/>")
				ngx.say("uri args end", "<br/>")
				ngx.say("<br/>")
            }
        }
    }
post請(qǐng)求參數(shù):ngx.req.get_post_args()
server {
        listen 8080;
        location / {
        	#定義nginx變量	
			set $b $host;
			
            default_type text/html;
            content_by_lua_block {
				ngx.say("uri args begin", "<br/>")
				-- 獲取請(qǐng)求體中的數(shù)據(jù)
				ngx.req.read_body()
				local uri_args = ngx.req.get_post_args() --獲取key-value格式的數(shù)據(jù)
				ngx.say("param:username=",uri_args['username'], "<br/>")
				ngx.say("param:password=",uri_args['password'], "<br/>")
				ngx.say("uri args end", "<br/>")
				ngx.say("<br/>")
            }
        }
    }其他請(qǐng)求相關(guān)的方法:
獲取請(qǐng)求的http協(xié)議版本:ngx.req.http_version()
獲取請(qǐng)求方法:ngx.req.get_method()
獲取請(qǐng)求頭內(nèi)容:ngx.req.get_headers()
獲取請(qǐng)求的body內(nèi)容體:ngx.req.get_body_data()
 server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
				--寫響應(yīng)頭
				ngx.header.a = "1"
				--多個(gè)響應(yīng)頭可以使用table
				ngx.header.b = {"2", "3"}
				--輸出響應(yīng)
				ngx.say("a", "b", "<br/>")
				ngx.print("c", "d", "<br/>")
				--200狀態(tài)碼退出
				return ngx.exit(200)
            }
        }
    }
}響應(yīng)相關(guān)方法:
ngx.header.xx = yy:輸出響應(yīng)頭;
ngx.print():輸出響應(yīng)內(nèi)容體;
ngx.say():同ngx.print()一樣,但是會(huì)最后輸出一個(gè)換行符;
ngx.exit():指定狀態(tài)碼退出;
ngx.send_headers():發(fā)送響應(yīng)狀態(tài)碼,當(dāng)調(diào)用ngx.say/ngx.print時(shí)自動(dòng)發(fā)送響應(yīng)狀態(tài)碼;
ngx.headers_sent( ): 判斷是否發(fā)送了響應(yīng)狀態(tài)碼。
重定向
 server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
				ngx.redirect("http://jd.com", 302);  
            }
        }
    }使用過(guò)如Java的朋友可能知道如Ehcache等這種進(jìn)程內(nèi)本地緩存,Nginx是一個(gè)Master進(jìn)程多個(gè)Worker進(jìn)程的工作方式,因此我們可能需要在多個(gè)Worker進(jìn)程中共享數(shù)據(jù),那么此時(shí)就可以使用ngx.shared.DICT來(lái)實(shí)現(xiàn)全局內(nèi)存共享。
1、首先在nginx.conf的http部分定義一個(gè)全局內(nèi)存,并指定內(nèi)存大小。
#共享全局變量,在所有worker間共享,如下:定義了一個(gè)名為shared_data的全局內(nèi)存,大小為1m lua_shared_dict shared_data 1m;
2、使用全局內(nèi)存
 server {	
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
				--1、獲取全局共享內(nèi)存變量
				local shared_data = ngx.shared.shared_data
				--2、獲取字典值
				local i = shared_data:get("i")
				if not i then
					i = 1
					--3、惰性賦值
					shared_data:set("i", i)
					ngx.say("lazy set i ", i, "<br/>")
				end
				--遞增
				i = shared_data:incr("i", 1)
				ngx.say("i=", i, "<br/>")
            }
        }
    }3、全局內(nèi)存常用方法介紹
ngx.shared.DICT
獲取共享內(nèi)存字典項(xiàng)對(duì)象
語(yǔ)法:dict = ngx.shared.DICT dict = ngx.shared[name_var] 其中,DICT和name_var表示的名稱是一致的,比如上面例子中,shared_data = ngx.shared.shared_data 就是dict = ngx.shared.DICT的表達(dá)形式, 也可以通過(guò)下面的方式達(dá)到同樣的目的: shared_data = ngx.shared['shared_data']
ngx.shared.DICT:get(key)
獲取共享內(nèi)存上key對(duì)應(yīng)的值。如果key不存在,或者key已經(jīng)過(guò)期,將會(huì)返回nil;如果出現(xiàn)錯(cuò)誤,那么將會(huì)返回nil以及錯(cuò)誤信息。
ngx.shared.DICT:get_stale(key)
與get方法類似,區(qū)別在于該方法對(duì)于過(guò)期的key也會(huì)返回,第三個(gè)返回參數(shù)表明返回的key的值是否已經(jīng)過(guò)期,true表示過(guò)期,false表示沒有過(guò)期。
ngx.shared.DICT:set(key, value, exptime?, flags?)
“無(wú)條件”地往共享內(nèi)存上插入key-value對(duì),這里講的“無(wú)條件”指的是不管待插入的共享內(nèi)存上是否已經(jīng)存在相同的key。
三個(gè)返回值的含義:
success:成功插入為true,插入失敗為false
err:操作失敗時(shí)的錯(cuò)誤信息,可能類似"no memory"
forcible:true表明需要通過(guò)強(qiáng)制刪除(LRU算法)共享內(nèi)存上其他字典項(xiàng)來(lái)實(shí)現(xiàn)插入,false表明沒有刪除共享內(nèi)存上的字典項(xiàng)來(lái)實(shí)現(xiàn)插入。
exptime參數(shù)表明key的有效期時(shí)間,單位是秒(s),默認(rèn)值為0,表明永遠(yuǎn)不會(huì)過(guò)期;
flags參數(shù)是一個(gè)用戶標(biāo)志值,會(huì)在調(diào)用get方法時(shí)同時(shí)獲取得到
ngx.shared.DICT.safe_set(key, value, exptime?, flags?)
與set方法類似,區(qū)別在于不會(huì)在共享內(nèi)存用完的情況下,通過(guò)強(qiáng)制刪除(LRU算法)的方法實(shí)現(xiàn)插入。如果內(nèi)存不足,會(huì)直接返回nil和err信息"no 
memory"
ngx.shared.DICT.add(key, value, exptime?, flags?)
與set方法類似,與set方法區(qū)別在于不會(huì)插入重復(fù)的鍵(可以簡(jiǎn)單認(rèn)為add方法是set方法的一個(gè)子方法),如果待插入的key已經(jīng)存在,將會(huì)返回nil和和err="exists"
ngx.shared.DICT.safe_add(key, value, exptime?, flags?)
與safe_set方法類似,區(qū)別在于不會(huì)插入重復(fù)的鍵(可以簡(jiǎn)單認(rèn)為safe_add方法是safe_set方法的一個(gè)子方法),如果待插入的key已經(jīng)存在,將會(huì)返回nil和和err="exists"
ngx.shared.DICT.replace(key, value, exptime?, flags?)
與set方法類似,區(qū)別在于只對(duì)已經(jīng)存在的key進(jìn)行操作(可以簡(jiǎn)單認(rèn)為replace方法是set方法的一個(gè)子方法),如果待插入的key在字典上不存在,將會(huì)返回nil和錯(cuò)誤信息"not 
found"
ngx.shared.DICT.delete(key)
無(wú)條件刪除指定的key-value對(duì),其等價(jià)于ngx.shared.DICT:set(key, nil)
ngx.shared.DICT.incr(key, value)
對(duì)key對(duì)應(yīng)的值進(jìn)行增量操作,增量值是value,其中value的值可以是一個(gè)正數(shù),0,也可以是一個(gè)負(fù)數(shù)。value必須是一個(gè)Lua類型中的number類型,否則將會(huì)返回nil和"not 
a number";key必須是一個(gè)已經(jīng)存在于共享內(nèi)存中的key,否則將會(huì)返回nil和"not found".
ngx.shared.DICT.flush_all()
清除字典上的所有字段,但不會(huì)真正釋放掉字段所占用的內(nèi)存,而僅僅是將每個(gè)字段標(biāo)志為過(guò)期。
ngx.shared.DICT.flush_expired(max_count?)
清除字典上過(guò)期的字段,max_count表明上限值,如果為0或者沒有給出,表明需要清除所有過(guò)期的字段,返回值flushed是實(shí)際刪除掉的過(guò)期字段的數(shù)目。
注意:
與flush_all方法的區(qū)別在于,該方法將會(huì)釋放掉過(guò)期字段所占用的內(nèi)存
ngx.shared.DICT.get_keys(max_count?)
從字典上獲取字段列表,個(gè)數(shù)為max_count,如果為0或沒有給出,表明不限定個(gè)數(shù)。默認(rèn)值是1024個(gè)
注意:
強(qiáng)烈建議在調(diào)用該方法時(shí),指定一個(gè)max_count參數(shù),因?yàn)樵趉eys數(shù)量很大的情況下,如果不指定max_count的值,可能會(huì)導(dǎo)致字典被鎖定,從而阻塞試圖訪問字典的worker進(jìn)程。
猜你喜歡: