Jitter Before Starting

go-microregistry 缓存层针对每个服务监听注册中心事件的代码如下:

 1// run starts the cache watcher loop
 2// it creates a new watcher if there's a problem.
 3func (c *cache) run(service string) {
 4	c.Lock()
 5	c.watchedRunning[service] = true
 6	c.Unlock()
 7	// reset watcher on exit
 8	defer func() {
 9		c.Lock()
10		c.watched = make(map[string]bool)
11		c.watchedRunning[service] = false
12		c.Unlock()
13	}()
14
15	var a, b int
16
17	for {
18		// exit early if already dead
19		if c.quit() {
20			return
21		}
22
23		// jitter before starting
24		j := rand.Int63n(100)
25		time.Sleep(time.Duration(j) * time.Millisecond)
26
27		// create new watcher
28		w, err := c.Registry.Watch(registry.WatchService(service))
29		if err != nil {
30			if c.quit() {
31				return
32			}
33
34			d := backoff(a)
35			c.setStatus(err)
36
37			if a > 3 {
38				a = 0
39			}
40
41			time.Sleep(d)
42			a++
43
44			continue
45		}
46
47		// reset a
48		a = 0
49
50		// watch for events
51		if err := c.watch(w); err != nil {
52			if c.quit() {
53				return
54			}
55
56			d := backoff(b)
57			c.setStatus(err)
58
59			if b > 3 {
60				b = 0
61			}
62
63			time.Sleep(d)
64			b++
65
66			continue
67		}
68
69		// reset b
70		b = 0
71	}
72}

在分布式系统或并发编程中,“jitter before starting”的作用是通过引入随机延迟来避免多个客户端或协程同时执行操作,从而减少资源竞争、服务端压力或“惊群效应”(thundering herd problem)

具体分析这段代码中的作用:

  1. 分散请求峰值

    • 当多个客户端/协程尝试同时启动监视器(如服务注册中心的Watch操作)时,可能导致服务端瞬间负载激增。
    • rand.Int63n(100)生成0-99毫秒的随机延迟,使得不同客户端/协程的启动时间分散,避免同时发起大量请求。
  2. 避免连续的同步重试

    • 在错误恢复场景中(如c.Registry.Watch失败后的重试),如果所有失败的客户端立即重试,可能形成同步的重试浪潮。
    • 随机延迟破坏了这种同步性,使重试时间点随机化,提高服务端恢复的可能性。
  3. 配合指数退避(backoff)

    • 代码中的backoff(a)backoff(b)是逐渐增加等待时间的退避策略(如指数退避)。
    • jitter与退避策略结合,既避免短时间内的密集重试(退避),又防止多个客户端退避后同时唤醒(jitter)。
  4. 提高鲁棒性

    • 在网络不稳定的场景中,随机延迟可以降低因短暂故障(如网络抖动)导致多个客户端同时重建连接而加剧问题的风险。

类比现实场景:

假设某个服务注册中心(如Consul或Etcd)短暂宕机,所有依赖它的客户端都会尝试重建Watch连接。如果没有jitter:

  • 所有客户端可能严格按照固定间隔(如0ms, 100ms, 200ms...)重试,导致服务端恢复后瞬间被再次压垮。
  • 加入jitter后,客户端的重试时间会在退避基础上叠加随机偏移(如12ms, 87ms, 45ms...),分散请求压力,提高整体恢复成功率。

总结:

此处的jitter是一种轻量级的容错机制,通过随机化操作的时间分布,优化系统在高并发或故障场景下的行为,避免自发性同步引发的雪崩效应。