TT Lab
开始
学习 学习路径 课程

Loki — 不索引日志的日志库

400 要修,429 要等

在 TT Lab 中继续学习

一句话总结

写入一侧的拒绝有两种。400 要去修,429 要去等。把这两者用同一个代码处理的采集器,两种都会处理错。

为什么需要它

接入新服务的那天,采集器日志里涌出大量拒绝。负责人打开重试逻辑就下班了。第二天早上,拒绝依旧,而采集器的缓冲区已经满了,连别的服务的日志都被挤压了。

拒绝是 400。标签名里带有连字符,这样的行不管重发多少次,永远都会被拒绝。重试没有改善情况,只是把队列填满了。反过来,同一周里另一个服务出现的 429,重试才是正确答案,而那边却不重试,直接丢弃了。

工作原理

Loki 拒绝传入请求的原因大致有四种。

情形 代码 处理
标签名不符合语法 400 修改发送一侧
标签个数超过上限(max_label_names_per_series) 400 减少标签
行太长(max_line_size) 400 截断或拆分
超过每个流的速率(per_stream_rate_limit) 429 退避后重试

标签名的规则与 Prometheus 相同——以字母或下划线开头,只能使用字母、数字和下划线。连字符不行,也不能以数字开头。想把 Kubernetes 标签原样搬过来,常常会撞上这堵墙,所以最好事先在采集器一侧放入改名的设置。

速率限制是以流为单位的。所以即使是同一个服务,如果标签组合有多个,每个组合都会各自获得限额。反过来,如果减少标签、合并流,流量就会集中到一个流上,出现 429。降低基数和避开速率限制,朝相反的方向拉扯——不了解这种张力,就会只修一边,却把另一边弄炸。

突发(burst)又给这幅图添了一层。per_stream_rate_limit_burst 是允许瞬间超过限额的量。所以平时平静、突然爆发的流量,开头一段时间能通过,之后才会收到 429。“一开始行,突然就不行了”这个症状,真身大多就是这个。

收到 429 时,正确的客户端要具备三样——指数退避、抖动、重试上限。没有抖动,多个采集器就会以同样的节奏再次涌来,一起撞上同一堵墙。没有上限,把 400 误当成 429 时,就会永远重试下去。

在现场相遇的样子

最常见的事故,就是上面的“对 400 重试”。办法是在采集器设置里用状态码明确重试条件,把 400 一类的送进隔离队列,让人去看。

第二是过长的行。一个堆栈跟踪超过上限,那个请求就会整个被拒绝,同一批里好好的行也一起掉了。所以要在采集器里先截断,或者把批设小,缩小受影响的范围。

第三是标签个数。把 Kubernetes 元数据全部变成标签,很容易超过上限。只留下需要的五六个,其余放在正文里,拒绝没有了,流的数量也减少了。

下一项实验要做什么

在 /config 里亲手读出服务器持有的限额,做成表格,实际发送错误的标签和过长的行,收到 400 及其正文。然后启动一个设置了较低速率限额的第二个 Loki,收到真正的 429,并用数字说明为什么开头几次因为突发而通过了。最后加上退避重试,做到一行不丢、全部存下。