Может ли nginx использоваться в качестве обратного прокси для серверного websocket-сервера?

мы работаем над приложением Ruby on Rails, которое должно использовать преимущества HTML5 websockets. На данный момент у нас есть два отдельных "сервера", так сказать: наше основное приложение работает на nginx+passenger и отдельный сервер, использующий Pratik Naik's судороги framework (который работает на тонкий) для обработки соединений websocket.

В идеале, когда придет время для развертывания, у нас будет приложение rails, работающее на nginx + passenger, и сервер websocket быть проксированным за nginx, поэтому нам не нужно, чтобы сервер websocket работал на другом порту.

проблема в том,что в этой настройке кажется, что nginx закрывает соединения слишком рано. Соединение успешно установлено к тонкому серверу, после этого немедленно закрыто с кодом 200 ответов. Мы предполагаем, что nginx не понимает, что клиент пытается установить долгосрочное соединение для трафика websocket.

правда, я не все, что подкованный с конфигурацией nginx, так можно ли даже настроить nginx в качестве обратного прокси для сервера websocket? Или мне нужно ждать, пока nginx предложит поддержку для нового рукопожатия websocket? Предполагая, что наличие сервера приложений и сервера websocket, прослушивающего порт 80, является требованием, может ли это означать, что я должен иметь тонкий запуск на отдельном сервере без nginx впереди?

заранее спасибо за любые советы или предложения. :)

-Джон

7 ответов


вы не можете использовать Nginx для этого в настоящее время[это не так], но я бы предложил посмотреть на HAProxy. Я использовал его именно для этой цели.

хитрость состоит в том, чтобы установить длинные таймауты, чтобы соединения сокетов не были закрыты. Что-то вроде:

timeout client  86400000 # In the frontend
timeout server  86400000 # In the backend

Если вы хотите служить, скажем, приложение rails и cramp на том же порту, вы можете использовать правила ACL для обнаружения соединения websocket и использовать другой бэкэнд. Таким образом, ваша конфигурация интерфейса haproxy будет выглядеть примерно как

frontend all 0.0.0.0:80
  timeout client    86400000
  default_backend   rails_backend
  acl websocket hdr(Upgrade)    -i WebSocket
  use_backend   cramp_backend   if websocket

для полноты бэкэнд будет выглядеть как

backend cramp_backend
  timeout server  86400000
  server cramp1 localhost:8090 maxconn 200 check

Как насчет использования my модуль nginx_tcp_proxy_module?

этот модуль предназначен для общего TCP прокси с Nginx. Я думаю, что это также подходит для вебсокетов. И я просто добавляю tcp_ssl_module в ветку разработки.


nginx и (>= 1.3.13) теперь поддерживает обратное проксирование websockets.

# the upstream server doesn't need a prefix! 
# no need for wss:// or http:// because nginx will upgrade to http1.1 in the config below
upstream app_server {
    server localhost:3000;
}

server {
    # ...

    location / {
        proxy_pass http://app_server;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_redirect off;
    }
}

из коробки (т. е. официальные источники) Nginx может установить только HTTP 1.0 соединения с восходящим (=backend), что означает, что нет keepalive возможно: Nginx выберет восходящий сервер, откроет соединение с ним, прокси, кэш (если вы хотите) и закроет соединение. Вот и все.

Это основная причина, по которой фреймворки, требующие постоянных подключений к бэкэнду, не будут работать через Nginx (нет HTTP/1.1 = нет keepalive и нет websockets, я думаю). Несмотря на это недостаток есть очевидное преимущество: Nginx может выбрать из нескольких восходящих потоков (баланс нагрузки) и отработки отказа на живой в случае, если некоторые из них не удалось.

редактировать: Nginx поддерживает HTTP 1.1 для бэкэндов и keepalive с версии 1.1.4. поддерживаются восходящие потоки" fastcgi "и" proxy". вот это-документы


для тех, кто интересуется той же проблемой, nginx теперь официально поддерживает HTTP 1.1 вверх по течению. См. документацию nginx для "keepalive"и" proxy_http_version 1.1".


Как насчет Nginx с новым модулем http Push:http://pushmodule.slact.net/. Он заботится о жонглировании соединением (так сказать), о котором, возможно, придется беспокоиться с обратным прокси. Это, безусловно, жизнеспособная альтернатива Websockets, которые еще не полностью в смеси. Я знаю, что разработчик модуля HTTP Push все еще работает над полностью стабильной версией, но он находится в активной разработке. Существуют версии, которые используются в производственных кодовых базах. Цитировать автор, " полезный инструмент со скучным названием."


Я использую nginx для обратного прокси-сервера в стиле кометы с длинными соединениями опроса, и он отлично работает. Убедитесь, что proxy_send_timeout и proxy_read_timeout настроены на соответствующие значения. Также убедитесь, что ваш сервер, который nginx проксирует, поддерживает http 1.0, потому что я не думаю, что прокси-модуль nginx еще делает http 1.1.

просто чтобы прояснить некоторую путаницу в нескольких ответах: Keepalive позволяет клиенту повторно использовать соединение для отправки другого HTTP-запроса. Это не имеет ничего общего с длительным опросом или удержанием соединений открытыми, пока не произойдет событие, о котором спрашивал исходный вопрос. Таким образом, это не имеет значения, чем прокси-модуль nginx поддерживает только HTTP 1.0, который не имеет keepalive.