一、前言
本节我们来看下如何使用通道来解决多goroutine下并发安全的,这里我们借助go官网的一个轮询url列表并发起http请求的例子来进行讲解。这个例子可以很好的说明通过通信来共享内存。
二、功能时序
如下图是本实例的概要功能时序
首先 pending 列表里面存放一些url列表
程序启动后会开启两个Poller goroutine来从pendling列表里面并发的获取url,Poller内部会对获取的url发起HTTP请求,并发响应码记录到map结构的urlStatus,其中key为url,value为状态码,如果http请求出错还会记录当前url出错次数,然后poller会把url对象传递给complete列表(存放已经调用过http的url)
complete列表里面的url对象会被顺序拿出来,每个url开启一个goroutine进行休眠(根据请求该url失败的次数休眠时间不同),休眠完毕后,在把url对象放入到pending列表。
StateMonitor模块则负责定时的打印urlStatus内容。
三、代码分析
3.1 领域对象定义
资源实体,每个url都会被封装为Resource对象
type Resource struct {
url string//url
errCount int//http请求失败次数
}
该资源实体有两个方法:
//休眠
func (r *Resource) Sleep(done chan<- *Resource)
//发起http调用
func (r *Resource) Poll() string
状态实体,用来记录请求每个url返回的状态码
type State struct {
url string//url
status string//http状态码,比如200,或者报错信息
}
常量定义
const (
numPollers = 2 // 开启多少个Poller goroutine
pollInterval = 60 * time.Second // 间隔多少时间再次轮询url列表
statusInterval = 10 * time.Second // 监控模块,间隔多少时间打印一次urlStatus内容
errTimeout = 10 * time.Second // 请求http失败后,在pollInterval基础上 间隔多少单位时间再次尝试
)
url列表