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