Допустим, у меня есть служба, работающая на уровне необработанного TCP, и я хочу добавить к ней балансировку нагрузки. Я пытался использовать ngx_stream_core_module
. Хотя TCP-потоки действительно передаются на внутренние серверы через прокси, я обнаружил некоторые проблемы, которые не могу решить.
Моя служба написана на node.js, и это распространенный метод настройки диспетчера процессов, например pm2, который перезапускает узел в случае, если он потребляет слишком много памяти. Но это, очевидно, отключит всех подключенных клиентов. Я ожидал, что nginx будет подключать пользователей к следующему серверу в восходящем потоке (ну, может быть, это тоже> 2016, но), но мое соединение просто закрывается.
Для работы моей службы требуются IP-адрес конечного пользователя и удаленный порт, но в сокете приложения remoteAddress и remotePort указывают на локальный экземпляр nginx. Т.е. когда я печатаю его в буфер, я вижу 127.0.0.1, когда соединение проксируется, и мой реальный ip, когда я подключаюсь к узлу напрямую. Я вижу, что nginx поддерживает некоторые переменные конфигурации (начиная с версии 1.11.2), и $ remote_addr среди них. Но я не вижу никакой информации, как передать эту переменную в апстрим. proxy_set_header
директива недоступна внутри потока и выглядит нормально, поскольку в TCP нет никаких «заголовков». Это вообще возможно?
Я не DevOps, а программист, поэтому слышал о haproxy, но понятия не имею, может ли он решить эти две проблемы. Может это?
Для тестирования я использовал тупой сервер echo node.js, где вся рабочая часть сужена до
server.on('connection', socket => {
socket.write(`Hello from ${instance}, ${socket.remoteAddress}:${socket.remotePort}\n`);
});
И соответствующая часть моей конфигурации nginx:
stream {
upstream echo {
server localhost:9000;
server localhost:9001;
}
server {
listen 8080;
proxy_connect_timeout 1s;
proxy_timeout 2h;
proxy_pass echo;
}
}
Наконец, я использовал netcat для проверки.
// direct connect
~|⇒ nc 95.85.15.120 9000
Hello, ::ffff:86.110.174.98:65408
// proxied connect
~|⇒ nc 95.85.15.120 8080
Hello, ::ffff:127.0.0.1:44056
Здесь документы модуля.
Это не то, что могло бы работать с TCP, потому что это наверняка сломает почти любой протокол, работающий поверх. Например, что, если соединение будет разорвано посреди какого-либо сообщения или команды?
Ты можешь использовать протокол прокси для передачи исходных IP-адресов, но они должны поддерживаться вашим сервером.
Или вы можете настроить привязка к IP-адресам клиентов:
proxy_bind $remote_addr transparent;