线上系统最常见的问题之一就是“接口变慢”。用户反馈页面加载慢,运营反馈后台卡顿,开发查看服务器却发现 CPU 并不高。这类问题如果只靠登录服务器 grep 日志,效率会很低。
尤其当业务部署在多台 CVM 或容器实例上时,日志分散在不同机器中,排查过程会更加复杂。更好的方式是将应用日志统一采集到日志服务中,基于关键词、字段和时间范围进行检索分析。
本文以一个 Web API 服务为例,介绍如何通过结构化日志和云上日志分析定位慢请求问题。
很多系统早期日志类似这样:
request finished这类日志对排查问题帮助有限。更推荐输出结构化日志,例如 JSON 格式:
{
"time": "2026-05-13T10:30:00+08:00",
"level": "info",
"trace_id": "abc123",
"method": "GET",
"path": "/api/orders",
"status": 200,
"cost_ms": 356,
"user_id": "10001",
"client_ip": "1.2.3.4"
}结构化日志的好处是字段清晰,可以直接按接口路径、状态码、耗时、用户 ID 和 trace_id 查询。
对于慢请求分析,至少建议记录以下字段:
请求时间; 请求方法; 请求路径; HTTP 状态码; 接口耗时; trace_id; 用户 ID 或租户 ID; 错误信息。
以 Express 应用为例,可以通过中间件记录每次请求耗时:
app.use((req, res, next) => {
const start = Date.now();
const traceId = req.headers['x-trace-id'] || crypto.randomUUID();
res.on('finish', () => {
const costMs = Date.now() - start;
console.log(JSON.stringify({
time: new Date().toISOString(),
level: 'info',
trace_id: traceId,
method: req.method,
path: req.path,
status: res.statusCode,
cost_ms: costMs,
client_ip: req.ip
}));
});
next();
});如果是 Java Spring Boot,可以通过 Filter 或 Interceptor 实现类似能力。
关键点是:日志必须稳定、字段命名统一,并且尽量避免输出无意义文本。否则后续检索和统计会非常困难。
在腾讯云环境中,可以通过日志采集组件将 CVM 或容器中的日志文件采集到日志服务。常见做法是:
应用将日志写入固定文件,例如:
/var/log/demo-app/access.log
/var/log/demo-app/error.log日志采集器监听这些文件,并将新增日志上传到日志主题中。
建议按环境和业务拆分日志主题,例如:
prod-api-access
prod-api-error
test-api-access生产环境和测试环境不要混在一起,否则查询时容易误判。
当用户反馈“订单页面很慢”时,可以先查询订单相关接口:
path="/api/orders"然后筛选耗时大于 1000ms 的请求:
path="/api/orders" AND cost_ms > 1000接着可以按接口路径统计平均耗时和 P95 耗时。通常平均值不能完全反映问题,因为少量极慢请求可能被平均掉。P95、P99 更适合观察用户实际体验。
如果发现 /api/orders 的 P95 明显升高,可以继续按状态码、用户 ID、机器 IP 等维度拆分:
path="/api/orders" AND cost_ms > 1000 AND status=200如果慢请求状态码是 200,说明接口没有报错,但处理过程慢。 如果慢请求集中在 500,说明可能是异常重试、依赖服务报错或数据库错误。 如果慢请求只集中在某一台机器,可能是单机负载、磁盘 I/O 或网络问题。
单条接口日志只能说明入口耗时,但无法直接说明慢在哪里。因此建议在系统中引入 trace_id。
一次请求进入网关或后端服务时生成 trace_id,然后在后续数据库访问、缓存访问、第三方 API 调用日志中都带上同一个 trace_id。
例如:
{
"trace_id": "abc123",
"event": "mysql_query",
"sql": "select * from orders where user_id=?",
"cost_ms": 820
}当发现某个请求耗时 1200ms 时,可以用 trace_id 查询完整链路:
trace_id="abc123"如果结果显示 MySQL 查询耗时 820ms,就可以初步判断瓶颈在数据库查询。接下来再结合慢 SQL 日志和索引情况分析。
接口慢通常来自以下几类问题:
第一,数据库查询慢。常见原因是缺少索引、扫描数据量过大、SQL 写法不合理。
第二,外部接口慢。例如支付、短信、地图、风控等第三方服务响应时间不稳定。
第三,缓存未命中。大量请求穿透到数据库,导致数据库压力升高。
第四,单机资源问题。某台机器 CPU、内存、磁盘 I/O 或网络异常。
第五,锁竞争。高并发下多个请求竞争同一资源,例如库存扣减、订单状态更新。
第六,日志过多。同步写大量日志也可能拖慢接口响应。
定位问题后,可以按瓶颈类型采取不同优化方式。
如果是数据库慢查询,可以补充索引、优化 SQL、分页查询、减少不必要字段返回。 如果是外部接口慢,可以增加超时控制、异步化、重试限流和降级策略。 如果是缓存问题,可以增加热点缓存、预热缓存,并防止缓存击穿。 如果是单机问题,可以扩容实例,或检查是否存在异常进程。 如果是锁竞争,需要重新设计并发控制方式,减少锁粒度。
例如数据库查询优化前:
SELECT * FROM orders WHERE user_id = 10001 ORDER BY created_at DESC;如果没有合适索引,数据量大时会很慢。可以增加联合索引:
CREATE INDEX idx_user_created ON orders(user_id, created_at);同时避免 SELECT *,只查询页面需要的字段。
慢请求不应该只靠用户反馈发现。可以配置日志告警,例如:
5 分钟内 cost_ms > 1000 的请求数超过阈值;
某接口 P95 超过 800ms;
HTTP 500 错误数持续升高;
某关键词错误日志数量异常增加。
这样系统出现性能问题时,研发可以更早发现并处理。
日志分析不是简单地“把日志存起来”,而是要让日志具备可检索、可统计、可关联的能力。结构化日志、统一字段、trace_id 和日志告警,是排查线上问题的基础设施。
对于云上业务来说,使用日志服务集中管理 CVM、容器和应用日志,可以显著提高问题定位效率。无论是接口慢、错误率升高,还是某个用户请求异常,都可以通过日志快速缩小范围,找到真正的瓶颈。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。