OpenResty 反向代理的用法與技巧

OpenResty中使用反向代理

導語:

Nginx最開始是做爲反向代理被熟知的,基於它的OpenResty的天然也是支持反向代理的,下面咱們就來看看它的一些基本用法以及在使用過程當中的一些技巧。nginx

1、基本用法


在業務環境中,可能會將OpenResty(之後簡稱OR)做爲反向代理,根據不一樣的location定位到不一樣的後端,在這樣的架構下,對應的反向代理配置多是這樣的:git

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服務,大部分人可能會選擇經過域名的方式去定位上游好比用以下配置:github

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裏面有沒有一些高階的用法可讓上游漂移變得簡單呢?答案是確定的,下面就來看看更加方便的用法,以及裏面的坑。redis

2、進階用法


上面呢咱們講到如何使用OR(其實就用到了Nginx的配置啦)來完成反向代理,可是因爲Ip或者域名寫死,而Nginx又不支持host,因此在作上游平滑遷移的時候不是很方便,因此咱們能夠經過在上游配置中用Nginx變量來代替上游的地址,變能夠避免上述問題。後端

location /internet_proxy {
    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的訪問量也是可行的。dom

相關文章
相關標籤/搜索