首页 > 解决方案 > 如何在 Heroku 中运行监听 MongoDB 和监听套接字 io 消息的快速服务器?

问题描述

我正在为 Heroku 设置服务器后端,它正在侦听 google Oauthentication,侦听要保存到 Mongo DB 的消息,并侦听聊天消息以使用套接字 io 发送给所有连接的用户。

仅供参考,我的应用程序是使用 React 构建的。

在我的本地主机上运行时,我能够让这些功能按预期工作,但我必须在两个不同的端口上设置套接字 io 使用的 http 服务器实例和所有其他功能使用的 express 服务器。

然而 Heroku 只允许我访问一个端口。

我一直在网上寻找不同的解决方案。

我最好的选择似乎是尝试让套接字 io 通过同一个端口发送消息,但是当我这样做时,我收到一个错误,指出我不能让两个不同的服务器访问同一个端口。

因此,即使我使用相同的 express 实例来为 socket io 创建我的 http 服务器实例,它们也被认为是单独的实例。

我的主要问题是,socket io 需要一个 http 服务器实例,并且所有其他功能都可以使用 express 服务器运行。

我想知道是否有人在尝试部署到 Heroku 时遇到过这样的问题?我一直在寻找有类似问题的人,但没有任何运气。我真的可以在这个问题上使用一些指针。

我在下面发布我的服务器代码。

编辑 2019 年 5 月 21 日:我决定减少相关代码,因为有很多与问题无关的内容需要解析。

require(`dotenv`).config();
require("./config/connection");

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

// Routes to Mongo DB
const chatRouter = require('./routes/chat');

// Passport
const passport = require("passport");
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const mongoose = require('mongoose');
const keys = require('./config/keys');

// socket io
const server = require('http').createServer(app);
const io = require('socket.io')(server);

// google
const routes = require("./routes");
const cookieSession = require('cookie-session');
const path = require('path');

const db = require('./model');

const PORT = process.env.PORT || 3001;

// Tells Express to Read the data sent in JSON format
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

// Tells Express to allows data to be sent across different origins
// required by CORS policy
app.use(function (req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

// Implementation of other features such as saving chat messages to database
// and implementing passport
...

// Chat implementation using Socket IO

io.on('connection', client => {

  // implementing chat feature
  ...

});

server.listen('8000', () => {
  console.log('listening on port 8000');
});

// alternatively we can attempt to listen on the port specified by Heroku
// server.listen(PORT, () => {
//   console.log(`listening on port ${PORT}`);
// });

// implementing more features, such as Google Oauth
// and other api routes
...

// Express application instance listening on port specified by Heroku
app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});

我很感激可以在这个问题上提供的任何帮助。

谢谢!

标签: javascriptnode.jsreactjsexpresssocket.io

解决方案


所以看起来我的问题已经被问到并得到了回答。

您可以在以下链接中找到答案, Socket.io + NodeJS doesn't work on Heroku

我只是在这里做一个简短的总结。

Heroku 要求我们的应用程序在从前端到后端通信时在同一个端口上运行我们 API 的所有功能,反之亦然。所以我第一次尝试指定两个不同的端口在本地工作,但在部署到 Heroku 时失败了。

然后我尝试对两个服务器实例使用相同的端口。


// implementing express
const express = require('express');
const app = express();

// uses port provided by Heroku OR port 3000
const PORT = process.env.PORT || 3000;

...

// implementing Socket IO
const server = require('http').createServer(app); // creates an instance of an http server
const io = require('socket.io')(server);

...

io.on('connection', client => {

    // server side chat features implemented here

}

server.listen(PORT); 

...

app.listen(PORT); // Express is returning a different instance of the http server

解决方案比我想象的要简单。

由于 app.listen(PORT) 返回一个 http 服务器的实例,我们可以将它用于 Socket IO。在单击之前,我必须先查看一些示例代码。Full Stack Web Development Bootcamp 的一位老师将我链接到这个 git hub 存储库,演示如何在将应用程序部署到 Heroku 时使用套接字 IO。

请参阅以下链接, https://github.com/heroku-examples/node-socket.io/blob/master/server.js

上面示例中的实现看起来有些不同,但实际上执行的操作与我将在下面的示例中演示的相同,


// get Express library and create Express application
const express = require('express');
const app = express();

// get socket io library
const SocketIO = require('socket.io');

// uses port provided by Heroku OR port 3000
const PORT = process.env.PORT || 3000;

...

// This time we store the HTTP Server instance in a variable
// when we tell the Express application to listen on the specified port
const server = app.listen(PORT); 

// and use that instance to implement our socket io connection
const io = SocketIO.listen(server);

io.on('connection', client => {

    // server side chat features implemented here

}

希望这个解释可以帮助其他人理解并避免我面临的问题。

并且一定要查看发布的链接,因为我发现它们对于理解我面临的问题以及如何解决它很有用。


推荐阅读