【问题标题】:nginx, node.js and socket.io - is there a working marriage?nginx、node.js 和 socket.io - 有工作婚姻吗?
【发布时间】:2012-06-25 13:03:03
【问题描述】:

nginx 是一个杀手级静态文件服务器。

它可以像this example 一样为node.js 提供服务,但方式有限。

nginxapparently unable 以代理websockets

我发现唯一可行的方法是按照 this article 使用 HAProxy 前端 - 但它是从 2011 年 10 月 6 日开始的。

这个必须是一个常见的问题,但我没有找到一个非常常见的解决方案。


解决方案

(请参阅https://github.com/bangkok-maco/barebone-node了解完整的解决方案和详细信息)

ip 测试架构:

  • 127.0.0.12 - www.chat.nit - 公共,在 /etc/hosts 和 haproxy 中
  • 127.0.1.12 - 内部 nginx 网络服务器
  • 127.0.2.12 - 内部聊天服务 node.js socket.io

/etc/haproxy/haproxy.cfg:

global
 maxconn 4096
 nbproc 2
 daemon
 # user nobody
 log             127.0.0.1       local1 notice

defaults
 mode http

# listen on 127.0.0.12:80
frontend app
 bind 127.0.0.12:80
 mode tcp
 timeout client 86400000
 default_backend www_backend
 acl is_chat hdr_dom(Host) chat
 acl is_websocket path_beg /socket.io

 use_backend chat_socket_backend if is_websocket is_chat
 tcp-request inspect-delay 500ms
 tcp-request content accept if HTTP

# ngnix on 127.0.1.12:80
backend www_backend
 balance roundrobin
 option forwardfor
 mode http
 option httplog
 option httpclose
 timeout server 30000
 timeout connect 4000
 server w1 127.0.1.12:80 weight 1 maxconn 1024 check

# node (socket.io) on 127.0.2.12:80
backend chat_socket_backend
 balance roundrobin
 mode http
 option httplog
 option forwardfor
 timeout queue 5000
 timeout server 86400000
 timeout connect 86400000
 timeout check 1s
 no option httpclose
 option http-server-close
 option forceclose
 server s14 127.0.2.12:8000 weight 1 maxconn 1024 check

/etc/nginx/sites-enabled/www.chat.nit

server {
    listen   127.0.1.12:80;

    root /data/node/chat;
    index client.html;

    server_name www.chat.nit;

    # favicon.ico is in /images
    location = /favicon.ico$ { rewrite /(.*) /images/$1 last; }

    # standard includes
    location ^~ /(css|images|scripts)/ {
            try_files $uri =404;
    }

    # html page (only in root dir)
    location ~ ^/([-_a-z]+).html$ {
            try_files $uri =404;
    }

    error_page 404 /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
            root /usr/share/nginx/www;
    }
}

聊天(node.js):server.js

var app = require('http').createServer()
   , io = require('socket.io').listen(app);    
app.listen(8000,'127.0.2.12');

io.sockets.on('connection', function(socket) {
  ...
};

聊天:client.html

<head>
  <script src="/scripts/socket.io/socket.io.js"></script>
  <script>
    var socket = io.connect('http://www.chat.nit:80'); 
    ...
  </script>
</head>

注释:

  1. 将socket.io客户端js链接到scripts/目录

    /.../scripts$ ln -s ../node_modules/socket.io/node_modules/socket.io-client/dist/socket.io

  2. /etc/default/haproxy(与文本相反,必须设置为工作完全

    启用=1

  3. 此版本 haproxy 未记录。找到kvz's写了如何通过127.0.0.1使用rsyslogd,但无法让它飞起来。

  4. 这个解决方案是工作 - 不是系统管理员质量可以肯定。 (增强功能非常受欢迎。)

【问题讨论】:

  • 实际上 HAProxy 正在工作。我正在使用它来代理 WebSockets,我对此非常满意。根据我的经验,代理 WebSockets(和其他请求)比“杀手级静态文件服务器”更重要,但实际上它取决于您的应用程序。此外,Node.js 不是一个糟糕的静态文件服务器(例如 Express 框架)——该技术与 nginx(异步单线程)非常相似。
  • 您可以发布您的 HAProxy 配置作为答案吗?你知道是否可以在非 ws 的 nginx 和 ws/wss 的 node.js 之间拆分 HAProxy 的输出?
  • 是的,拆分应该不是问题。毕竟ws/wss可以被upgrade header 识别。
  • 您可能有兴趣查看tcp_proxy 的 Nginx,可以proxy websockets

标签: node.js nginx websocket socket.io haproxy


【解决方案1】:

从 v1.3.13 起,您似乎可以通过 nginx 代理 WebSockets

详情请见http://nginx.org/en/docs/http/websocket.html

【讨论】:

    【解决方案2】:

    这是我的(旧的和用于测试目的的)HAProxy 配置,用于代理 WebSocket 和正常的 HTTP 请求。

    global
        maxconn 4096
        nbproc 2
        daemon
        user nobody
    
    defaults
        mode http
    
    frontend app
        bind 0.0.0.0:8000
        mode tcp
        timeout client 86400000
        default_backend www_backend
        acl is_websocket path_beg /sockets
    
        use_backend socket_backend if is_websocket
        tcp-request inspect-delay 500ms
        tcp-request content accept if HTTP
    
    backend www_backend
        balance roundrobin
        option forwardfor
        mode http
        option httplog
        option httpclose
        timeout server 30000
        timeout connect 4000
        server w1 localhost:8080 weight 1 maxconn 1024 check
    
    backend socket_backend
        balance roundrobin
        mode http
        option httplog
        option forwardfor
        timeout queue 5000
        timeout server 86400000
        timeout connect 86400000
        timeout check 1s
        no option httpclose
        option http-server-close
        option forceclose
        server s1 localhost:8081 weight 1 maxconn 1024 check
    

    请注意,我通过查看路径(acl is_websocket path_beg /sockets 行)来识别请求是否为 WS。这可以替换为例如:

    acl is_websocket hdr(Upgrade) -i WebSocket
    

    或者这个:

    acl is_websocket hdr_beg(Host) -i ws
    

    或两者兼而有之。使用此配置代理到 nginx 应该是开箱即用的。

    【讨论】:

    • 由于旅行和天生的无能 ;),测试时间比我想象的要长。底线 - 效果很好!非常感谢!!已将所有文章作为问题的附录发布。
    • @ccyoung 太好了!请记住根据您的需要进行调整!
    • 您能看看发布的内容吗?感谢您可能拥有的任何见解。
    猜你喜欢
    • 2012-07-16
    • 1970-01-01
    • 2012-01-11
    • 2015-08-20
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2017-07-27
    相关资源
    最近更新 更多