如何在Heroku上获取非Web进程端口?含HapiJS代理场景
嘿!咱们一步步来解决你的两个问题:
1. 如何在Heroku上查询Web进程之外其他进程使用的端口
- 通过环境变量查询:如果你的非Web进程(比如worker或者自定义dyno)是用环境变量来指定端口的(比如
WORKER_PORT),直接用Heroku CLI就能获取这个值:
不管你是通过heroku config:get WORKER_PORTheroku config:set WORKER_PORT=XXXX命令设置的变量,还是在Procfile/代码里定义的,这个方法都管用。 - 查看dyno日志:如果你的进程启动时会打印监听的端口信息,你可以过滤对应dyno的日志来查看:
把heroku logs --dyno=<你的dyno名称><你的dyno名称>换成你的非Web进程dyno的名字(比如Procfile里定义的worker),然后找包含“listening on port”或者类似描述的日志行就行。 - 直接在dyno里执行命令:用Heroku的exec功能进入运行中的dyno shell,然后用网络工具查看开放端口:
- 先进入dyno shell:
heroku ps:exec --dyno=<你的dyno名称> - 进入后,用
ss命令(Heroku dyno里一般没有netstat,ss更常用)列出监听的端口:
这个命令会显示所有正在监听端口的进程,你可以通过进程名称找到对应的非Web进程端口。ss -tulpn
- 先进入dyno shell:
2. 在HapiJS中获取非Web进程的端口并代理请求
首先要明确:Heroku不会像给Web进程自动分配$PORT环境变量那样,给非Web dyno自动分配端口。所以你需要给私有Webhook服务器显式设置一个端口变量,然后在HapiJS应用里读取它。下面是完整的实现步骤:
步骤1:配置Webhook服务器使用环境变量端口
修改你的Webhook服务器代码,从环境变量读取端口(不要硬编码),示例:
// webhook-server.js const port = process.env.WEBHOOK_PORT || 3001; // 本地开发时 fallback 到3001 // ... 启动服务器并监听 port 端口
然后在Heroku上设置这个环境变量:
heroku config:set WEBHOOK_PORT=3001
如果你的HapiJS服务器和Webhook服务器运行在同一个dyno里(比如Procfile里用web: node server.js & node webhook-server.js这样的命令启动),这个环境变量会被两个进程共享。
步骤2:在HapiJS中配置代理
使用Hapi官方的代理插件@hapi/h2o2来将特定请求转发到私有Webhook服务器,设置方法如下:
- 安装插件:
npm install @hapi/h2o2 - 在HapiJS服务器中注册插件并添加代理路由:
// server.js const Hapi = require('@hapi/hapi'); const h2o2 = require('@hapi/h2o2'); const init = async () => { const server = Hapi.server({ port: process.env.PORT || 3000, host: '0.0.0.0' }); // 注册代理插件 await server.register(h2o2); // 添加代理路由,将/webhook下的所有请求转发到Webhook服务器 server.route({ method: ['GET', 'POST', 'PUT'], // 匹配Webhook支持的HTTP方法 path: '/webhook/{path*}', // 代理/webhook下的所有路径 handler: { proxy: { uri: `http://localhost:${process.env.WEBHOOK_PORT}/{path}`, passThrough: true, // 转发请求头、请求体等信息 xforward: true // 设置X-Forwarded-For、X-Forwarded-Proto等头部 } } }); await server.start(); console.log('服务器运行在 %s', server.info.uri); }; init();
这样一来,所有发送到你的Heroku应用域名/webhook/...的请求,都会被转发到运行在localhost:<WEBHOOK_PORT>/...的私有Webhook服务器。
重要注意事项
- 如果你的Webhook服务器和HapiJS服务器在不同的dyno里,
localhost就无法访问了。这种情况下你需要用Heroku私有空间或者其他私有网络方案,不过复杂度会高很多。大部分场景下,把两个进程放在同一个dyno里做内部代理是更简单的选择。 - 永远用环境变量而不是硬编码端口——这样你的应用在本地开发和Heroku部署时都能灵活适配。
内容的提问来源于stack exchange,提问作者bobber205
相关产品推荐
相关产品推荐

