Socket.io,Express 4和Nginx与SSL *和CLUSTER *抛出400(错误请求)?

时间:2018-01-30 00:02:11

标签: node.js express ssl nginx socket.io

我使用nginx进行面向网络的流量并代理我的node.js连接,以及处理我的SSL。

连接已成功建立 - io.on(' connection')确实触发了控制台日志服务器端,但随后我在客户端上获得了400(错误请求)(在Firefox和Chrome中) )然后连接一遍又一遍地重置(并继续抛出相同的错误)。

错误如下(来自Chrome):

polling-xhr.js:264 GET https://192.168.56.101/socket.io/?EIO=3&transport=polling&t=M54C3iW&sid=byqOIkctI9uWOAU2AAAA 400 (Bad Request)
    i.create @ polling-xhr.js:264
    i @ polling-xhr.js:165
    o.request @ polling-xhr.js:92
    o.doPoll @ polling-xhr.js:122
    n.poll @ polling.js:118
    n.onData @ polling.js:157
    (anonymous) @ polling-xhr.js:125
    n.emit @ index.js:133
    i.onData @ polling-xhr.js:299
    i.onLoad @ polling-xhr.js:366
    hasXDR.r.onreadystatechange @ polling-xhr.js:252
    XMLHttpRequest.send (async)
    i.create @ polling-xhr.js:264
    i @ polling-xhr.js:165
    o.request @ polling-xhr.js:92
    o.doPoll @ polling-xhr.js:122
    n.poll @ polling.js:118
    n.doOpen @ polling.js:63
    n.open @ transport.js:80
    n.open @ socket.js:245
    n @ socket.js:119
    n @ socket.js:28
    n.open.n.connect @ manager.js:226
    n @ manager.js:69
    n @ manager.js:37
    n @ index.js:60
    (anonymous) @ control.js:6
192.168.56.101/:1 WebSocket connection to 'wss://192.168.56.101/socket.io/?EIO=3&transport=websocket&sid=byqOIkctI9uWOAU2AAAA' failed: WebSocket is closed before the connection is established.

Nginx日志(在信息级别)显示以下内容:

2018/01/29 19:37:10 [info] 28262#28262: *18403 client closed connection while waiting for request, client: 192.168.56.1, server: 192.168.56.101:443

我的nginx配置如下 (无论有没有"位置/socket.io/"阻止,我都试过这个,并得到完全相同的结果。):

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}
upstream altairServer {
    server 192.168.56.101:8000;
}
server {
    listen 192.168.56.101:443;
    server_name     altair.e6diaspora.com;

    ssl on;
    ssl_certificate /home/e6serv/crypto/domain.pem;
    ssl_certificate_key /home/e6serv/crypto/server.key;

    access_log /home/e6serv/logs/nginx/host.access.log;
    error_log /home/e6serv/logs/nginx/host.error.log;

    root        /home/e6serv/e6Code/e6GS1/public;

    location / {
            try_files maintain.html $uri $uri/index.html @node;
    }

    location /socket.io/ {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;

            proxy_pass http://altairServer;
            proxy_redirect off;

            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
    }

    location @node {
            proxy_pass http://altairServer;
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-NginX-Proxy true;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_max_temp_file_size 0;
            proxy_redirect off;
            proxy_read_timeout 240s;
    }
}

相关的服务器端代码如下:

const app = express();
app.set('port', 8000);
app.engine('html', require('ejs').renderFile);
app.use(methodOverride());
app.use(session({
secret: SITE_SECRET,
    store: redisSesStore,
    cookie: {maxAge: 604800000},
    resave: false,
    saveUninitialized: false
}));
app.use(parseCookie());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use('/',router);

const httpServer = http.createServer(app)
const io = socketIo.listen(httpServer);

io.use(passportSocketIo.authorize({
    key: 'connect.sid',
    secret: SITE_SECRET,
    store: redisSesStore,
    passport: passport,
    cookieParser: parseCookie
}));

httpServer.listen(app.get('port'), '192.168.56.101', function(){
    log.warn('Worker Started HTTP Server')
});

io.on('connection', function(socket) {
    log.debug(socket.request.user)
    var event = { type:'userConnect',data:'Hello Client'};
    process.send(event);
}

我的客户端代码如下:

control.socket = io.connect('https://'+hostname);
console.log("Should be connected")
//NOTE: This final line does not work--the console.log never fires:
control.socket.on('userConnect',function (data) {console.log(data)}) 

1 个答案:

答案 0 :(得分:1)

我发现了问题的根源......我在这里谈论的额外元素是node.js的Cluster。

https://github.com/socketio/socket.io/issues/1942

https://socket.io/docs/using-multiple-nodes/

Socket.io默认为轮询,这需要在各种工作者之间进行粘性负载平衡。解决方案可以在socket.io多节点文档中找到。

我在我的nginx配置中添加了以下内容:

03720568  push        ebp  
03720569  mov         ebp,esp  
0372056B  push        edi  
0372056C  push        esi  
0372056D  push        ebx  
0372056E  test        dword ptr [esp-1000h],eax  
03720575  test        dword ptr [esp-2000h],eax  
0372057C  sub         esp,2C7Ch  
03720582  mov         esi,ecx  
...and so on...

(另请注意,必须设置特定工作人员以侦听特定端口。)