// 添加请求到队列,并发安全 func (self *Matrix) Push(req *request.Request) { if sdl.checkStatus(status.STOP) { return } // 禁止并发,降低请求积存量 self.Lock() defer self.Unlock() // 达到请求上限,停止该规则运行 if self.maxPage >= 0 { return } // 暂停状态时等待,降低请求积存量 waited := false for sdl.checkStatus(status.PAUSE) { waited = true runtime.Gosched() } if waited && sdl.checkStatus(status.STOP) { return } // 资源使用过多时等待,降低请求积存量 waited = false for self.resCount > sdl.avgRes() { waited = true runtime.Gosched() } if waited && sdl.checkStatus(status.STOP) { return } // 不可重复下载的req if !req.IsReloadable() { hash := makeUnique(req) // 已存在成功记录时退出 if self.hasHistory(hash) { return } // 添加到临时记录 self.insertTempHistory(hash) } var priority = req.GetPriority() // 初始化该蜘蛛下该优先级队列 if _, found := self.reqs[priority]; !found { self.priorities = append(self.priorities, priority) sort.Ints(self.priorities) // 从小到大排序 self.reqs[priority] = []*request.Request{} } // 添加请求到队列 self.reqs[priority] = append(self.reqs[priority], req) // 大致限制加入队列的请求量,并发情况下应该会比maxPage多 atomic.AddInt64(&self.maxPage, 1) }
// 返回是否作为新的失败请求被添加至队列尾部 func (self *Matrix) DoHistory(req *request.Request, ok bool) bool { hash := makeUnique(req) if !req.IsReloadable() { self.tempHistoryLock.Lock() delete(self.tempHistory, hash) self.tempHistoryLock.Unlock() if ok { self.history.UpsertSuccess(hash) return false } } if ok { return false } self.failureLock.Lock() defer self.failureLock.Unlock() if _, ok := self.failures[hash]; !ok { // 首次失败时,在任务队列末尾重新执行一次 self.failures[hash] = req logs.Log.Informational(" * + 失败请求: [%v]\n", req.GetUrl()) return true } // 失败两次后,加入历史失败记录 self.history.UpsertFailure(req) return false }