七叶笔记 » golang编程 » Go语言学习基础-工人池、等待组、速率限制

Go语言学习基础-工人池、等待组、速率限制

Worker Pool工人池

下面的例子使用协程和通道实现工人池,程序同时运行了几个工人实例。这些工人从通道jobs中获取工作,并发送结果到通道results。每个工人函数休眠一秒钟来模拟一项耗时的任务。

使用工人池时,需要向工人发送工作并收集他们的结果,为此创建了2个通道。启动3个工人协程,开始时由于还没有作业而被阻塞。向通道jobs中发送5个作业任务,然后关闭该通道,以表明这是所有的工作。最后,收集所有的工作结果,这也确保了工人协程能正常结束。等待多个协程的另一种方法是使用WaitGroup。尽管总共有大约5秒钟的工作,因为有3个协程同时执行,因此这个程序只用了大约2秒钟。

结果:

$ time go run worker-pools.go

worker 1 started job 1

worker 2 started job 2

worker 3 started job 3

worker 1 finished job 1

worker 1 started job 4

worker 2 finished job 2

worker 2 started job 5

worker 3 finished job 3

worker 1 finished job 4

worker 2 finished job 5

real 0m2.358s

WaitGroup等待组

要等待多个协程完成,可以使用等待组。注意,等待组必须通过指针传递给函数。

等待组用于等待所有启动的协程完成工作。当启动一个协程时递增一次等待组的计数器。主函数调用等待组的Wait方法阻塞,直到等待组计数器返回0后再继续往下执行;在协程中return返回函数时,需要先调用等待组的Done方法减少等待组的计数器,表示本协程结束执行,所有的协程都要通知他们已经完成了。每个协程的启动和完成的顺序可能不同。

结果:

$ go run waitgroups.go

Worker 5 starting

Worker 3 starting

Worker 4 starting

Worker 1 starting

Worker 2 starting

Worker 4 done

Worker 1 done

Worker 2 done

Worker 5 done

Worker 3 done

Rate Limiting速率限制

速率限制是控制资源利用、维护服务质量的重要机制。Go通过协程、通道和计时器优雅实现速率限制。

首先,是常规速率限制。假设要限制对传入请求的处理。创建请求通道requests,创建计时器time.Tick,每隔200毫秒触发一次,以此限制从通道接收值的速率,因此把速率限制方案中使用的计时器通道叫作速率调节器。在处理每个请求服务之前,通过阻塞限制器信道的接收,从而限制了请求的处理速率。

有时,可能希望在速率限制方案中允许突发请求,但同时又保留整个速率限制,可以通过带缓冲的速率限制器通道来实现突发速率限制。通道burstyLimiter将允许最多3个事件的突发,常规情况下每隔200毫秒,向通道添加一个新值。现在再模拟5个传入请求,其中前3个将受益于burstyLimiter的突发能力。运行程序,看到第一批请求按需要每200毫秒被处理一次。对于第二批请求,由于burstable速率限制,会立即服务前3个,然后服务其余2个,每个延迟约200毫秒。

结果:

$ go run rate-limiting.go

request 1 2012-10-19 00:38:18.687438 +0000 UTC

request 2 2012-10-19 00:38:18.887471 +0000 UTC

request 3 2012-10-19 00:38:19.087238 +0000 UTC

request 4 2012-10-19 00:38:19.287338 +0000 UTC

request 5 2012-10-19 00:38:19.487331 +0000 UTC

request 1 2012-10-19 00:38:20.487578 +0000 UTC

request 2 2012-10-19 00:38:20.487645 +0000 UTC

request 3 2012-10-19 00:38:20.487676 +0000 UTC

request 4 2012-10-19 00:38:20.687483 +0000 UTC

request 5 2012-10-19 00:38:20.887542 +0000 UTC

相关文章