美文网首页docker and K8S
OpenResty实现动态路由

OpenResty实现动态路由

作者: 猴子精h | 来源:发表于2018-07-09 15:38 被阅读366次

    什么是路由

    这里所说的「路由」不是用在网络中的概念,而是在 web 开发中,访问路径以及具体的内容映射。比如,访问 /a 映射到某个具体的页面,这个就称为一个路由。动态路由,顾名思义就是动态地添加这种映射关系。

    OpenResty 中定义路由

    对于 OpenResty (Nginx) 来说,得益于它强劲的性能,常常用来当作反向代理网关。通过它强大的 location 配置将不同的 /$request_uri 转发到不同的后端服务中,这样的转发关系也就是我们这里要说到的「路由」:

    ...
    localtion = /a {
        ...
        proxy_pass http://$server_a;
    }
    
    location = /b {
        ....
        proxy_pass http://$server_b;
    }
    

    但是这些关系必须写死在配置文件中,当有后端有服务变更就需要手动地修改配置文件并 reload 使配置生效。这样的操作在今天以容器作为服务的载体下就显得异常的繁琐了,容器的生命周期通常来说是短暂的,一旦容器发生变动就需要去手动修改配置。

    通过 Lua + Redis 实现动态路由

    应用场景

    该方案是将原来定义 upstream 中的 server_ip 存放在 redis 中,通过 lua 去读取后直接 proxy_pass,这样做其实是损失了 Nginx 中 upstream 中的负载均衡算法,心跳机制,所有应用场景存在一定的局限性,就是 proxy_pass 的 server_ip 是一个 LB 的地址,这个 LB 上实现了原来由 Nginx upstream 中实现的负载均衡和心跳机制。有个好消息就是这样的方案就非常适合现在的 Kubernetes 架构了,Kubernetes 中的 Service 对象产生的 cluster_ip 正是一个 LB 的 IP。

    lua+redis实现动态路由.png
    1. 使用 ngx_redis2 模块来读取 redis 实现读取 redis 的接口,并在 location 中配置 internal 保护这个接口只运行内部调用。
    location = /redis {
        internal;
        set_unescape_uri $key $arg_key;
        redis2_query get $key;
        redis2_pass 192.168.4.182:6379;
    }
    
    1. 使用 ngx.location.capture 来调用内部接口,它可以发起非阻塞的内部请求访问目标 location。
    location = /app1 {
        resolver 114.114.114.114;
        set $target '';
        default_type "text/html";
    
        access_by_lua_block {
            local rds_key = "app1"
            # 从 redis 中获取 key 为 app1 对应的 server_ip
            local res = ngx.location.capture('/get_redis', { args = {key = rds_key}})
    
            local parser = require("redis.parser")
            local server, typ = parser.parse_reply(res.body)
            if typ ~= parser.BULK_REPLY or not server then
                ngx.log(ngx.ERR, "bad redis response: ", res.body)
                ngx.exit(500)
            end
    
            ngx.var.target = server
        }
    
        proxy_pass http://$target;
    }
    

    关于性能

    该方案每次请求都会去请求一次 redis网上有人使用本地缓存 + redis 缓存来提升性能,具体看这里

    相关文章

      网友评论

        本文标题:OpenResty实现动态路由

        本文链接:https://www.haomeiwen.com/subject/ashtpftx.html