Apache反向代理到Node - 连接被拒绝:AH00957

10

我正在尝试使用默认版本的20.04服务器Ubuntu和Apache与Node一起使全新基于云的服务器运行。Node服务器似乎正在运行,并报告4006端口已打开,但我认为我的Apache配置没有问题。请求将会非常非常长时间挂起,而节点终端中不显示任何错误信息。因此,故障必定存在于我的Apache配置中,因为我们得到以下Apache错误而无JS错误。

一段时间后出现请求错误

502 proxy error

Apache错误日志

[Sun Oct 17 20:58:56.608793 2021] [proxy:error] [pid 1596878] (111)Connection refused: AH00957: HTTP: attempt to connect to [::1]:4006 (localhost) failed
[Sun Oct 17 20:58:56.608909 2021] [proxy_http:error] [pid 1596878] [client 207.46.13.93:27392] AH01114: HTTP: failed to make connection to backend: localhost

虚拟主机
<VirtualHost IP_ADDRESS:80>
    ServerName api.aDomain.com
    Redirect permanent / https://api.aDomain.com/
</VirtualHost>
<IfModule mod_ssl.c>
    <VirtualHost IP_ADDRESS:443>
        ServerName api.aDomain.com

        ProxyRequests on
        LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
        LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so

        ProxyPass / http://localhost:4006/
        ProxyPassReverse / http://localhost:4006/
    

        #certificates SSL
        SSLEngine on
        SSLCACertificateFile /etc/ssl/api.aDomain.com/apimini.ca
        SSLCertificateFile /etc/ssl/api.aDomain.com/apimini.crt
        SSLCertificateKeyFile /etc/ssl/api.aDomain.com/apimini.key

        ErrorLog ${APACHE_LOG_DIR}/error_api.aDomain.com.log
        CustomLog ${APACHE_LOG_DIR}/access_api.aDomain.com.log combined

    </VirtualHost>
</IfModule>

终端输出

[nodemon] 1.19.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `babel-node -r dotenv/config --inspect=9229 index.js`
Debugger listening on ws://127.0.0.1:9229/c1fcf271-aea8-47ff-910e-fe5a91fce6d2
For help, see: https://nodejs.org/en/docs/inspector
Browserslist: caniuse-lite is outdated. Please run next command `npm update`
 Server ready at http://localhost:4006

Node服务器

import cors from 'cors'

import scrape from './src/api/routes/scrape'

const express = require('express')
const { ApolloServer, gql } = require('apollo-server-express')
const { postgraphile } = require('postgraphile')
const ConnectionFilterPlugin = require('postgraphile-plugin-connection-filter')

const dbHost = process.env.DB_HOST
const dbPort = process.env.DB_PORT
const dbName = process.env.DB_NAME
const dbUser = process.env.DB_USER
const dbPwd = process.env.DB_PWD
const dbUrl = dbPwd
  ? `postgres://${dbUser}:${dbPwd}@${dbHost}:${dbPort}/${dbName}`
  : `postgres://${dbHost}:${dbPort}/${dbName}`

var corsOptions = {
  origin: '*',
  optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
}

async function main() {
  // Construct a schema, using GraphQL schema language
  const typeDefs = gql`
    type Query {
      hello: String
    }
  `

  // Provide resolver functions for your schema fields
  const resolvers = {
    Query: {
      hello: () => 'Hello world!',
    },
  }

  const server = new ApolloServer({ typeDefs, resolvers })

  const app = express()
  app.use(cors(corsOptions))
  app.use(
    postgraphile(process.env.DATABASE_URL || dbUrl, 'public', {
      appendPlugins: [ConnectionFilterPlugin],
      watchPg: true,
      graphiql: true,
      enhanceGraphiql: true,
    })
  )
  server.applyMiddleware({ app })

  //Scraping Tools
  scrape(app)

  const port = 4006
  await app.listen({ port })
  console.log(` Server ready at http://localhost:${port}`)
}

main().catch(e => {
  console.error(e)
  process.exit(1)
})

启用的Apache模块

/etc/apache2/mods-enabled/proxy.conf /etc/apache2/mods-enabled/proxy.load /etc/apache2/mods-enabled/proxy_http.load

更新的错误日志

[Thu Oct 21 10:59:22.560608 2021] [proxy_http:error] [pid 10273] (70007)The timeout specified has expired: [client 93.115.195.232:8963] AH01102: error reading status line from remote server 127.0.0.1:4006, referer: https://miniatureawards.com/
[Thu Oct 21 10:59:22.560691 2021] [proxy:error] [pid 10273] [client 93.115.195.232:8963] AH00898: Error reading from remote server returned by /graphql, referer: https://miniatureawards.com/

在节点服务上执行curl/wget命令,查看是否返回任何内容。Apache配置看起来没问题。也许节点没有将套接字绑定到正确的网络接口。这只是猜测,因为您没有提及节点应用程序的任何信息。 - Marc
因此,/graphiql 端点在没有任何模式的情况下加载,但确实加载了。这意味着代理可能正在工作,我需要确保 psql 权限正确,从逻辑上讲,这就是它对我的含义! - Jamie Hutber
在您的VirtualHost中,您设置了ProxyRequests on,这是用于正向代理,但实际上您定义了一个反向代理。我建议首先将ProxyRequests关闭(默认值)。从文档中可以看到,在典型的反向代理或网关配置中,此选项应设置为Off。 - Chris
4个回答

4

哇,我从来没有想到过 - 非常感谢! - Ricky Levi

