在HAProxy中使用LUA处理http响应

我正在尝试在HAProxy中定义LUA挂接,以便我可以在收到响应后执行一个操作(杀死处理请求的容器)。我的问题在于处理HAProxy缓冲区。我尝试了不同的实现,这是最接近工作的一种(尽管有一半的时间无法将所有数据发送回客户端):

function hook(txn)
  local in_len = txn.res:get_in_len()
  while in_len > 0 do
    txn.res:forward(in_len)
    local out_len = txn.res:get_out_len()
    while out_len ~= 0 do
      core.yield()
      out_len = txn.res:get_out_len()
    end
    in_len = txn.res:get_in_len()
  end
  os.execute("docker rm -f server_" .. txn.sf:srv_id())
end

core.register_action("hook", { "http-res" }, hook)

我最大的问题是没有Content-length头,所以我不知道何时处理了所有信息,也不知道何时结束。此外,我一直无法使getset方法起作用,因为每次调用get时我会获得完全相同的信息。

以下是HAProxy的配置:

backend my-backend
  balance roundrobin
  http-response lua.hook
  server server_1 192.168.1.3:80 check

在杀死后端服务器之前处理所有信息的正确方法是什么?

点赞
用户7631780
用户7631780

当您在“txn.res: forward(in_len)”中使用 forward 函数 时,您将数据从HTTP响应缓冲区的输入部分移动到输出部分。

接下来您使用 yield,它会将处理权交回给HAProxy,这时问题就出现了。HAProxy无法分析标头(它们直接移动到输出缓冲区),并且会将响应视为无效。

因此,我认为您始终只收到HAProxy之前的第一个缓冲区。

如果您更改脚本并在TCP上下文中使用它,则HAProxy无需检查HTTP响应是否有效,它将正常工作。 在TCP上下文中,您的脚本甚至可以简化为以下内容:

function hook(txn)
    local in_len = txn.res:get_in_len()
    while in_len > 0 do
            core.yield()
            in_len = txn.res:get_in_len()
    end
    os.execute("docker rm -f server_" .. txn.sf:srv_id())
end
core.register_action("hook", { "tcp-res" }, hook)

此外,您需要知道使用os.execute()不是一个好主意,因为它会阻塞HAProxy,直到执行完成。更多关于它的信息,请参见“Non Blocking design”中的章节。 因此,最好选择其他选择,例如使用API向容器发送操作。

2018-11-14 18:18:25