用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") }