package app import ( "fmt" "gitea.anxinyun.cn/container/common_models" "gitea.anxinyun.cn/container/common_utils" "gitea.anxinyun.cn/container/common_utils/configLoad" "log" "net/rpc" "node/et_worker/et_recv" "os" "os/signal" "syscall" "time" ) type EtNode struct { nodeInfo *common_models.NodeArgs master *rpcMaster ch chan *common_models.ProcessData recvDataHandler *et_recv.RecvDataHanler } type rpcMaster struct { conn *rpc.Client addr string } const chSize = 1 func NewEtWorker() *EtNode { node := &EtNode{ ch: make(chan *common_models.ProcessData, chSize), recvDataHandler: et_recv.NewRecvDataHanler(), } node.exitMonitor() node.heartMonitor() return node } // Handler 是 RPC 服务方法,由 master 远程调用 func (the *EtNode) Handler(iotaData common_models.IotaData, replay *bool) error { *replay = true err := the.ConsumerProcess(&iotaData) if err != nil { *replay = false } return err } // ConsumerProcess 将 IotaData -> ProcessData func (the *EtNode) ConsumerProcess(iotaData *common_models.IotaData) error { deviceData, err := the.recvDataHandler.OnDataHandler(*iotaData) if err != nil { return err } if deviceData == nil { return nil } log.Printf("rpc处理设备数据[%s]-time[%s]-[%v]", deviceData.DeviceId, deviceData.AcqTime, deviceData.Raw) //log.Printf("rpc处理设备数据[%s]-time[%s]-data:%v", iotaData.DeviceId, iotaData.TriggerTime, iotaData.ThemeData.ThemeData) the.ch <- &common_models.ProcessData{ DeviceData: *deviceData, Stations: []common_models.Station{}, } return nil } // 实现源接口 //func (the *EtNode) Process(ctx context.Context) (<-chan any, error) { // source := make(chan any, chSize) // go func() { // defer close(source) // for { // select { // case a := <-the.ch: // source <- a // log.Printf("存储数据=>source out,len=%d,%d", len(source), len(the.ch)) // case <-ctx.Done(): // log.Println("退出[source] EtNode.Process") // return // } // // } // }() // return source, nil //} // RegisterToMaster 调用 master 发布的RPC服务方法 master.NodeRegister func (the *EtNode) RegisterToMaster() { maxCount := 3 connectCount := 0 for { connectCount++ if connectCount > maxCount { log.Printf("RegisterToMaster 失败 超过%d次,准备退出", maxCount) time.Sleep(time.Second * 10) os.Exit(1) } masterAddr := loadMasterAddr() masterConn, err := rpc.Dial("tcp", masterAddr) if err != nil { log.Printf("链接失败-> node[%s]", masterAddr) time.Sleep(time.Second * 5) continue } the.master = &rpcMaster{ conn: masterConn, addr: masterAddr, } time.Sleep(time.Millisecond * 200) //获取node自己地址 ipPrefix := configLoad.LoadConfig().GetString("node.hostIpPrefix") ip4 := common_utils.ReadIP4WithPrefixFirst(ipPrefix) hostName, err := os.Hostname() log.Printf("node [%s] ip=%s", hostName, ip4) port := configLoad.LoadConfig().GetUint16("node.port") callNodeAddr := fmt.Sprintf("%s:%d", ip4, port) if the.nodeInfo == nil { the.nodeInfo = &common_models.NodeArgs{ ID: hostName + time.Now().Format("_20060102_150405"), NodeType: "etNode", Status: "", Resources: "", Addr: callNodeAddr, ThingIds: []string{}, } } var result bool err = the.master.conn.Call("master.NodeRegister", the.nodeInfo, &result) if err != nil { log.Printf("node[%s] 注册到 master[%s]异常:%v", the.nodeInfo.Addr, the.master.addr, result) continue } break } } func (the *EtNode) heartToMaster() { maxCount := 3 connectCount := 0 reRegister := false for { connectCount++ if connectCount > maxCount { log.Printf("heartToMaster 失败 超过%d次", maxCount) reRegister = true break } var result bool err := the.master.conn.Call("master.NodeHeart", the.nodeInfo, &result) if err != nil { log.Printf("node[%s] 心跳到 master[%s]异常:%v", the.nodeInfo.Addr, the.master.addr, result) time.Sleep(time.Second * 5) continue } break } if reRegister { //触发重新注册 log.Printf("node[%s] 心跳失败触发-重新注册到 master[%s]", the.nodeInfo.Addr, the.master.addr) the.RegisterToMaster() } } func (the *EtNode) UnRegisterToMaster() { var result bool if err := the.master.conn.Call("master.NodeUnRegister", the.nodeInfo, &result); err != nil { log.Printf("node[%s] 注销到 master,异常:%v", the.nodeInfo.Addr, err.Error()) } else { log.Printf("node[%s] 注销到 master,结果:%v", the.nodeInfo.Addr, result) } } func (the *EtNode) exitMonitor() { go func() { c := make(chan os.Signal, 1) // 通过signal.Notify函数将信号通道c注册到系统相关的退出信号上 // 这里使用了两个退出信号:syscall.SIGINT(Ctrl+C)和syscall.SIGTERM(系统发送的退出信号) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) // 阻塞等待接收信号 s := <-c log.Printf("接收到退出信号:%v,进行清理工作\n", s) the.UnRegisterToMaster() time.Sleep(3 * time.Second) os.Exit(0) }() } func (the *EtNode) heartMonitor() { go func() { ticker := time.NewTicker(time.Minute) defer ticker.Stop() for range ticker.C { if the.master != nil { log.Printf("node[%s] 心跳触发-> master[%s]", the.nodeInfo.Addr, the.master.addr) the.heartToMaster() } } }() } // LoadCh test用 func (the *EtNode) LoadCh() chan *common_models.ProcessData { return the.ch } func loadMasterAddr() string { masterHost := configLoad.LoadConfig().GetString("node.remoteMasterHost") masterPort := configLoad.LoadConfig().GetUint16("master.port") if masterHost == "" { masterHost = "127.0.0.1" } if masterPort == 0 { masterPort = 50000 } return fmt.Sprintf("%s:%d", masterHost, masterPort) }