首页nginx
Ad7bc863acc50ad3b747c51c2f85b431

Nginx 向客户端输出真实的后端 IP 地址

Chalin发布于376 次阅读
因为涉及到内外网的改造,所以狠多东西现在需要依赖于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_addr2
    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

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条评论
暂无评论~~
相关小书
nginx教程

nginx教程

最全面,最深入的nginx入门到精通的教程

发表于

喜欢