Можно ли использовать nginx в качестве обратного прокси-сервера для внутреннего сервера веб-сокетов? - PullRequest
35 голосов
/ 10 марта 2010

Мы работаем над приложением Ruby on Rails, которое должно использовать преимущества веб-сокетов html5. На данный момент у нас есть два отдельных «сервера», так сказать: наше основное приложение, работающее на nginx + passenger, и отдельный сервер, использующий платформу Pratik Naik Cramp (которая работает на Thin ) для обработки соединений с веб-сокетом.

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

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

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

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

-John

Ответы [ 7 ]

26 голосов
/ 08 апреля 2010

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

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

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

Если вы хотите обслуживать, например, приложение rails и cramp на одном и том же порту, вы можете использовать правила ACL для обнаружения соединения через веб-сокет и использовать другой бэкэнд. Таким образом, ваш внешний интерфейс 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
12 голосов
/ 14 сентября 2010

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

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

11 голосов
/ 20 февраля 2013

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

# 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;
    }
}
7 голосов
/ 10 марта 2010

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

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

Редактировать : Nginx поддерживает HTTP 1.1 для бэкэндов и keepalive начиная с версии 1.1.4. Поддерживаются апстрики fastcgi и proxy. Вот это документы

5 голосов
/ 15 мая 2012

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

3 голосов
/ 10 марта 2010

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

2 голосов
/ 26 мая 2010

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

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

...