使用对冲模式降低长尾请求

使用对冲模式降低长尾请求 Google的论文《The Tail At Scale》提出了一种解决微服务长尾效应的方法:对冲请求模式, 通过将同一个请求发送到不同的节点,降低一个返回的作为有效请求,并且将其他请求抛弃

 

对冲请求模式出现在论文The Tail At Scale中,是Google 解决微服务长尾效应的一个办法.也是gRPC中两种重试模式之一。
source: https://grpc.io/img/basic_hedge.svg
对冲请求客户端将同一个请求发送到不同的节点,一旦收到第一个结果,客户端就会取消剩余的未处理请求。
这种模式主要作用是为了实现可以预测的延迟。假设我们的服务的一个调用链路是20个节点,每个节点的P99是1s,从概率上讲,一定有 18.2% 的请求时间大于1s。

通过对冲模式,我们每次都是从最快的节点那里得到结果,所以不会存在不可预测的长尾延迟(服务故障不在考虑范围之内) 。
在Golang中,我们可以使用context很方便的实现对冲请求,比如在下面的例子中:对于同一个后端服务,我们发起五次请求,只取最先返回的那次。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func hedgedRequest() string {
	ch := make(chan string) // chan used to abort other requests
	ctx, cancel := context.WithCancel(context.Background())

	for i := 0; i < 5; i++ {
		go func(ctx *context.Context, ch chan string, i int) {
			log.Println("in goroutine: ", i)
			if request(ctx, "http://localhost:8090", i) {
				ch <- fmt.Sprintf("finsh [from %v]", i)
				log.Println("completed goroutine: ", i)
			}
		}(&ctx, ch, i)
	}

	select {
	case s := <-ch:
		cancel()
		log.Println("cancelled all inflight requests")
		return s
	case <-time.After(5 * time.Second):
		cancel()
		return "all requests timeout after 5 secs"
	}
}

完整的代码 请访问:https://go.dev/play/p/fY9Lj_M7ZYE
这样做的好处就是,我们可以规避服务的长尾延迟,使服务的之间的延迟控制在可控的范围内。不过直接这么实现会造成额外的多倍负载。需要仔细设计。

为什么会出现长尾延迟?

出现长尾延迟的原因有很多,比如

  1. 现在混合部署已经成为主流,意味着一台物理机上有很多人跟你抢夺关键资源,所以可能会因为关键资源调度,导致长尾效应
  2. GC,这个不需要过多解释,Golang的 STW会放大长尾延迟
  3. 排队, 包括 消息队列、 网络等。
  4. ….

有什么办法可以避免对冲请求模式造成的 请求放大嘛?Go High-Performance Programming EP7: Use singleflight To Merge The Same Request 中详细介绍了如何使用 SingleFlight 来合并相同的请求。这个场景下面,使用SingleFlight 能够一定程度的缓解重复请求。

还有一种做法是只发送一个请求, 到P95的时候,如果还没有收到返回,那么就立即向第二个节点发送请求。这样做的好处就是将重复请求缩小到5%。并且大大缩短了长尾请求。

在这篇论文中,还有一些方法可以用来解决,长尾请求

  1. 服务分级 && 优先级队列(Differentiating service classes and
    higher-level queuing)
    。差异化服务类别可以用来优先调度用户正在等待的请求,而不是非交互式请求。保持低级队列较短,以便更高级别的策略更快生效。
  2. 减少队头阻塞 ,将耗费时间比较多的请求,转换成比较小的请求。Web性能优化的时候有时候也会使用这种方式。
  3. 微分区(Micro-partition) 以细粒度来调整负载便可以尽量降低负载不均导致的延迟影响。
  4. 对于性能比较差的机器,采用熔断。
  5. ……

你还有其他处理长尾请求的好方法吗?

  • 本文长期连接
  • 如果您觉得我的博客对你有帮助,请通过 RSS订阅我。
  • 或者在X上关注我。
  • 如果您有Medium账号,能给我个关注嘛?我的文章第一时间都会发布在Medium。
Licensed under CC BY-NC-SA 4.0
最后更新于 Jan 16, 2025 14:44 CST
使用 Hugo 构建
主题 StackJimmy 设计