[TOC]
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
可以看到三台机器全部接收到了请求
完结