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

相关文章
相关标签/搜索