OpenResty 反向代理的用法與技巧
OpenResty中使用反向代理
導語:
一、基本用法
在業務環境中,可能會將OpenResty(以后簡稱OR)作為反向代理,根據不同的location定位到不同的后端,在這樣的架構下,對應的反向代理配置可能是這樣的:
location /upstream_A { proxy_pass http://192.168.1.100:8080; proxy_connect_timeout 2s; ... } location /upstream_B { proxy_pass http://192.168.1.110:8080; proxy_connect_timeout 2s; ... }
可以看到這部分的配置和Nginx并沒有太大差別,但是這樣的配置會有一些問題,比如我們需要切換后端服務器,將upstream_A這個location的流量打到192.168.1.120這個上游地址而不用修改配置或者重啟Nginx服務,大部分人可能會選擇通過域名的方式去定位上游比如用如下配置:
location /upstream_A { proxy_pass http://domain_for_upstream_A:8080; proxy_connect_timeout 2s; ... } location /upstream_B { proxy_pass http://domain_for_upstream_B:8080; proxy_connect_timeout 2s; ... }
當需要做_上游切換_的時候,通過修改 /etc/host 文件來將域名定向到新的Ip,但不幸的是,Ngixn并不會使用/etc/host 而是使用命令resolver來指定DNS服務器,那么在OR里面有沒有一些高階的用法可以讓上游漂移變得簡單呢?答案是肯定的,下面就來看看更加方便的用法,以及里面的坑。
二、進階用法
上面呢我們講到如何使用OR(其實就用到了Nginx的配置啦)來完成反向代理,但是由于Ip或者域名寫死,而Nginx又不支持host,所以在做上游平滑遷移的時候不是很方便,所以我們可以通過在上游配置中用Nginx變量來代替上游的地址,變可以避免上述問題。
location /internet_prxoy { internal; set_by_lua $query_url 'return ngx.unescape_uri(ngx.var.arg_url);' proxy_pass $query_url; } location /upstream_A { content_by_lua ' local redis_op = require "lua.redis_op" local upstream_addr = redis_op.get_upstream_from_redis() -- 從redis中獲取上游地址 local url = 'http://'.. upstream_addr .. '/foo/bar' local res = ngx.location.capture('/internet_proxy', { args = {url = url}} ) --容錯判斷 ngx.print(res.body) '; }
這樣,當請求訪問到/upstream_A的時候,會在redis當中讀取到上游服務器的真實地址并通過/internet_prxoy轉發到上游。
看到這里有人可能會問,為什么需要配置一個額外的跳轉location,而不直接在set_by_lua階段訪問redis并對Nginx變量進行賦值?
原因是函數get_upstream_from_redis會涉及到redis的訪問,而 lua-resty-redis 使用了 ngx.socket.tcp 這個函數,這個函數所支持的執行階段不包括_set_階段,需要我們需要一次跳轉,通過第一次location的content階段從redis中將數據讀取出來,在第二個location的set階段利用剛才所讀取的數據完成反向代理。
需要注意的是如果第一次location,(也就是上述代碼中的/upstream_A)的流量非常高,那么可以在redis的訪問函數,也就是上述代碼中的get_upstream_from_redis()函數中用shared.dict來做一次緩存,減少對redis的訪問量也是可行的。