Hello!
2012/5/28 hkmstu <hk...@126.com>:
> 我想要设置一个nginx反向代理,代理多台不同的服务器。
>
> nginx根据post data中的特定字段来转发到不同的服务器。例如post
> data中如果包含foo,则转发到192.168.0.2:8080;包含bar,则转发到192.168.0.3:8080。
>
> 所以问题的关键是读取post data中的数据,但是我附件中的配置,总是读不出post data,不知道有什么方法读出post
> data然后匹配正确转发。求助~
>
这个需求可以使用 ngx_lua 模块来做,例如:
location /what {
set $target '';
access_by_lua '
ngx.req.read_body()
local data = ngx.req.get_body_data()
if not data then
local datafile = ngx.req.get_body_file()
if not datafile then
ngx.log(ngx.ERR, "No request body found")
ngx.exit(500)
end
-- request body buffered into a temp file
local fh, err = io.open(datafile, "r")
if not fh then
ngx.log(ngx.ERR, "failed to open ", datafile, "
for reading: ", err)
ngx.exit(500)
end
data = fh:read("*a") -- we should have scanned the
file streamingly
fh:close()
if not data then
ngx.log(ngx.ERR, "failed to read ", datafile)
ngx.exit(500)
end
-- request body in the variable "data" now
if string.match(data, "foo") then
ngx.var.target = "192.168.0.2:8080"
elseif string.match(data, "bar") then
ngx.var.target = "192.168.0.3:8080"
else
ngx.log(ngx.ERR, "I do not know where to go")
end
';
proxy_pass http://$target;
}
上例已在我本地简单测试过,包括请求体过大而缓冲到磁盘临时文件的情形。为简单起见,在缓冲到文件的时候,上例把文件数据全部读到内存中再进行匹配,真实的情况下,应改用按块读取文件数据,并进行某种形式的流式匹配
:) 为了便于调试和诊断问题,上面的示例代码添加上了比较完整的错误处理。
这里的核心思想是使用 Lua 代码在 access 请求处理阶段主动读取请求体,并对请求体数据进行相关的匹配,然后分情况设置 nginx
变量 $target 的值,最后在 content 请求处理阶段把 $target 直接喂给 ngx_proxy 模块的
proxy_pass 配置指令,完成动态指向的代理。下面这个例子也使用了类似的思想,只不过是根据 Redis TCP 查询的结果来动态决定
proxy_pass 的指向:
http://openresty.org/#DynamicRoutingBasedOnRedis
相关的更多细节可以参考 ngx_lua 模块的官方文档:
http://wiki.nginx.org/HttpLuaModule
Regards,
-agentzh