天津网站推广:golang实现并发爬虫三(用行列调剂器实现)

admin 3个月前 (08-05) 科技 77 3

欲看此文,必先可先看:

golang实现并发爬虫一(单任务版本爬虫功效)

gollang实现并发爬虫二(简朴调剂器)

 

上文中的用简朴的调剂器实现了并发爬虫。

而且,也提到了这种并发爬虫的实现可以提高爬取效率。

当workerCount为1和workerCount为10时其爬取效率是有显著差别的。

然而,文末实在也提到了这个简朴调剂器实现的爬虫有个不可控或者说是控制力太小了的问题

究其原因就是由于我们实现的方式是来一个request就给建立一个groutine。

为了让这个程序变得更为可控。得想想怎么可以优化下了。

 

现在,异常显著,优化点就是我不想要来一个request就建立一个这个实现历程。

那么,我们可以想到行列。

把request放到request行列里。

那么,request行列里一定是会有一个request的头的,我们就可以把这个request的头元素给到worker去做实现。

也就是这样:

 

 

 but,这样是没有对worker举行一个控制的。

我们希望request可以选择我们想要的一个worker。

那么,我们也可以让scheduler维护一个worker的行列。

 

 这里用了三个并行的模块:

1.engine 引擎模块。

2.scheduler 调剂器模块。

3.worker 事情模块。

这三者通讯都是通过channel来通讯的。

 

上图中可知道调剂器模块实际上是维护了2个channel,一个是request的channel,一个是worker的channel。

//行列调剂器
//这个scheduler与engine和worker之间的通讯都是通过channel来毗邻的。
//故尔它的肚子里应该有request相关的channel和worker相关的channel.
//另外注重这里worker的channel的类型是chan Request。
type QueuedScheduler struct {
    requestChan chan con_engine.Request
    workerChan  chan chan con_engine.Request
}

那么,我们就只需要在这个scheduler调剂器的两个channel里,各取一个元素,即取request和worker(chan con_engine.Request),把request发给worker就可以了。

一直不停的去取和发送,这就是这个行列调剂器要做的事情了。

谁人弯曲的箭头也就是指的这个事情了。在request的行列里找到合适的request发给worker行列里合适的worker就好。

这就是一个整体的思想了。

 

稍微说下关于维护若何两个行列的代码。

重点在于怎么才气做到各读取一个元素。

channel的读取是会壅闭的。

若是我先读取request,若是读取不到,那么在守候的时刻就没有办法取到worker了。

解决方案就是用select,由于select会保证一点,select里的每一个case都市被执行到且会很快速的执行。

func (s *QueuedScheduler) Run() {
    s.requestChan = make(chan con_engine.Request) //指针接收者才气改变内里的内容。
    s.workerChan = make(chan chan con_engine.Request)
    go func() {
        var requestQ []con_engine.Request
        var workerQ []chan con_engine.Request
        for {
            var activeRequest con_engine.Request
            var activeWorker chan con_engine.Request
            if len(requestQ) > 0 && len(workerQ) > 0 {
                activeRequest = requestQ[0]
                activeWorker = workerQ[0]
            }
            //收到一个request就让request排队,收到一个worker就让worker排队。所有的channel操作都放到select里。
            select {
            case r := <-s.requestChan:
                requestQ = append(requestQ, r)
            case w := <-s.workerChan:
                workerQ = append(workerQ, w)
            case activeWorker <- activeRequest:
                requestQ = requestQ[1:]
                workerQ = workerQ[1:]
            }
        }
    }()
}

select就是在做三件事情:

1.从requestChan里收一个request,将这个request存在变量requestQ里。

2.从workerChan里收一个worker,将这个worker存在变量workerQ里。

3.把第一个requestQ里的第一个元素发给第一个workerQ里的第一个元素。  

 

其他代码就感兴趣的同砚自己看吧。

作者就先说到这里。

总体调剂的思想上面的图中。

详细的实现在源码里。

迎接人人留言指教。

 

源码:

https://github.com/anmutu/du_crawler/tree/master/04crawler

 

,

申博Sunbet

申博Sunbet www.jrd18.com-金融岛-致力于传播金融财经及内容变现!

欧博开户声明:该文看法仅代表作者自己,与本平台无关。转载请注明:天津网站推广:golang实现并发爬虫三(用行列调剂器实现)

网友评论

  • (*)

最新评论

  • 申傅会员网 2020-05-10 00:33:19 回复

    Sunbet:www.sunbet.xyz是Sunbet指定的Sunbet官网,Sunbet提供Sunbet(Sunbet)、Sunbet、申博代理合作等业务。我只是路过而已~

    1
    • AllbetGmaing官网 2020-05-17 05:12:45 回复

      @申傅会员网 皇冠APP是一个开放皇冠代理APP下载、皇冠会员APP下载、皇冠线路APP下载、皇冠登录APP下载的平台,皇冠体育APP上最新登录线路、新2皇冠网址更新最快,皇冠体育APP开放皇冠会员注册、皇冠代理开户等业务。这个,很值

  • 欧博APP下载 2020-08-05 00:04:32 回复

    欧博亚洲欢迎进入欧博亚洲(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。不会这样吧

    2

站点信息

  • 文章总数:474
  • 页面总数:0
  • 分类总数:8
  • 标签总数:850
  • 评论总数:143
  • 浏览总数:3464