• OpenResty 反向代理的用法与技巧


    Nginx最开始是作为反向代理被熟知的,基于它的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的访问量也是可行的。

  • 相关阅读:
    java 通过Iterator输出Map
    java SortedSet接口swap方法
    java vector
    java Iterator双向迭代输出
    java 序列化和反序列化多个对象
    培训
    每天晚上

    又想起了

  • 原文地址:https://www.cnblogs.com/archoncap/p/5045051.html
Copyright © 2020-2023  润新知