踩坑:egg.js在Nginx docker中提示 Session ID unknown

問題: 在本地啓動egg.js,使用egg-socket.io,能正常連接到websocket,而放到docker中運行,則無法連接得上,提示Session ID unknown,http報400錯誤。

原因: 之所以在本地能成功連接,是因爲本地啓動方式爲egg-bin dev,會針對本地開發做很多處理,而在docker中啓動腳本是egg-scripts start,如果沒有在sticky模式下運行,則會出現無法正常連接,同時報錯。

值得注意點是Egg框架是以 Cluster 方式啓動的,而 socket.io 協議實現需要 sticky 特性支持,否則在多進程模式下無法正常工作。

由於 socket.io 的設計,在多進程中服務器必須在 sticky 模式下工作,故需要給 startCluster 傳遞 sticky 參數。

添加之後再運行就連接正常了。

修改 package.jsonnpm scripts 腳本:

{
  "scripts": {
    "dev": "egg-bin dev --sticky",
    "start": "egg-scripts start --sticky"
  }
}

Nginx 配置

location / {
  # 這兩行需要開啓
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $host;
  proxy_pass   http://127.0.0.1:7001;
}

Cluster 是什麼呢?

簡單的說,

  • 在服務器上同時啓動多個進程。
  • 每個進程裏都跑的是同一份源代碼(好比把以前一個進程的工作分給多個進程去做)。
  • 更神奇的是,這些進程可以同時監聽一個端口(具體原理推薦閱讀 @DavidCai1993 這篇 Cluster 實現原理)。

其中:

  • 負責啓動其他進程的叫做 Master 進程,他好比是個『包工頭』,不做具體的工作,只負責啓動其他進程。
  • 其他被啓動的叫 Worker 進程,顧名思義就是幹活的『工人』。它們接收請求,對外提供服務。
  • Worker 進程的數量一般根據服務器的 CPU 核數來定,這樣就可以完美利用多核資源。
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章