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


Related articles: