Heroku部署gqlgen Golang服务报Unexpected token <及503错误
gqlgen部署Heroku后Playground查询报503、JSON解析错误排查方案
问题现象
- 基于Golang GraphQL框架gqlgen开发的服务部署到Heroku平台后,可正常访问GraphQL Playground页面
- 在Playground中发起查询请求时返回错误:
{"errors": {"message": "Unexpected token < in JSON at position 0","stack": "SyntaxError: Unexpected token < in JSON at position 0"}} - 通过浏览器开发者工具查看请求响应,接口返回
503 Service Unavailable状态码
核心判断
那个JSON解析错误不是业务层返回的报错,本质是接口返回了HTML格式的Heroku平台错误页,页面以<!DOCTYPE html>开头,首字符就是<,Playground默认按JSON格式解析响应就会抛出这个语法错误,核心要解决的是503服务不可用的问题。
排查步骤与修复方案
1. 修正端口绑定逻辑
Heroku不会使用代码里硬编码的固定端口,会通过PORT环境变量动态分配服务监听端口,硬编码端口会导致平台健康检查失败,请求无法路由到服务进程。
- 调整服务启动时的监听逻辑,优先读取环境变量中的端口,参考代码:
port := os.Getenv("PORT") if port == "" { port = "8080" // 本地开发 fallback 端口 } if err := http.ListenAndServe(":"+port, nil); err != nil { log.Fatalf("服务启动失败: %v", err) }
2. 检查Procfile配置
项目根目录必须存在无后缀名的Procfile文件,用来告诉Heroku如何启动web进程,配置错误会直接导致进程启动失败。
- 正确配置参考(根据自己的项目启动命令调整):
- 若部署预编译的二进制文件:
web: ./your_binary_name - 若测试阶段直接用源码启动:
web: go run main.go
- 若部署预编译的二进制文件:
- 注意确认配置里的启动入口、二进制文件名和实际项目一致,不要写错路径。
3. 校验GraphQL路由注册逻辑
能打开Playground不代表GraphQL接口路由注册正确,gqlgen的Playground是静态页面,如果只注册了根路径的GET方法返回Playground,没有给查询路径的POST方法绑定GraphQL处理逻辑,POST请求就会落到平台默认错误页返回503。
- 检查路由注册代码,确保查询路径的POST请求正确绑定到GraphQL服务处理,参考配置:
// 初始化gqlgen服务 srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{ Resolvers: &graph.Resolver{}, })) // 注册Playground路由,第二个参数是GraphQL实际查询路径 http.Handle("/", playground.Handler("GraphQL Playground", "/query")) // 必须注册查询路径的处理,覆盖POST等请求方法 http.Handle("/query", srv)
4. 排查启动阶段的依赖异常
如果服务启动时需要连接数据库、缓存等第三方依赖,连接失败导致进程直接退出的话,Heroku检测不到存活的web进程就会返回503。
- 本地执行
heroku local模拟线上环境启动,查看启动日志有没有缺环境变量、数据库连接失败、配置错误的问题 - 线上执行
heroku logs --tail拉取实时运行日志,排查有没有进程崩溃、panic、连接超时的报错:如果项目用到数据库,不要写死本地连接地址,要读取平台对应的环境变量(比如Heroku Postgres的DATABASE_URL),确认对应插件已经正常开通配置。
内容的提问来源于stack exchange,提问作者creator life
相关产品推荐
相关产品推荐

