【问题标题】:Nodejs server deployed on Heroku. Requests fail部署在 Heroku 上的 Nodejs 服务器。请求失败
【发布时间】:2021-08-06 10:42:27
【问题描述】:

我有一个迷你论坛应用程序,包括传递到包的身份验证、帖子、cmets 和网关。在本地,所有请求都可以正常工作。但是在部署到 Heroku 之后,只有 GET 请求有效,其他请求失败。

日志中的错误:[HPM] 代理请求 anaalamed-mini-forum.herokuapp.com/api/login 到 http://localhost:4000/ [ECONNRESET] (https://nodejs.org/api/errors.html#errors_common_system_errors) 时发生错误

这是我的第一步,所以...感谢您的帮助

网关/index.ts

import { app } from 'api-server';
import { createProxyMiddleware } from 'http-proxy-middleware';
import fetch from 'node-fetch';
import * as express from 'express';
import * as path from 'path';

app.use(['/api/comments', '/api/posts'], async function checkAuth(req, res, next) {
try {
    const response = await fetch('http://localhost:4000/api/me', { headers: { cookie: req.headers.cookie } })
    const user = await response.text();
    const setCookie = response.headers.get('set-cookie')
    if (setCookie) {
        res.append('set-cookie', setCookie);
    }
    req.headers.user = user;
} catch {
    req.headers.user = '';
}
next();
})
app.use('/api/comments', createProxyMiddleware({ target: 'http://localhost:4002', changeOrigin: true }));
app.use('/api/posts', createProxyMiddleware({ target: 'http://localhost:4001', changeOrigin: true }));
app.use(['/api/users', '/api/me', '/api/register', '/api/login', '/api/logout'], createProxyMiddleware({ target: 'http://localhost:4000', changeOrigin: true }));

// serve UI
app.use(express.static(path.resolve(__dirname, '../../ui/build')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../../ui/build', 'index.html'));
});

app.listen(process.env.PORT || 8080, () => console.log('Gateway app is running! on Port: ', process.env.PORT))

日志

2021-08-06T10:19:59.365861+00:00 heroku[router]: at=info method=GET path="/api/comments?entity=61068acdbe91bb0f7145ccf3" host=anaalamed-mini-forum.herokuapp.com request_id=5f0d58d4-fd3f-495a-b86c-6494fcc8ebe1 fwd="5.29.13.122" dyno=web.1 connect=0ms service=82ms status=304 bytes=183 protocol=https
2021-08-06T10:19:59.391481+00:00 heroku[router]: at=info method=GET path="/api/comments?entity=61069bf0be91bb0f7145ccf4" host=anaalamed-mini-forum.herokuapp.com request_id=49fbacde-0fc5-491b-81e5-1538eda0747b fwd="5.29.13.122" dyno=web.1 connect=0ms service=80ms status=304 bytes=181 protocol=https
2021-08-06T10:19:59.332485+00:00 heroku[router]: at=info method=GET path="/api/comments?entity=610689fdbe91bb0f7145ccf2" host=anaalamed-mini-forum.herokuapp.com request_id=f75eab61-bfe5-43b4-8a53-c6757ff4972c fwd="5.29.13.122" dyno=web.1 connect=1ms service=81ms status=304 bytes=183 protocol=https
2021-08-06T10:19:59.364159+00:00 app[web.1]: [start:comments] ::ffff:127.0.0.1 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61068acdbe91bb0f7145ccf3 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.366881+00:00 app[web.1]: [start:gateway] ::ffff:10.13.124.73 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61068acdbe91bb0f7145ccf3 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.388509+00:00 app[web.1]: [start:comments] ::ffff:127.0.0.1 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61069bf0be91bb0f7145ccf4 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.390036+00:00 app[web.1]: [start:gateway] ::ffff:10.15.14.173 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61069bf0be91bb0f7145ccf4 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.609755+00:00 app[web.1]: [start:gateway] ::ffff:10.32.238.58 - - [06/Aug/2021:10:19:59 +0000] "GET /icon.png HTTP/1.1" 200 157694 "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.616941+00:00 heroku[router]: at=info method=GET path="/icon.png" host=anaalamed-mini-forum.herokuapp.com request_id=4b32c985-21e1-46cf-b2b6-63ece2e09e57 fwd="5.29.13.122" dyno=web.1 connect=1ms service=12ms status=200 bytes=158004 protocol=https
2021-08-06T10:21:31.302014+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=POST path="/api/login" host=anaalamed-mini-forum.herokuapp.com request_id=3ff0432f-90f0-4e71-92b3-48d21c1966f3 fwd="5.29.13.122" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https
2021-08-06T10:21:31.310593+00:00 app[web.1]: [start:gateway] [HPM] Error occurred while proxying request anaalamed-mini-forum.herokuapp.com/api/login to http://localhost:4000/ [ECONNRESET] (https://nodejs.org/api/errors.html#errors_common_system_errors)
2021-08-06T10:21:31.321710+00:00 app[web.1]: [start:gateway] ::ffff:10.39.170.242 - - [06/Aug/2021:10:21:31 +0000] "POST /api/login HTTP/1.1" 504 - "https://anaalamed-mini-forum.herokuapp.com/login" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:21:31.323846+00:00 app[web.1]: [start:auth] ::ffff:127.0.0.1 - - [06/Aug/2021:10:21:31 +0000] "POST /api/login HTTP/1.1" - - "https://anaalamed-mini-forum.herokuapp.com/login" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:21:31.334977+00:00 app[web.1]: [start:auth] BadRequestError: request aborted
2021-08-06T10:21:31.334980+00:00 app[web.1]: [start:auth]     at IncomingMessage.onAborted (/app/node_modules/raw-body/index.js:231:10)
2021-08-06T10:21:31.334981+00:00 app[web.1]: [start:auth]     at IncomingMessage.emit (events.js:400:28)
2021-08-06T10:21:31.334981+00:00 app[web.1]: [start:auth]     at abortIncoming (_http_server.js:566:9)
2021-08-06T10:21:31.334981+00:00 app[web.1]: [start:auth]     at socketOnClose (_http_server.js:559:3)
2021-08-06T10:21:31.334982+00:00 app[web.1]: [start:auth]     at Socket.emit (events.js:412:35)
2021-08-06T10:21:31.334982+00:00 app[web.1]: [start:auth]     at TCP.<anonymous> (net.js:675:12)

