大致思路是通过监听Docker的events来动态的加载后端节点,监听到docker的变化时,将相应的容器ip 加到Sharedict中储存, nginx.conf如下:
env HOSTNAME;
env PROXY_PORT;
stream {
lua_package_path "/tcp-proxy/lib/?.lua;;";
lua_package_cpath "/tcp-proxy/?.so;;";
resolver 8.8.8.8;
lua_shared_dict serverList 1m;
lua_shared_dict containerInfo 5m;
# lua_code_cache on;
lua_socket_read_timeout 2628000m; # five year
init_by_lua_file /tcp-proxy/lib/resty/init.lua;
upstream backend {
server 0.0.0.1:9000;
balancer_by_lua_file /tcp-proxy/lib/resty/balancer.lua;
}
server {
# Traffic entrance
listen 9000;
proxy_pass backend;
}
server {
# listing docker event
listen 6000;
content_by_lua_block {
local docker = require "resty.dockerAPI"
local client = docker:newClient("unix:///tmp/docker.sock")
client:init()
client:events()
}
}
server {
# stream dict interface
listen 1000;
preread_by_lua_file /tcp-proxy/lib/resty/shareDictStreamAPI.lua;
content_by_lua_block {
ngx.say(123)
}
}
}
init_by_lua_file /tcp-proxy/lib/resty/init.lua; 这里面是在每次重载配置文件文件时刷新shared DICT中的内容
/tcp-proxy/lib/resty/balancer.lua; 的代码如下:
local balancer = require "ngx.balancer"
local rr_up = package.loaded.my_rr_up
local server = rr_up:find()
ngx.log(ngx.ERR, string.format( "current server : %s", server))
assert(balancer.set_current_peer(server))
这里的local rr_up = package.loaded.my_rr_up 是从监听1000端口的那个server下的preread_by_lua_file /tcp-proxy/lib/resty/shareDictStreamAPI.lua; 文件里来的
问题也出在这里,在本机上运行无误,但是一旦迁移到其他机器则会报错:
[error] 14#14: *35 failed to run balancer_by_lua*: /tcp-proxy/lib/resty/balancer.lua:4: attempt to index local 'rr_up' (a nil value)
stack traceback:
/tcp-proxy/lib/resty/balancer.lua:4: in function </tcp-proxy/lib/resty/balancer.lua:1> while connecting to upstream, client: 172.22.0.3, server: 0.0.0.0:9000, bytes from/to client:0/0, bytes from/to upstream:0/0
preread_by_lua_file /tcp-proxy/lib/resty/shareDictStreamAPI.lua; 的文件内容如下:
local resty_roundrobin = require "resty.roundrobin"
server_list = dict:get_keys()
local serverList = {}
if not serverList then
ngx.log(ngx.ERR, string.format( "current backend : %s", server))
ngx.exit(500)
end
for k,v in pairs(server_list) do
serverList[v] = 1
end
ngx.log(ngx.ERR, cjson.encode(serverList))
local rr_up = resty_roundrobin:new(serverList)
package.loaded.my_rr_up = rr_up
在每次后端容器有变化时,则会通知这个接口进行重载
另外所有的运行环境都是在容器内的,按理说应该是可以排除环境问题的,但是就是不工作