Implement the reverse proxy method tutorial with nginx+lua+redis
- 2020-05-13 04:32:30
- OfStack
preface
Recently, due to the need of work, we need to reconstruct IVR. Now we have three IVR service providers and N businesses in the system. Because IVR can only callback from the external network like 1, and the development environment does not allow the external network to access.
It's really annoying. Therefore, we plan to refactor 1, encapsulate multiple IVR, which is transparent to the business. Meanwhile, the callback can be directly forwarded to the requested students for different callid of multiple IVR service providers
Develop a domain name.
The callid parameters of different IVR service providers are different, some are in url (call_id), and some are directly post's json data (callid), so it is too ridiculous.
Directly use lua for processing, check which student initiated the request of callid in redis (it will be written into redis when requesting IVR), and directly go to ok for proxy_pass's domain name development.
The deployment environment
The environment directly USES openresty, redis, json, these common libraries have been packaged, you can also install their own, but it is too troublesome.
openresty
nginx configuration
Create a new vhost and configure it as follows
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;
}
}
If you do not add resolver, you may report an error, which cannot be resolved. If you add one 8.8.8.8, you can solve it.
lua_code_cache is the configuration of the development environment. It does not cache the lua code. After the modification of lua, it will take effect directly.
But our requirement is primarily for the development environment, so it doesn't matter.
lua code
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_uri
local callid = nil
local channel = 0
if string.find(uri, 'yuntongxun') then
callid = args["callid"]
channel = 0
elseif 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 = 1
elseif string.find(uri, 'huawei') then
callid = args["vSessionsId"]
channel = 2
else
end
if callid == nil then
ngx.say(uri)
ngx.say(cjson.encode(args))
ngx.say('callid is empty')
return ''
end
local key = callid .. '_channel' .. channel
local res = cache:get(key)
if res == ngx.null then
ngx.say("cache get error")
return ''
end
ngx.var.backend = res
Nothing special, for multiple IVR service providers, parse callid, and then spell it into 1 key, go to redis and query the value(developer domain name) that key wrote at that time.
Finally, the whole parameter of backend is set, and then proxy_pass is done by nginx.
conclusion