1
我无法确切预测会发生什么,可能是NodeJS应用程序崩溃并且不再运行,或者是Apache文件配置错误。但我强烈相信,从头开始做这件事情可以解决这种情况。
这一步将更新Ubuntu软件包,安装所需的应用程序,配置Apache文件,并设置与NodeJS和Apache的反向代理。
只要不触及您的NodeJS文件和其他相关代码应用程序,它们就会很安全。您也可以备份以确保安全。该Ubuntu服务器上运行的其他应用程序,例如数据库应用程序,如MySQL,仍将正常运行。

1. 首先,我们需要更新Ubuntu软件包并安装Apache和NodeJS。


$ sudo apt update
$ sudo apt install apache2 npm


2. 运行此命令以使我们能够使用Apache作为反向代理服务器


sudo a2enmod proxy proxy_http rewrite headers expires



3. 创建一个Apache虚拟主机文件

该命令将允许您使用Ubuntu终端作为文本编辑器,按照终端的指南和提示进行编写。

注意:

将“yourSite.com”更改为您网站的域名。这并不是很重要,应该是文件名。但我认为最好以您的站点域名命名,这样您可以识别它。


$ sudo nano /etc/apache2/sites-available/yourSite.com.conf


使用nano编辑器编写您网站的Apache配置文件非常重要。
注意:这部分内容至关重要,请注意。
将ServerName和ServerAlias更改为您的站点域名。
ProxyPass和ProxyPassReverse各有两个参数。
第一个是反斜杠“/”,它是您的NodeJS应用程序所在的绝对路径,因为只有一个反斜杠,这意味着它是您的主目录。
第二个是您的NodeJS应用程序的url“http://127.0.0.1:3000/”。请注意其端口“3000”,您可能需要将其替换为NodeJS应用程序中使用的端口。

<VirtualHost *:80>
    ServerName example.com // replace this with site domain name without www at the beginning
    ServerAlias www.example.com // replace this with site domain name beginning with www. + yourdomainname + .com

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia Full

    <Proxy *>
        Require all granted
    </Proxy>

    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:30000/
</VirtualHost>


5. 禁用默认的Apache网站并启用新的网站。

$ sudo a2dissite 000-default
$ sudo a2ensite example.com.conf


6. 重新启动Apache服务器以应用更改

sudo systemctl restart apache2


我们已经完成了将Apache设置为反向代理的工作,现在需要安装你的项目的npm包并运行NodeJS应用程序。

7. 接下来的步骤都与NodeJS部署相关。你可能已经知道这些步骤。


// install npm packages
npm install

// for a better experience using NodeJS in production install pm2 globally
npm install -g pm2

// Then run your NodeJS application using pm2 command

pm2 start // you should be at root of your NodeJS project folder when running this command

// run this another pm2 command to make sure your NodeJS app will re-run when it encounter downtime.

$ pm2 save
$ pm2 startup


您的Apache和NodeJS服务器现在已经启动。尝试通过在浏览器地址栏中输入您的站点域名来访问您的站点。
例如:http://yourSite.com

我还没有时间彻底测试这个,但遗憾的是里面没有任何帮助我的东西。或者是我已经知道的。我将启动一个新服务器并试一试! - Jamie Hutber
我愿意帮忙,只需在评论中提醒我。 - German

1

我不是这个主题的专家,但我有一个类似的设置;我使用 socket.io 来提供 WebSockets 服务...

从你的帖子中看来,你似乎不需要代理 WebSockets,你日志中显示的那个似乎只用于调试目的(如果我错了,请纠正我)。

以下是我的 Apache 配置核心:

    RewriteEngine On

    RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
    RewriteCond %{QUERY_STRING} transport=websocket    [NC]
    RewriteRule /(.*)           ws://127.0.0.1:4006/$1 [P,L]

    <Location />
        ProxyPass        http://127.0.0.1:4006/ retry=2
        ProxyPassReverse http://127.0.0.1:4006/
    </Location>

另外还有几点建议。

警告

在您保护好服务器之前,请勿启用代理 ProxyRequests。公开代理服务器对您的网络和整个互联网都是危险的。

来源:https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyrequests

我不知道您的主机上的IPV6设置是什么,您可以尝试在Apache配置中使用 127.0.0.1 而不是 localhost,以尝试强制Apache使用IPV4。


感谢 @danieleRicci。我已经尝试了上面的方法,我仍然可以访问 \graphiql 但无法访问 \graphql 端点。 i 是不同之处:D 这让我想到...可能代理实际上正在工作?但是对我来说没有意义的是,如果 Apache 代理不起作用,我怎么能通过代理访问 https://api.miniatureawards.com/graphiql。但是 https://api.miniatureawards.com/graphql 没有返回任何内容。但是 Apache 的日志给了我代理错误!嗯,需要好好思考一下。 - Jamie Hutber
抱歉@JamieHutber,我不确定您是否能够访问http://localhost:4006/graphql(显然是从同一主机)。除此之外,很抱歉,我不了解GraphQL,/graphql URL上的协议是什么?简单的HTTP吗? - Daniele Ricci
谢谢你们的支持:)我感觉我可能会让人们陷入一个黑洞中:) 然而/graphql是http协议。我可以访问http://localhost:4006/graphql,因为我可以使用curl命令从该URL获取结果。但是,当我尝试从Web浏览器访问此URL时,服务器没有返回任何响应。 - Jamie Hutber
那么,问题解决了吗,@JamieHutber?好多了 :) - Daniele Ricci
很遗憾,不是这样的。我已经迁移了我的一台旧服务器,所以我不知道问题出在哪里。只是当我尝试访问/graphql时,它会挂起,没有任何错误或通知。 - Jamie Hutber

0
如果您使用Docker作为节点服务器,那么它可能设置不正确。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接