Как отправить tcp-запрос бэкендам с первым байтом контента в openresty lua - PullRequest
0 голосов
/ 06 ноября 2018

Я запустил openresty с одним tcp сервером и двумя бэкэндами. Сервер tcp отправляет запрос бэкэндам в соответствии с содержимым из потока tcp. Ниже приведен пример конфигурации openresty:

stream {
  # define a TCP server listening on the port 1234:
  upstream backend1 {
    server  172.17.0.1:8081;
  }
  upstream backend2 {
    server  172.17.0.1:8082;
  }

  server {
    listen 1234;

    content_by_lua_block {
      local sock = ngx.req.socket( true )
      -- reveive first byte
      local data, err = sock:receive( 1 )

      --dispatch two backend1 if data is greater than 'a', otherwise dispatch to backend2
      local a = string.byte(data, 1, 1 )
      if a > 'a' then
        --how to send to backend1
      else
        --how to send to backend2
      end
    }
  }
}

Я не знаю, как создать мост между запросом и серверной частью в соответствии с первым байтом в запросе с помощью lua-скрипта.

Если кто-нибудь может помочь это?

1 Ответ

0 голосов
/ 20 марта 2019

Вопрос довольно старый, но я надеюсь, что мой ответ по-прежнему актуален для вас.

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
...