记一次线上API调用失败的排查过程:从405到时间同步

最近在开发一个代码审查工具时,遇到了一个有意思的问题。本地测试一切正常,但调用线上API时却一直 失败。整个排查过程挺有意思的,记录下来分享给大家。

背景

我们团队开发了一个内部的代码审查系统,前端使用React,后端是Node.js + Koa框架。最近在开发一个CLI工具,需要调用后端API上传代码审查报告。

问题现象

本地开发时,CLI工具调用本地服务一切正常: POST http://localhost:34789/document/createCodeReviewDocument 返回 200 OK

但调用线上服务时,却返回了405错误: POST gw.example.com/document/cr... 返回 405 Method Not Allowed

排查过程

第一阶段:路由问题

首先怀疑是路由配置问题。查看后端代码发现,我们的路由分为公有路由和私有路由:

  • 公有路由:/public/* (登录等接口)
  • 私有路由:直接挂载,无前缀

但通过浏览器开发者工具发现,线上其他接口都是通过 /api/* 访问的。原来是Nginx做了路由转发:

bash 复制代码
location /api/ {
    proxy_pass http://backend/;
}

第一个坑:线上需要加 /api 前缀,而本地不需要。

第二阶段:认证问题

修复URL后,405错误解决了,但又出现了新问题:

bash 复制代码
{
  "success": false,
  "errorCode": 40403,
  "errorMsg": "{\"code\":9999}"
}

9999是我们系统的默认错误码,说明出现了未知异常。为了定位问题,我临时修改了错误处理代码,让它 返回详细错误信息:

bash 复制代码
} catch (error) {
  // 临时添加详细错误信息
  throw new CodedError(error.message || '系统错误')
}

第三阶段:数据库连接?

重新部署后,发现本地连接生产环境会报数据库连接超时。这很正常,因为阿里云RDS有IP白名单限制。

但奇怪的是,其他接口(如 getProjectList)能正常返回数据,说明线上服务是能访问数据库的。那问题出在哪里?

第四阶段:真相大白

最后实在没办法,只能登录服务器查看日志。PM2的日志暴露了真正的问题:

bash 复制代码
RequestTimeTooSkewedError: The difference between the request time and the current time is too large.

原来是服务器时间不同步!

阿里云OSS有个安全机制:请求时间与服务器时间差不能超过15分钟。我们的服务器时间慢了20多分钟。

解决方案

解决方法很简单,同步服务器时间:

同步时间

bash 复制代码
ntpdate ntp.aliyun.com

设置定时同步

bash 复制代码
echo "*/30 * * * * /usr/sbin/ntpdate ntp.aliyun.com" >> /var/spool/cron/root

重启服务

bash 复制代码
pm2 restart all

经验总结

  1. 不同环境的差异要重视 - 本地和线上的路由配置可能不同(Nginx转发规则) - 注意时区和时间同步问题
  2. 错误处理很重要 - 默认的错误码(如9999)掩盖了真实问题 - 开发环境可以返回详细错误,生产环境要注意信息安全
  3. 日志是排查问题的关键 - 不要只看API返回,要看服务端日志 - PM2、系统日志都可能包含关键信息
  4. OSS等云服务的特殊要求 - 时间同步是基础但容易被忽略 - 签名机制对时间很敏感
  5. 排查思路 - 从表象到本质,层层深入 - 对比正常接口和异常接口的差异 - 必要时登录服务器查看详细日志

这次问题虽然最后解决很简单,但排查过程还是学到不少东西。特别是时间同步这种基础设施问题,平时 不注意,出问题的时候还真不容易想到。


PS: 感谢团队小伙伴们的支持,特别是运维同学提供的服务器权限。

相关推荐
苏三的开发日记2 小时前
windows系统搭建kafka环境
后端
爬山算法2 小时前
Netty(19)Netty的性能优化手段有哪些?
java·后端
Tony Bai2 小时前
Cloudflare 2025 年度报告发布——Go 语言再次“屠榜”API 领域,AI 流量激增!
开发语言·人工智能·后端·golang
想用offer打牌2 小时前
虚拟内存与寻址方式解析(面试版)
java·后端·面试·系统架构
無量2 小时前
AQS抽象队列同步器原理与应用
后端
9号达人3 小时前
支付成功订单却没了?MyBatis连接池的坑我踩了
java·后端·面试
用户497357337983 小时前
【轻松掌握通信协议】C#的通信过程与协议实操 | 2024全新
后端
草莓熊Lotso3 小时前
C++11 核心精髓:类新功能、lambda与包装器实战
开发语言·c++·人工智能·经验分享·后端·nginx·asp.net
追逐时光者3 小时前
精选 8 个 .NET 开发实用的类库,效率提升利器!
后端·.net
a程序小傲4 小时前
京东Java面试被问:Fork/Join框架的使用场景
java·开发语言·后端·postgresql·面试·职场和发展