OpenResty部署反向代理

1、應用場景

  • 部署一個proxy做反向代理,根據Http請求中的機房的名字,將請求轉發到不同機房的後端伺服器上。

2、OpenResty

官網上是這麼解釋的: OpenResty effectively turns the nginx server into a powerful web app server, in which the web developers can use the Lua programming language to script various existing nginx C modules and Lua modules and construct extremely high-performance web applications that are capable to handle 10K ~ 1000K+ connections in a single box

我自己的理解是:OpenResty包含兩個東西,Nginx和LuaJIT。藉助於Nignx可以進行非阻塞的方式處理請求,然後通過Lua的腳本對接收到的請求進行處理,比如確定請求發往的目的伺服器。

現在開始我們的實踐,首先描述下實驗中Http請求的頭部格式。然後展示下nginx的配置、lua腳本、upstream的配置。

3、請求頭部

這裡的Zone是必備參數,

url: XX.api.ucloud.cnRequest:{ "Action":"GetNetTC", "EIP":"120.132.6.X", "Zone": "cn-sh2-01", #必備參數,需要根據Zone將請求轉發到對應機房的伺服器上 "Backend": "UNetTool",}

4、文件目錄

  1. conf: nignx和unet-tool伺服器的配置文件
  2. lua-script: lua的兩個腳本文件
  3. fabfile.py: 自動部署的python腳本

5、Nignx配置

Nignx配置文件中除了指定監聽埠、日誌位置等,還需要配置proxy_pass,其值是由lua-script/main.lua確定的。

worker_processes 4;pid logs/nginx.pid;error_log logs/error.log info;events { worker_connections 2048;}http { log_format upstream $time_iso8601 $remote_addr $host $request_time $upstream_response_time $request $request_body $status $upstream_addr; # lua settings lua_package_path lua-script/?.lua;;; # region upstream include upstreams.conf; #引入各機房伺服器的配置 server { listen 0.0.0.0:2003; #部署腳本中會將0.0.0.0替換成proxy的Ip地址。 access_log logs/unettool-proxy-access.log upstream; error_log logs/unettool-proxy-error.log; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Connection ""; proxy_http_version 1.1; set $backend ; #定義一個變數backend rewrite_by_lua_file lua-script/main.lua; #更新變數backend proxy_pass http://$backend; #將請求發往backend error_page 500 502 = @backend_error; } location @backend_error { content_by_lua_file lua-script/backend_error.lua; } }}

6、Lua腳本

  1. mian.lua是用途是確定某個請求發往哪個後端的,將結果賦值給backend。部分代碼如下所示

  2. 最重要的代碼其實只有兩行,根據請求頭部的zone,得到_upstream的名字,然後賦值給變數backend

_upstream = unettool-proxy-..tostring(zone) ngx.var.backend = _upstream

function _send_error_response(err) -- 一些設置 ngx.say({"RetCode": 230, "Message": "Param [Zone] is required"})endfunction _get_req_params() local method_name = ngx.req.get_method() local args = {} local err = nil if method_name == GET then args = ngx.req.get_uri_args() elseif method_name == POST then ngx.req.read_body() local content_type = ngx.req.get_headers()[Content-Type] if content_type == application/x-www-form-urlencoded then args, err = ngx.req.get_post_args() elseif content_type == application/json then args, err = ngx.req.get_body_data() if args ~= ngx.null then args = cjson.decode(args) end end end return argsendlocal args = _get_req_params()if args == nil then _send_error_response(fetch request params error) returnendlocal action = args[Action]local zone = args[Zone]if zone == nil or zone == then _send_error_response(missing Zone) returnend_upstream = unettool-proxy-..tostring(zone)if _upstream == nil or _upstream == then _send_error_response(Zone or SrcZone is illegal) return endngx.var.backend = _upstream

7、Upstream的配置

示例如下:

upstream unettool-proxy-cn-bj1-01{ keepalive 1000; server 172.X.X.X:2003;}upstream unettool-proxy-cn-sh2-01{ keepalive 1000; server 172.X.X.X:2003;}upstream unettool-proxy-cn-sh2-02{ keepalive 1000; server 172.X.X.X:2003;}

到這裡基本上,就算完成了,為了方便我們快速部署,寫了一個簡單的fabfile文件。

8、fabfile自動部署

這一步沒什麼可說的,就是用python的fabric庫執行一些遠程和本地的命令。

#! /usr/bin/env pythonfrom fabric.api import local,env,run,local,settings,putenv.hosts=[172.X.X.X, 172.X.X.X]def deploy(branch=from_dezho,tag=v0.1): code_dir = /data/unet-tool local_tmp_code_dir = ~/tmp/unet-tool put(openresty-1.9.15.1.tar.gz, /tmp) run(cd /tmp/ && tar xvf openresty-1.9.15.1.tar.gz) run(yum install pcre) run(yum install readline-devel pcre-devel openssl-devel gcc) run(cd /tmp/openresty-1.9.15.1 && ./configure && make && make install) local(tar cf unettool-proxy.tar ../unettool-proxy --exclude openresty-1.9.15.1.tar.gz) put(./unettool-proxy.tar, /data/) run(cd /data/unettool-proxy/ && /usr/local/openresty/nginx/sbin/nginx -p /data/unettool-proxy/ -c conf/nginx.conf -s stop) run(rm -rf /data/unettool-proxy) run(cd /data && tar xf unettool-proxy.tar) run(rm /data/unettool-proxy.tar) run(sed -i "s/0.0.0.0/%s/g" /data/unettool-proxy/conf/nginx.conf % env.host ) run(cd /data/unettool-proxy/ && /usr/local/openresty/nginx/sbin/nginx -p /data/unettool-proxy/ -c conf/nginx.conf)def updateUpstreamConf(): put(conf/upstreams.conf, /data/unettool-proxy/conf/) run(cd /data/unettool-proxy/ && /usr/local/openresty/nginx/sbin/nginx -p /data/unettool-proxy/ -c conf/nginx.conf -s stop) run(cd /data/unettool-proxy/ && /usr/local/openresty/nginx/sbin/nginx -p /data/unettool-proxy/ -c conf/nginx.conf)

推薦閱讀:

Kong - The Microservice API Gateway
nginx為什麼性能這麼優越?
為什麼考慮到溢出用減法來比較更好?
Nginx支持ASP.net嗎?
10 分鐘內快速構建能夠承載海量數據的 NGINX 日誌分析與報警平台

TAG:Python | Nginx | OpenResty |