nginx-openresty实现中间件

nginx-openresty实现中间件

nginx-openresty实现中间件

注意

在正式ngx.exec()时,绝对不能输出任何东西,比如 ngx.say("debug"),否则将陷入重定向之中

日志会不断的提示attempt to call ngx.exec after sending out response headers

这应该是一个常识性问题,都知道在header不能输出任何东西,我居然忘了,,,折腾半天.

安装

  • Mac

默认安装目录/usr/local/Cellar/openresty/1.15.8.2

brew install openresty/brew/openresty

如果你用Mac遇到了如下错误信息

make[1]: *** [lj_folddef.h] Segmentation fault: 11
make[1]: *** Deleting file `lj_folddef.h"
make[1]: *** Waiting for unfinished jobs....
make: *** [default] Error 2
ERROR: failed to run command: gmake -j8 TARGET_STRIP=@: CCDEBUG=-g XCFLAGS="-msse4.2 -DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT" CC=cc PREFIX=/usr/local/Cellar/openresty/1.15.8.2/luajit

If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
  https://github.com/openresty/homebrew-brew/issues

These open issues may also help:
The openresty-debug package should use openresty-openssl-debug instead https://github.com/openresty/homebrew-brew/issues/3
Fails to install OpenResty https://github.com/openresty/homebrew-brew/issues/5
Can"t install openresty on macOS 10.15 https://github.com/openresty/homebrew-brew/issues/10

Error: A newer Command Line Tools release is available.
Update them from Software Update in System Preferences or
https://developer.apple.com/download/more/.

去这里 apple官网开发插件下载 下载最新的Xcode command line tools即可, 脑袋糊涂了,折腾一晚上下载不下来,还以为官方资源有问题,原来是迅雷的问题......

也有人说直接brew install *gcc*但是我觉得这样太粗暴了,我没这么干,想省事的话可以试试.

  • Ubuntu

默认安装目录/usr/local/openresty/nginx/

sudo apt install -y libpcre3-dev libssl-dev perl make build-essential curl
&& sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates
&& wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
&& sudo apt-get -y install --no-install-recommends software-properties-common
&& sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
&& sudo apt-get update
&& sudo apt-get -y install openresty

NGINX配置


        location ~ /lua_request {
            #default_type "text/json";
            default_type "text/html";
            #content_by_lua_file "/Users/liuhao/my-shell/lua/index.lua";
            content_by_lua_file "/Users/liuhao/my-shell/lua/middle.lua";
        }

		# 转发给//192.168.56.100
        location @server_100 {
            proxy_pass http://192.168.56.100:80;
		    # 将用户的IP信息同时带过去,要不然,后端服务器获得的IP地址将是代理服务器的IP;
		    proxy_set_header X-Forwarded_For $remote_addr;
        }

		# 转发给//192.168.56.101
        location @server_101 {
            proxy_pass http://192.168.56.101:80;
		    # 将用户的IP信息同时带过去,要不然,后端服务器获得的IP地址将是代理服务器的IP;
		    proxy_set_header X-Forwarded_For $remote_addr;
        }

		# 转发给//192.168.56.102
        location @server_102 {
            proxy_pass http://192.168.56.102:80;
		    # 将用户的IP信息同时带过去,要不然,后端服务器获得的IP地址将是代理服务器的IP;
		    proxy_set_header X-Forwarded_For $remote_addr;
        }

lua代码

这就是一个转发案例,一个简单的场景.

如果要做的更加的复杂的功能,比如要做一个分布式的换保存可以用到一致性hash

也可也向下面这样把name缓存用户的唯一值,然后按照要求进行IP转发.

其实这个案例最重要的是学到,可以在lua中写中间件,做数据过滤.

local restyMemcached = require "resty.memcached"

--获取GET请求参数,_name就是参数名,如果是别的比如ID就是_id
local name = ngx.var.arg_name

 --lua 初始化 memcached
 local memcached ,err = restyMemcached:new()
 if not memcached then
    return ngx.say("memcached init failed: ",err)
 end

 -- 连接memcached
 local ok,err = memcached:connect("127.0.0.1",11211)
 if not ok then
    return ngx.say("connect failed: ",err)
 end

 -- 从 memcached 获取 参数
 local value,flags,err =memcached:get("name-"..name)
 if err then
    return ngx.say("get failed: ",err)
 end
--一定要注意,当下面ngx.exec()的时候,前面一定不能用任何的输出,刚才忘了这一点,卡了半天
--  ngx.say("request key:", name," cache:", value)

 --这个并不是真正的switch,lua没有switch,这是通过lua的table来实现的伪switch
 local switch = {
    ["100"] = function()
        --@server_100 看nginx定义的,交给NGINX进行转发
        -- ngx.say("switch:100")
        ngx.exec("@server_100")
    end,
    ["101"] = function()
        --@server_101 看nginx定义的,交给NGINX进行转发
        -- ngx.say("switch:101")
        ngx.exec("@server_101")
    end,
    ["102"] = function()
        --@server_102 看nginx定义的,交给NGINX进行转发
        -- ngx.say("switch:102")
        ngx.exec("@server_102")
    end,
}
--通过下标获取到在switch中的数据
local server = switch[value]
if server then
    --执行switch下的case
    --一定要注意,当这里ngx.exec()的时候,前面一定不能用任何的输出,刚才忘了这一点,卡了半天
    server()
    return
end
return ngx.say("server not exist")

请求测试

发送请求

curl http://localhost/lua_request?name=100
curl http://localhost/lua_request?name=101
curl http://localhost/lua_request?name=102

可以看到三台机器全部接收到了请求

image-20200308170738616

完结