当前位置 主页 > 服务器问题 > nginx问题汇总 >

    利用nginx+lua+redis实现反向代理方法教程

    栏目:nginx问题汇总 时间:2019-02-28 16:29

    这篇文章主要给大家介绍了利用nginx+lua+redis实现反向代理方法教程,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。

    前言

    最近因为工作需要,要进行IVR的重构, 我们现在系统接了三家IVR服务商, N个业务, 由于IVR这玩意一般只能外网回调, 而开发环境又不允许外网随便访问,

    着实烦人。 所有我们打算重构一把, 封装多家IVR, 对业务透明, 同时回调可以针对多家IVR服务商的不同callid直接转发到当时请求的同学的

    开发域名去。

    而不同的IVR服务商的callid参数是不同的,有的是在url里面(call_id), 有的则是直接post的json数据(callid), 所以太扯了。

    直接用lua处理下, 查下redis里面这个callid当时是哪位同学发起的请求(请求IVR的时候会写入redis中), 直接proxy_pass到这位同学的开发域名去就ok了。

    环境部署

    环境直接用openresty吧, redis、json这些常用库都已经打包完毕, 也可以自己安装, 就是太麻烦。

    openresty

    nginx配置

    新建一个vhost, 配置如下

    server { server_name ivr.com;             access_log /home/work/log/nginx/access.ivr.log; error_log /home/work/log/nginx/error.ivr.log; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Protocol $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 30;  proxy_connect_timeout 10;  location /ivr/ { lua_code_cache off; resolver 8.8.8.8; set $backend '';  rewrite_by_lua_file /home/work/tengine-2.1.0/conf/lua/ivr.lua; proxy_pass http://$backend; } } 

    不加resolver的话可能会报错, 无法解析,加一个8.8.8.8就可以搞定了。

    lua_code_cache 是开发环境的配置, 不缓存lua代码, 修改完lua直接生效, 不然每次要重启nginx, 上生产环境要关掉, 严重影响性能。

    不过我们这个需求主要是针对开发环境, 所以无所谓。

    lua代码

    local redis = require "resty.redis"local cjson = require "cjson"local cache = redis.new()cache.connect(cache, '127.0.0.1', '6379')local args = ngx.req.get_uri_args()local uri = ngx.var.request_urilocal callid = nillocal channel = 0if string.find(uri, 'yuntongxun') then callid = args["callid"] channel = 0elseif string.find(uri, 'yunhu') then ngx.req.read_body() local body_data = ngx.req.get_body_data() local data = cjson.decode(body_data) callid = data['call_id'] channel = 1elseif string.find(uri, 'huawei') then callid = args["vSessionsId"] channel = 2else endif callid == nil then ngx.say(uri) ngx.say(cjson.encode(args)) ngx.say('callid is empty') return ''endlocal key = callid .. '_channel' .. channellocal res = cache:get(key)if res == ngx.null then ngx.say("cache get error") return ''endngx.var.backend = res

    没啥特别的, 针对多个IVR服务商, 进行解析callid, 然后拼成一个key, 去redis中查询整个key当时写入的value(开发者域名),

    最后设置backend整个参数, 然后由nginx进行proxy_pass就完了。