node.js 服务器在 elastic beanstalk ALB 上有 websockets 没有 socket.io

node.js server with websockets on elastic beanstalk ALB without socket.io

我正在尝试让 node.js 服务器(使用 express)使用应用程序负载均衡器(ALB)在弹性 beanstalk(EB)中使用 websockets,但不使用 socket.io(因为 peerjs- server 是我要获取的服务器 运行 而不是用 socket.io).

写的

我看过几篇文章建议您必须使用 socket.io(或另一个不依赖于 websockets 的库),但亚马逊说 ALB 直接支持 websockets。

我的服务器既是 create-react-app 服务器又是 peerjs-server。对于 Web UI 和 peerjs ws 连接,它在端口 9000 上的开发中运行良好。

我已经尝试了我发现的所有不同方法,但我还没有得到它的工作,我什至看到了一些暗示它无法完成的东西,但看起来快到了。有没有人让这个工作,如果是的话,怎么做?

好的,我让它工作了。以下是我为使一切在端口 9000 上正常工作所做的工作。

在 EB 中,创建应用程序,然后开始创建环境。

在环境配置中,进入 Software 部分并告诉它您将使用 npm run prod 来启动您的服务器。:

现在,进入 负载均衡器 部分,如下图所示:

  1. 在端口 9000 上添加监听器
  2. 在端口 9000 上创建一个进程并启用粘性(我调用了我的 peerjsServer)
  3. 为您要用于访问服务器的每个 URL 路径添加规则,并将每个规则分配给您创建的进程 (peerjsServer)。还将默认值指向该进程,以便 80 上的健康检查成功通过您的服务器

您可能需要跳转到 AWS UI 中的 EC2 仪表板,以确保必要的安全组 在那里定义。我想我在 上创建了前两个,后两个是默认创建的,但我不记得了。无论如何,他们需要为入站和出站打开端口 9000(默认情况下始终存在端口 80):

返回 EB 配置,转到 实例 部分并确保您的实例已分配给它的安全组:

我 运行 react-scripts build 使 /build 目录包含服务器的生产版本 UI(这是我创建的 create-react-apps 东西这里不涉及)。

在我的代码中,我使用 server.js 启动服务器,它使服务器成为 运行 peerjs-server ws 服务器和 http 服务器。

const express = require("express");
const bodyParser = require("body-parser");
const path = require('path');

const passport = require("passport");
const users = require("./routes/api/users");
const games = require("./routes/api/games");
const Game = require("./src/models/Game");

const WebSocket = require('ws');
const ExpressPeerServer = require('peerjs-server').ExpressPeerServer;

const app = express();
const url = require('url');

const port = process.env.PEERSERVERPORT || 9000; 

// WebSocket for making db updates to client.
const wsserver = require('./wsserver').wsserver

// Server that gets all requests: lobby UI, peerserver, db websocket
const server = require('http').createServer(app);

wsserver.on('connection', function connection(ws) {
  ws.on('message', msg => {
    ws.send(msg)
  })

  ws.on('close', () => {
    console.log('WebSocket was closed')
  })
});

server.on('upgrade', function upgrade(request, socket, head) {
  const pathname = url.parse(request.url).pathname;

  if (pathname === '/ws') {
    wsserver.handleUpgrade(request, socket, head, function done(ws) {
      wsserver.emit('connection', ws, request);
    });    
  }
});

// Bodyparser middleware
app.use(
  bodyParser.urlencoded({
    extended: false
  })
);
app.use(bodyParser.json());

// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);

// Routes -- the /api/* path is defined in the EB load balancer
app.use("/api/users", users);
app.use("/api/games", games);

// This is the create-react-apps /build directory of UI code
app.use(express.static(path.join(__dirname, 'build')));
app.get('/login', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

// These are the paths that are defined in the EB load balancer
app.get('/logout', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.get('/register', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.get('/dashboard', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

// Peer server for making WebRTC connections between game clients.
const options = { 
    debug: true
}
const peerserver = ExpressPeerServer(server, options);
app.use('/peerserver', peerserver);

app.use(express.static(path.join(__dirname, 'src')));

app.get('*', function(req, res) {
  res.sendFile(path.join(__dirname, 'src', 'index.html'));
});

peerserver.on('disconnect', (client) => {
  console.log('Delete the game if the host client disconnects');
  Game.deleteMany({ hostPeerId: client })
    .then(() => {
      wsserver.clients.forEach(function each(client) {
        if (client.readyState === WebSocket.OPEN) {
          client.send("refreshGames");
        }
      })
    })
    .catch(err => console.log(err));
});

server.listen( port, () => console.log(`Server is up and running on port ${port} !`))

然后在我的package.json中,我将prod的脚本设置为运行上面的server.js来启动服务器,npm 运行 prod我把在前面的 Software 部分中,调用它来使服务器运行:

  ...
  "scripts": {
    "start": "set PORT=8081&& react-scripts start",
    "prod": "node server.js",
  ...

完成所有这些之后,我现在有一个使用 ALB 并处理端口 9000 上的 websocket (ws) 和 UI (http) 流量的 运行ning EB 服务器。