// Judge定时任务, 将 Judge发送缓存中的数据 通过rpc连接池 发送到Judge func forward2JudgeTask(Q *list.SafeListLimited, node string, concurrent int) { batch := g.Config().Judge.Batch // 一次发送,最多batch条数据 addr := g.Config().Judge.Cluster[node] sema := nsema.NewSemaphore(concurrent) for { items := Q.PopBackBy(batch) count := len(items) if count == 0 { time.Sleep(DefaultSendTaskSleepInterval) continue } judgeItems := make([]*cmodel.JudgeItem, count) for i := 0; i < count; i++ { judgeItems[i] = items[i].(*cmodel.JudgeItem) } // 同步Call + 有限并发 进行发送 sema.Acquire() go func(addr string, judgeItems []*cmodel.JudgeItem, count int) { defer sema.Release() resp := &cmodel.SimpleRpcResponse{} var err error sendOk := false for i := 0; i < 3; i++ { //最多重试3次 err = JudgeConnPools.Call(addr, "Judge.Send", judgeItems, resp) if err == nil { sendOk = true break } time.Sleep(time.Millisecond * 10) } // statistics if !sendOk { log.Printf("send judge %s:%s fail: %v", node, addr, err) proc.SendToJudgeFailCnt.IncrBy(int64(count)) } else { proc.SendToJudgeCnt.IncrBy(int64(count)) } }(addr, judgeItems, count) } }
// Graph定时任务, 进行数据迁移时的 数据冗余发送 func forward2GraphMigratingTask(Q *list.SafeListLimited, node string, addr string, concurrent int) { batch := g.Config().Graph.Batch // 一次发送,最多batch条数据 sema := nsema.NewSemaphore(concurrent) for { items := Q.PopBackBy(batch) count := len(items) if count == 0 { time.Sleep(DefaultSendTaskSleepInterval) continue } graphItems := make([]*cmodel.GraphItem, count) for i := 0; i < count; i++ { graphItems[i] = items[i].(*cmodel.GraphItem) } sema.Acquire() go func(addr string, graphItems []*cmodel.GraphItem, count int) { defer sema.Release() resp := &cmodel.SimpleRpcResponse{} var err error sendOk := false for i := 0; i < 3; i++ { //最多重试3次 err = GraphMigratingConnPools.Call(addr, "Graph.Send", graphItems, resp) if err == nil { sendOk = true break } time.Sleep(time.Millisecond * 10) //发送失败了,睡10ms } // statistics if !sendOk { log.Printf("send to graph migrating %s:%s fail: %v", node, addr, err) proc.SendToGraphMigratingFailCnt.IncrBy(int64(count)) } else { proc.SendToGraphMigratingCnt.IncrBy(int64(count)) } }(addr, graphItems, count) } }
// Tsdb定时任务, 将 Tsdb发送缓存中的数据 通过api连接池 发送到Tsdb // 单个Cluster配置多个influxdb地址,修改为并发发送。 func forward2InfluxdbTask(Q *list.SafeListLimited, node string, concurrent int) { cfg := g.Config() batch := cfg.Influxdb.Batch // 一次发送,最多batch条数据 sema := nsema.NewSemaphore(concurrent * len(cfg.Influxdb.Cluster2[node].Addrs)) retry := cfg.Influxdb.MaxRetry for { items := Q.PopBackBy(batch) count := len(items) if count == 0 { time.Sleep(DefaultSendTaskSleepInterval) continue } pts := make([]*client.Point, count) for i := 0; i < count; i++ { pts[i] = items[i].(*client.Point) } for _, addr := range cfg.Influxdb.Cluster2[node].Addrs { sema.Acquire() go coreSend2Influxdb(addr, sema, retry, pts) } } }
func forward2TransferTask(Q *nlist.SafeListLimited, concurrent int32) { cfg := g.Config() batch := int(cfg.Transfer.Batch) maxConns := int64(cfg.Transfer.MaxConns) retry := int(cfg.Transfer.Retry) if retry < 1 { retry = 1 } sema := nsema.NewSemaphore(int(concurrent)) transNum := len(TransferHostnames) for { items := Q.PopBackBy(batch) count := len(items) if count == 0 { time.Sleep(time.Millisecond * 50) continue } transItems := make([]*cmodel.MetricValue, count) for i := 0; i < count; i++ { transItems[i] = convert(items[i].(*cmodel.MetaData)) } sema.Acquire() go func(transItems []*cmodel.MetricValue, count int) { defer sema.Release() var err error // 随机遍历transfer列表,直到数据发送成功 或者 遍历完;随机遍历,可以缓解慢transfer resp := &g.TransferResp{} sendOk := false for j := 0; j < retry && !sendOk; j++ { rint := rand.Int() for i := 0; i < transNum && !sendOk; i++ { idx := (i + rint) % transNum host := TransferHostnames[idx] addr := TransferMap[host] // 过滤掉建连缓慢的host, 否则会严重影响发送速率 cc := pfc.GetCounterCount(host) if cc >= maxConns { continue } pfc.Counter(host, 1) err = SenderConnPools.Call(addr, "Transfer.Update", transItems, resp) pfc.Counter(host, -1) if err == nil { sendOk = true // statistics TransferSendCnt[host].IncrBy(int64(count)) } else { // statistics TransferSendFailCnt[host].IncrBy(int64(count)) } } } // statistics if !sendOk { if cfg.Debug { log.Printf("send to transfer fail, connpool:%v", SenderConnPools.Proc()) } pfc.Meter("SendFail", int64(count)) } else { pfc.Meter("Send", int64(count)) } }(transItems, count) } }