Вопрос довольно старый, но я надеюсь, что мой ответ по-прежнему актуален для вас.
stream {
lua_code_cache on;
init_by_lua_block {
-- cache package on startup
require('ngx.balancer')
-- share backend addresses via global table
-- (not recommended, only for demo purposes)
_G.BACKENDS = {
{'172.17.0.1', 8081},
{'172.17.0.1', 8082},
}
}
upstream lua_dispatcher {
# just an invalid address as a placeholder
server 0.0.0.1:1234;
balancer_by_lua_block {
local balancer = require('ngx.balancer')
local backend_index
if ngx.ctx.request_first_byte > 'a' then
backend_index = 1
else
backend_index = 2
end
local backend_table = _G.BACKENDS[backend_index]
local ok, err = balancer.set_current_peer(table.unpack(backend_table))
if not ok then
ngx.log(ngx.ERR, err)
ngx.exit(ngx.ERROR)
end
}
}
# proxy
server {
listen 9000;
proxy_pass lua_dispatcher;
# cosocket API not available in balancer_by_lua_block,
# so we read the first byte here and keep it in ngx.ctx table
preread_by_lua_block {
local sock = ngx.req.socket()
local data, err = sock:receive(1)
if not data then
ngx.log(ngx.ERR, err)
ngx.exit(ngx.ERROR)
end
ngx.ctx.request_first_byte = data:sub(1, 1)
}
}
# mock upstream 1
server {
listen 172.17.0.1:8081;
content_by_lua_block {
ngx.say('first')
}
}
# mock upstream 2
server {
listen 172.17.0.1:8082;
content_by_lua_block {
ngx.say('second')
}
}
}
$ nc -C localhost 9000 <<< '123'
second
$ nc -C localhost 9000 <<< '223'
second
$ nc -C localhost 9000 <<< 'a23'
second
$ nc -C localhost 9000 <<< 'b23'
first
$ nc -C localhost 9000 <<< 'c23'
first