Nginx 向客戶端輸出真實的后端IP地址


因為涉及到內外網的改造,所以狠多東西現在需要依賴於openresty來做總控實現。然后就碰見了一個比較難辦的問題,即在upstream時候,如何獲取實際處理請求的server地址。假設有如下upstream配置:

upstream backend {
server 127.0.0.1:88882
server 127.0.0.1:88892
}

location /test {
proxy_pass http://backend2
}

 

當我請求test的時候,我同時想直到到底是backend的哪一個server處理了,也就是我想得到實際處理的server地址。對於這個問題,我想了狠久,也走了狠多彎路,浪費了不少時間。

server return local ip?
首先,最簡單的做法,就是對於實際的upstream server,在處理test這個請求的時候返回自己的ip地址就可以了,不過這種方法通用性太差,並且如果該server有多ip,可能取得的本機ip跟upstream里面配置的還不一樣。

get upstream conf module?
然后,我想是不是nginx提供了一個模塊,能夠讀取conf解析之后的所有信息,對這個模塊的查找讓我走了彎路,google了一下,發現沒有相關東西,我還狠sb的一直不停的搜索。也不想想即使有這樣的模塊,如果我想要實現這個功能也是一件不怎么容易的事情。

upstream_addr
等到走了一些彎路,才發現nginx的upstream本來就有一個upstream_addr的模塊,一下子我覺得找到了方向,不過看這個變量的說明,發現它主要用在記錄log上面,而且沒說明外界如何獲取。查了一些資料之后,發現nginx有一個add_header,該指令干的事情就是在http response header里面加入自己定義的header,於是我在conf里面添加了這條指令,如下:

locaiton /test {
add_header Kss-Upstream $upstream_addr
proxy_pass http://backend2
}

這樣,當我訪問test的時候,response header里面就會有響應server的地址。

request:
curl -i http://127.0.0.1/test

response:

HTTP/1.1 200 OK
Kss-Upstream: 127.0.0.1:8888
subrequest response header
如果直接請求test,會狠好的得到upstream的addr,但是,如果是subrequest請求,就發現得不到了,如下:

location /test1 {
local res = ngx.location.capture("/test")
ngx.say(res.header["Kss-Upstream"])
}

請求test1的時候,發現subrequest的response header里面根本沒有Kss-Upstream這個字段。當時狠迷惑,google之后發現這個:Headers not returned from subrequest,原來,subrequest的header是不會返回到parent request這個層面的。至於如何處理,我按照上面的說明采用了兩種做法,發現都可行。

more_set_headers
agentzh舉了more_set_headers這種做法的一個例子,直接把add_header換成more_set_headers "Kss-Upstream: $upstream_addr"2這條語句搞定。

header_filter_by_lua
另一個做法就是使用header_filter_by_lua這個指令,該指令是處理header response filter的,在里面將upstream_addr的值設置到nginx的一個變量里面。如下:

location /test {
proxy_pass http://_test2
header_filter_by_lua 1
ngx.var.upaddr = ngx.var.upstream_addr
12
}

location /test1 {
set $upaddr 112
content_by_lua 1
local res = ngx.location.capture("/test", {share_all_vars = true})
ngx.say(ngx.var.upaddr)
12
}

對於這種方式,實現較為繁瑣,首先需要定義一個變量用來存儲upstream_addr的值,同時在capture的時候還需要設置share_all_vars為true。鑒於此,還是使用more_set_headers這條語句方便狠多。

后來我又實現了一下,發現沒必要這么復雜,完全可以不需要變量傳遞,只是在header_filter_by_lua里面這么做就可以了

header_filter_by_lua 1
ngx.header.kss_upstream_add = ngx.var.upstream_addr

記錄下,送給不知道的朋友!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM