Golang在GAE平台上开发的Telegram机器人运行一段时间后停止服务的问题
Golang在GAE平台上开发的Telegram机器人运行一段时间后停止服务的问题 Telegram 机器人在运行一段时间后停止工作。
我将一个简单的 Telegram 机器人上传到 Google 应用引擎。上传后它能正常工作一段时间,但之后就会停止响应 Telegram 的请求。这个机器人非常简单,使用了 github.com/go-telegram-bot-api/telegram-bot-api 包。
func main() {
bot, err := tba.NewBotAPI("apitockenhere")
var ucfg tba.UpdateConfig = tba.NewUpdate(0)
ucfg.Timeout = 60
uchan, err := bot.GetUpdatesChan(ucfg)
if err != nil {
log.Println(err)
}
...
for {
select {
case update := <-uchan:
...
}
}
}
如果我在浏览器中打开这个网络应用(它不包含任何处理程序,所以不会显示任何内容),Telegram 机器人会重新开始工作一段时间,然后再次停止。
在本地环境中它能正常工作,但在 GAE 上可能存在一些问题。 如何修改代码来防止它停止运行?
我注意到如果关闭浏览器,过一段时间后 Telegram 机器人也会停止工作。
更多关于Golang在GAE平台上开发的Telegram机器人运行一段时间后停止服务的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
也许,请求无法通过防火墙。
更多关于Golang在GAE平台上开发的Telegram机器人运行一段时间后停止服务的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
好的,如果你已经得到答案,请随时"标记为已解决"。我会选择选项3,因为搭建一个小型机器人要容易得多。
husonet:
也许,请求无法通过防火墙
我怀疑是防火墙的问题。发帖人特别提到,通过浏览器访问机器人以及上传后,机器人都能正常工作。
我确实期望GAE有某种机制来防止机器人行为,就像Heroku一样。
hollowaykeanho:
当通过浏览器访问机器人并上传后,机器人运行正常
确实如此
在GAE上运行Telegram机器人时遇到服务停止的问题,通常是由于GAE的实例管理机制导致的。GAE会自动停止闲置实例以节省资源,而你的长轮询连接在实例被挂起时会中断。
以下是解决方案和修改后的代码:
问题分析
- GAE实例在无请求时会自动挂起
- 长轮询连接在实例挂起时被中断
- 需要保持实例活跃或使用Webhook方式
解决方案:使用Webhook替代长轮询
package main
import (
"log"
"net/http"
"os"
tba "github.com/go-telegram-bot-api/telegram-bot-api"
)
var bot *tba.BotAPI
func main() {
var err error
bot, err = tba.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
if err != nil {
log.Fatal(err)
}
// 设置Webhook
_, err = bot.SetWebhook(tba.NewWebhook("https://your-app-name.appspot.com/"+bot.Token))
if err != nil {
log.Fatal(err)
}
// 设置路由
http.HandleFunc("/", handleRoot)
http.HandleFunc("/"+bot.Token, handleWebhook)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("Server starting on port %s", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
func handleRoot(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Telegram Bot is running"))
}
func handleWebhook(w http.ResponseWriter, r *http.Request) {
update, err := bot.HandleUpdate(r)
if err != nil {
log.Printf("Error handling update: %v", err)
return
}
if update.Message != nil {
handleMessage(update.Message)
}
}
func handleMessage(message *tba.Message) {
msg := tba.NewMessage(message.Chat.ID, "Received: "+message.Text)
bot.Send(msg)
}
替代方案:保持实例活跃(如果必须使用长轮询)
package main
import (
"log"
"net/http"
"time"
tba "github.com/go-telegram-bot-api/telegram-bot-api"
)
func main() {
// 启动健康检查端点
http.HandleFunc("/_ah/health", healthCheckHandler)
go http.ListenAndServe(":8080", nil)
bot, err := tba.NewBotAPI("apitockenhere")
if err != nil {
log.Fatal(err)
}
var ucfg tba.UpdateConfig = tba.NewUpdate(0)
ucfg.Timeout = 60
uchan, err := bot.GetUpdatesChan(ucfg)
if err != nil {
log.Fatal(err)
}
// 定期发送请求保持实例活跃
go keepAlive()
for update := range uchan {
if update.Message != nil {
handleUpdate(&update)
}
}
}
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}
func keepAlive() {
ticker := time.NewTicker(5 * time.Minute)
defer ticker.Stop()
for range ticker.C {
// 发送一个简单的HTTP请求到应用自身
http.Get("https://your-app-name.appspot.com/_ah/health")
}
}
func handleUpdate(update *tba.Update) {
// 处理消息逻辑
log.Printf("Received message: %s", update.Message.Text)
}
app.yaml配置示例
runtime: go116
instance_class: F2
automatic_scaling:
max_instances: 1
min_instances: 0
Webhook方案是推荐的方法,因为它符合GAE的无状态请求-响应模型,能有效避免实例挂起导致的服务中断问题。

