Pull to refresh

Поддержка реверс-проксирования Web Sockets в Nginx

Nginx *
Sandbox
Если вы используете Socket.IO или Faye с WebSockets, и хотите при этом использовать реверс-прокси с Nginx, то вы встретитесь с проблемой поддержки WebSocket в Nginx. Ее просто нет — WebSocket использует HTTP 1.1, в то же время как Nginx умеет правильно проксировать только HTTP 1.0.

Что делать?


Вы можете попытаться пойти в обход — использовать HAProxy для проксирования tcp соединений, или же скатиться к использованию Long-polling.
Но есть способ реализовать реверсированное проксирование и с NGINX, используя неофициальный патч, реализующий модуль tcp_proxy в nginx, который даст возможность пробрасывать произвольные tcp-соединения (по сути тоже самое, что дает HAProxy).

Компиляция nginx с модулем tcp_proxy


… в общем виде, будет выглядеть следующим образом:

export NGINX_VERSION=1.0.4
curl -O nginx.org/download/nginx-$NGINX_VERSION.tar.gz
git clone github.com/yaoweibin/nginx_tcp_proxy_module.git
tar -xvzf nginx-$NGINX_VERSION.tar.gz
cd nginx-$NGINX_VERSION
patch -p1 < ../nginx_tcp_proxy_module/tcp.patch
./configure --add-module=../nginx_tcp_proxy_module/
sudo make && make install


Код приведен с учетом того, что у вас установлены средства построения и удовлетворены все зависимости nginx. К примеру,

sudo apt-get install curl build-essential git-core
sudo apt-get build-dep nginx


Замечу, что для владельцев ubuntu-server имеет смысл вместо make install, делать checkinstall для установки nginx как пакета, а также добавить нужные опции по дополнительным модулям и путям к логам и конфигурации, к примеру как описано в Q&A.

Конфигурирование прокси


Создадим простой vhost для случая когда мы хотим пробросить порт 80 на порты 8001, 8002, 8003, 8004 наших бэкендов (в роли которых, к примеру, выступают сервера node.js с faye или socket.io модулями) с балансировкой нагрузки.

А на 9000 порт локалхоста выведем отладочную информацию по статусу работы прокси.

tcp {
upstream websockets {
## node processes
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
server 127.0.0.1:8004;
check interval=3000 rise=2 fall=5 timeout=1000;
}
server {
listen 0.0.0.0:80;
server_name вашеИмяДомена;
tcp_nodelay on;
proxy_pass websockets;
}
}

http {
## status check page for websockets
server {
listen 9000;

location /websocket_status {
check_status;
}
}
}


Запустив бэкенды, мы сможем наблюдать радостную картину:

image

При реализации нескольких бэкендов нужно понимать, что нет никаких гарантий, что клиент всегда будет подключаться к одному и тому же бэкенду (к примеру, серверу node.js), потому необходимо продумывать правильные пути управлением сессиями в кластере (например, использовать redis).

Удачи!

PS. За основу взята статья Johnathan Leppert
Tags:
Hubs:
Total votes 55: ↑53 and ↓2 +51
Views 10K
Comments Comments 15