John Wick

使用 StayPresent 部署一个永不休眠的 Railway Python 机器人——端口绑定、健康检查、自 ping 以及崩溃恢复。

在 Railway 上使用 StayPresent 运行永不休眠的 Python 机器人

Railway 会自动检测 Python 项目并在几分钟内完成部署,但铁路 Python 机器人(Discord 机器人、Telegram 机器人或爬虫)仍会遇到每个 PaaS 都存在的核心问题:平台期望一个面向 HTTP 的进程,而机器人的事件循环或网关连接并不会自然地提供这样的进程。本指南介绍如何使用 StayPresent 将机器人部署到 Railway 并保持在线。

目录

  1. Railway 如何检测并运行 Python 应用
  2. $PORT 要求
  3. 设置 StayPresent
  4. Railway 仪表盘中的健康检查
  5. 针对不活动敏感方案的自 Ping
  6. 崩溃恢复
  7. 完整可运行示例
  8. 最佳实践
  9. 常见错误
  10. 常见问题
  11. 结论

Railway 如何检测并运行 Python 应用

Railway 会通过 Nixpacks 从 requirements.txt(或 pyproject.toml)自动检测 Python 项目并为其构建容器,无需 Dockerfile。然后启动你的应用,并期望它绑定到 Railway 通过 PORT 环境变量分配的端口,以便其自身的路由和健康检查能够访问。

$PORT 要求

这与几乎所有现代 PaaS 遵循的模式相同:从环境变量读取 PORT,而不是硬编码。

import os
import staypresent

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
)

Enter fullscreen mode Exit fullscreen mode

如果你的机器人根本没有绑定到这个端口——这对于 Discord 或 Telegram 机器人来说是正常、预期的行为——即使你的机器人本身可能运行良好,Railway 的健康检查(如果已启用)也会报告部署不健康。

设置 StayPresent

安装生产环境扩展,以便让 Waitress 处理服务而非 Flask 的开发服务器:

pip install staypresent[prod]

Enter fullscreen mode Exit fullscreen mode

你的 main.py

import os
import staypresent

staypresent.web.json({
    "status": "running",
    "service": "my-telegram-bot",
})

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
)

Enter fullscreen mode Exit fullscreen mode

Railway 的启动命令很简单:

python main.py

Enter fullscreen mode Exit fullscreen mode

Railway 仪表盘中的健康检查

如果你为服务启用了 Railway 的健康检查功能,可以将其指向 StayPresent 内置的 /health 端点,该端点始终返回 {"status": "ok"}——无论你在根路由上配置了什么:

staypresent.web.json({"status": "running"})
# /health 仍返回 {"status": "ok"},与上述配置无关

Enter fullscreen mode Exit fullscreen mode

这将平台级健康监控与你在 / 提供给人类或自有工具的自定义状态载荷分离开来。

针对不活动敏感方案的自 Ping

是否会因不活动而休眠取决于你的具体 Railway 方案和配置——在做出任何假设前,请务必查阅 Railway 当前的定价和使用文档。如果你的部署适用此规则,staypresent.cron() 会向你自己的公开 URL 发送出站流量,以防止被视为闲置:

import staypresent

staypresent.cron(
    "https://my-app.up.railway.app",
    interval=240,
)

Enter fullscreen mode Exit fullscreen mode

与任何平台一样,这必须指向实际的公开 URL——ping 0.0.0.0127.0.0.1 不会离开机器,对不活动检测没有影响。

崩溃恢复

机器人会因各种常见原因崩溃,而 Railway 不会自动重启在容器内死亡的子进程,除非容器本身退出。StayPresent 直接处理这一内层:

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
    restart_on_crash=True,
    max_restarts=5,
    restart_delay=2.0,
    restart_reset_after=60.0,
)

Enter fullscreen mode Exit fullscreen mode

如果最终重启次数耗尽,StayPresent 会以机器人原始退出码退出整个进程——让 Railway 自己的部署重启策略作为最后的保障。

完整可运行示例

import os
import staypresent

staypresent.web.json({"status": "running"})

staypresent.cron("https://my-app.up.railway.app", interval=240)

staypresent.run(
    "bot.py",
    port=int(os.getenv("PORT", 8080)),
    threads=8,
    restart_on_crash=True,
    max_restarts=5,
)

Enter fullscreen mode Exit fullscreen mode

最佳实践

  • 始终动态读取 PORT——Railway 每次部署都会分配该端口,且不同环境可能不同。
  • 如果根路由提供自定义内容,请将任何已配置的健康检查指向 /health 而非 /
  • 对于接收真实流量的部署,请始终安装 prod 扩展,而不仅仅是用于保活 ping。

常见错误

  • 硬编码 port=8080 而非读取 os.getenv("PORT", 8080)——这在某些配置下可能有效,但在其他配置下可能静默失败,取决于 Railway 的设置方式。
  • 假设 Railway 的休眠行为与 Render 相同。 各平台策略不同且会随时间变化——请查阅 Railway 官方文档确认当前行为,而非假设。
  • 因“Railway 反正会重启崩溃的部署”而跳过崩溃恢复。 Railway 自己的重启策略在容器级别运行;容器仍在运行但其内部的机器人子进程崩溃是 StayPresent 直接处理的另一种失败模式。

常见问题

Railway 是否需要 Dockerfile?
不需要——Railway 可以通过 Nixpacks 自动检测并构建 Python 项目,无需 Dockerfile;当然,如果你希望显式控制,也支持 Dockerfile。

能否复用 Render 部署中的同一个 main.py
可以——因为两个平台都遵循相同的 $PORT 约定,相同的入口点通常无需修改即可在两者上运行。

在 Railway 上是否需要 staypresent.cron()
仅当你的具体方案/配置受不活动休眠影响时才需要——在决定前请查阅 Railway 当前的方案文档。

结论

一个铁路 Python 机器人保持在线的方式与在任何现代 PaaS 上运行机器人相同:绑定到分配的端口、暴露专用的健康端点,并让 StayPresent 监督机器人进程本身。该设置在 Railway、Render、Koyeb 和 Heroku 之间几乎完全相同,这正是 StayPresent 成为一次投入而非各平台样板代码的原因。

pip install staypresent[prod]

Enter fullscreen mode Exit fullscreen mode