首页 > 解决方案 > 使用 pm2 在系统启动时重新启动 socketio(非集群模式)

问题描述

我正在开发一个 express.js 应用程序,但我没有使用 pm2 -i 选项在集群模式下运行它,因为我只有一个 CPU。我以前在一些应用程序中使用过 pm2 在启动时启动 express.js 服务器并在其进程被终止时重新启动它。

我想知道两件事:

1 . 我想将 express.js 服务器与 socket.io 服务器一起运行,两者都在同一个端口(4000)上侦听,如文档中所述。socket.io 服务器也会在系统启动时启动并且它的进程被杀死吗?

$ pm2 启动 app.js

//app.js
const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', () => { /* … */ });
server.listen(4000);

2 . 我是否会对后端的应用程序状态(例如会话)有任何问题,因为这里说“确保您的应用程序是无状态的,这意味着进程中没有存储本地数据,例如会话/websocket 连接、会话内存和相关数据”这里长轮询(socket.io 用作后备)需要一些状态。我想只有在集群模式下使用 pm2 时才会出现这个问题,但我想确保任何经历过它的人。

标签: socket.iostatepm2

解决方案


  1. 因为您将 socket.io 实例附加到您的服务器对象,所以它们都可以在同一个端口上访问,并且都将在服务器启动时启动。我的套接字连接以相同的方式设置,我也在使用 PM2。要在机器启动时启动服务器,您需要告诉 PM2 这样做。检查此链接:https ://pm2.keymetrics.io/docs/usage/startup/
const server = require('http').createServer(app)

global.io = require('socket.io')(server, { transports: [ 'websocket' ]})
  1. 如果您将会话存储在本地内存中,您将遇到会话问题。我使用 connect-mongo 和 passport-socketio 进行会话,因为我在我的架构中使用 MongoDB 和护照。这会将所有会话保存在我的数据库中,并创建一个“会话”集合来存储它们,并防止它们在我出于任何原因部署或重新启动服务器时被破坏。如果您仅将会话数据存储在内存中,它将在服务器重新启动时被擦除。
const mongoose = require('mongoose')
const passportSocketIo = require('passport.socketio')
const session = require('express-session')
const cookieParser = require('cookie-parser')
const MongoStore = require('connect-mongo')(session)

const sessionStore = new MongoStore({ mongooseConnection: mongoose.connection })

const expressSession = session({
    resave: true, saveUninitialized: true, secret: process.env.passportSecret, cookie: { maxAge: 36000000 }, store: sessionStore, key: 'connect.sid'
})

app.use(expressSession)

io.use(passportSocketIo.authorize({
  key: 'connect.sid',
  secret: process.env.passportSecret,
  store: sessionStore,
  cookieParser: cookieParser
}))
   .on('connection', async (socket) => {
})

将此设置与 PM2 一起使用,我还没有看到 socket.io 在常规模式下有任何问题。对于集群模式,您只需要设置 Redis 服务器。对于 Ubuntu,请遵循:https ://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04

npm i socket.io-redis
const redisAdapter = require('socket.io-redis')

global.io = require('socket.io')(server, { transports: [ 'websocket' ]})

io.adapter(redisAdapter({ host: 'localhost', port: 6379 }))

这是 npm 包:https ://www.npmjs.com/package/socket.io-redis

让我的套接字在集群模式下工作就这么简单。


推荐阅读