用go写爬虫服务并发请求,限制并发数

java写爬虫服务,思路是线程池,任务队列,限制并行线程数即可。

go要用另一种设计思路,不能在线程层面限制,协程的异步请求,如果不作处理,并行发出所有网络请求,因网络请求数过多,会抛出异常

低版本的go可以并行执行map的操作,高版本会报异常,需要把map改为array,改起来很简单

func updateAllShowTimePeople() {
    //得到要请求的url,多批次请求
    allurls := getShowTimeTypeIndexFromDB()
    //要请求的任务总数
    allurlscount := len(allurls)
    //每批次并行请求的数量(这里就是指同时request的数量,根据网络和机型设置)
    gourp_url_count := 20
    //计算出一共需要执行几组,注意边界处理,例 21个url 每组5条,则要分5组(最后一组只有1条)
    group_count := allurlscount / gourp_url_count 
    //余数
    remainder := allurlscount % gourp_url_count
    if remainder != 0 {
    //有余数则多算一组
            group_count++ //6
    } else if group_count == 1 {
    //正好一组
            remainder = gourp_url_count
    }
    //组内 任务channel array
    chs := make([]chan bool, gourp_url_count)
    //遍历每组 这里是串行的
    for i := 0; i < group_count; i++ {
        //用来保存每批次的结果
        pimap := make(map[int]int)
        //遍历该批次内的任务,请求url
        for j := 0; j < gourp_url_count; j++ {
            chs[j] = make(chan bool)
            //不是最后一组则请求组内所有url || 是最后一组,序号小于余数的请求该url,序号大于余数的,无实际意义,直接 ch <- true。
            if (i != (group_count - 1)) || j < remainder {
                go getSingleShowTimeCurrentPeople(pimap, allurls[gourp_url_count * i + j], chs[j])
            } else {
                go function(){
                   ch <- true
                }
            }
        }
        //阻塞在这里,直到该批次内所有url都请求完毕。
        for _, ch := range chs {
            <-ch
        }
        //pimap 内保存改批次内所有url的请求结果,可以作进一步的处理,例,解析并存入数据库。
        //在高级的go版本里会报并发错误,可以改用数组保存结果 getSingleShowTimeCurrentPeople(pimap, allurls[gourp_url_count * i + j], chs[j]) 中j 可用作数组索引
        UpdateShowTimeSaledByShowIndex(pimap)
    }
    fmt.Println("all show time  update finished")
}
原文地址:https://www.cnblogs.com/zihunqingxin/p/6420562.html