根目录下的package.json

{
  "name": "mini-forum",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "scripts": {
    "dev": "concurrently \"npm run dev:*\"",
    "dev:auth": "npm run dev --workspace=apps/auth",
    "dev:posts": "npm run dev --workspace=apps/posts",
    "dev:gateway": "npm run dev --workspace=apps/gateway",
    "db": "docker-compose --file ./mongo-compose.yaml up",
    "start": "node start.js",
    "start:comments": "cd apps/comments && npm start",
    "start:auth": "cd apps/auth && npm start",
    "start:posts": "cd apps/posts && npm start",
    "start:gateway": "cd apps/gateway && npm start",
    "postinstall": "node postinstall.js",
    "build": "cd apps/ui && npm install && npm run build"
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "concurrently": "^6.0.2",
    "cors": "^2.8.5",
    "nodemon": "^2.0.7"
  },
  "engines": {
    "npm": "7.10.0"
  },
  "devDependencies": {
    "prettier": "2.3.1"
  }
}

start.js

const concurrently = require('concurrently');

// concurrently([{command: 'npm run start:*', env: process.env}])
concurrently([{command: 'npm run start:*'}])

所以“npm start”会启动所有应用程序:auth、posts、cmets 和 gateway。所有的应用程序都有自己的 package.json 并且可以单独启动。

【问题讨论】:

    标签: node.js express heroku


    【解决方案1】:

    您的 createProxyMiddleware 背后的原因是什么? 一旦您的应用程序在 Heroku 服务器上运行,这将失败,因为它将请求代理到 localhost:4002 / localhost:4001,这意味着应用程序将请求转发到将在同一服务器实例上运行的另一个“本地”服务(他们没有)。

    在本地对您来说它可能有效,因为您在测试应用程序时在本地运行了其他服务,但 Heroku 上不存在这些其他服务。

    #1 使用procfile

    您可以使用procfile 让多个 nodejs 进程在 1 个 dyno 下运行。正如this answer 中所述,这可能看起来像这样:

    web: node service1.js & node service2.js & node service3.js
    

    但是,由于您的每个服务都需要单独的端口,这可能对您不起作用,因为 heroku 只为每个测功机打开 1 个动态分配端口(在运行时在 process.env.PORT 下可用)。如果我是正确的,这是无法更改的。

    #2 使用多个应用程序/dynos

    我相信使用 heroku 的目的(建立微服务架构)是为每个服务创建 1 个应用程序,每个服务至少 1 个 dyno。这样做的大专业人士将能够相互独立地扩展每个服务。然后只需使用分配的子域来调用它们(app1.herokuapp.comapp2.herokuapp.com,...)。此外,您最终将拥有独立指标,并且可以独立更新测功机。这基本上是微服务背后的理念。

    #3 暂时不要使用微服务

    看着您的示例,感觉您可能不需要将其拆分为多个服务。考虑创建一个 API,如果您刚开始,它可能更容易管理。

    【讨论】:

    • 那么createProxyMiddleware中就不需要了?如何更改它以使其在 Heroku 上工作?非常感谢!
    • 您似乎正试图将您的应用拆分为多个微服务。如果是,您需要在 Heroku 上也运行这些微服务……否则您无法访问它们。这是你想要达到的目标吗?
    • 是的,完全正确。我需要那些在 Heroku 上运行的微服务
    • 这取决于您如何进行此设置。这些服务是独立启动/停止的 NodeJS/NPM 项目吗?还是它们都存在于同一个项目中,而您只是在脚本中启动所有其他服务?您可能希望在您的 OP 中分享尽可能多的信息 ....
    • 我添加了更多信息
    猜你喜欢
    • 1970-01-01
    • 2018-04-18
    • 2021-12-11
    • 2019-02-16
    • 2022-01-24
    • 2016-02-20
    • 1970-01-01
    • 2019-03-05
    • 2021-07-19
    相关资源
    最近更新 更多