github.com/sereiner/library@v0.0.0-20200518095232-1fa3e640cc5f/queue/xmq/xmq.producer.go (about) 1 package xmq 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "sync" 8 "time" 9 10 "github.com/sereiner/library/encoding" 11 logger "github.com/sereiner/library/log" 12 "github.com/sereiner/library/mq" 13 "github.com/sereiner/library/queue" 14 ) 15 16 //XMQProducer Producer 17 type XMQProducer struct { 18 conf *Conf 19 conn net.Conn 20 connecting bool 21 isConnected bool 22 closeCh chan struct{} 23 done bool 24 lk sync.Mutex 25 writeLock sync.Mutex 26 // header []string 27 lastWrite time.Time 28 firstConnected bool 29 Logger *logger.Logger 30 } 31 32 //New 创建新的producer 33 func New(address []string, c string) (producer *XMQProducer, err error) { 34 producer = &XMQProducer{} 35 producer.closeCh = make(chan struct{}) 36 producer.conf, err = NewConf(c) 37 if err != nil { 38 return nil, err 39 } 40 if producer.Logger == nil { 41 producer.Logger = logger.GetSession("xmq.queue", logger.CreateSession()) 42 } 43 // producer.header = make([]string, 0, 4) 44 return producer, producer.Connect() 45 } 46 47 //Connect 循环连接服务器 48 func (producer *XMQProducer) Connect() error { 49 err := producer.connectOnce() 50 if err != nil { 51 producer.Logger.Error(err) 52 } 53 go func() { 54 START: 55 for { 56 select { 57 case <-producer.closeCh: 58 break START 59 case <-time.After(time.Second * 3): 60 if producer.done { 61 return 62 } 63 if producer.isConnected { 64 if time.Since(producer.lastWrite).Seconds() > 3 { 65 message, err := NewXMQHeartBit().MakeMessage() 66 if err != nil { 67 producer.Logger.Error(err) 68 continue 69 } 70 err = producer.writeMessage(message) 71 if err == nil { 72 continue 73 } 74 producer.Logger.Error(err) 75 err = producer.connectOnce() 76 if err != nil { 77 producer.Logger.Error(err) 78 } 79 } 80 continue 81 } 82 err = producer.connectOnce() 83 if err != nil { 84 producer.Logger.Error(err) 85 } 86 87 } 88 } 89 }() 90 return nil 91 } 92 93 func (producer *XMQProducer) writeMessage(msg string) error { 94 if !producer.isConnected { 95 return fmt.Errorf("未连接到服务器") 96 } 97 producer.writeLock.Lock() 98 defer producer.writeLock.Unlock() 99 producer.lastWrite = time.Now() 100 result, err := encoding.Decode(msg, "gbk") 101 if err != nil { 102 return err 103 } 104 _, err = producer.conn.Write(result) 105 producer.lastWrite = time.Now() 106 if err != nil { 107 producer.Logger.Warn("发送数据失败:", err) 108 //producer.disconnect() 109 } 110 return err 111 } 112 113 func (producer *XMQProducer) disconnect() { 114 producer.isConnected = false 115 if producer.conn == nil { 116 return 117 } 118 producer.conn.Close() 119 return 120 } 121 122 //reconnect 自动重连 123 func (producer *XMQProducer) reconnect() { 124 producer.conn.Close() 125 producer.disconnect() 126 err := producer.Connect() 127 if err != nil { 128 producer.Logger.Errorf("连接到MQ服务器失败:%v", err) 129 } 130 } 131 132 //ConnectOnce 连接到服务器 133 func (producer *XMQProducer) connectOnce() (err error) { 134 if producer.connecting { 135 return nil 136 } 137 producer.lk.Lock() 138 defer producer.lk.Unlock() 139 if producer.connecting { 140 return nil 141 } 142 producer.connecting = true 143 defer func() { 144 producer.connecting = false 145 }() 146 producer.isConnected = false 147 producer.conn, err = net.DialTimeout("tcp", producer.conf.Address, time.Second*2) 148 if err != nil { 149 return fmt.Errorf("mq 无法连接到远程服务器:%v", err) 150 } 151 if !producer.firstConnected { 152 producer.firstConnected = true 153 } else { 154 producer.Logger.Info("恢复连接:", producer.conf.Address) 155 } 156 producer.isConnected = true 157 producer.lastWrite = time.Now() 158 return nil 159 } 160 func (producer *XMQProducer) Push(queue string, msg string) error { 161 return producer.Send(queue, msg, time.Hour*1000) 162 } 163 164 func (producer *XMQProducer) Pop(key string) (string, error) { 165 return "", fmt.Errorf("not support") 166 } 167 func (producer *XMQProducer) Count(key string) (int64, error) { 168 return 0, nil 169 } 170 171 //Send 发送消息 172 func (producer *XMQProducer) Send(queue string, msg string, timeout time.Duration) (err error) { 173 if producer.done { 174 return errors.New("mq producer 已关闭") 175 } 176 if !producer.isConnected { 177 return fmt.Errorf("producer无法连接到MQ服务器:%s", producer.conf.Address) 178 } 179 message := NewXMQMessage(queue, msg, int(timeout/time.Second)) 180 if producer.conf.Key != "" { 181 message.signKey = producer.conf.Key 182 } 183 smessage, err := message.MakeMessage() 184 if err != nil { 185 return 186 } 187 pmsg := &mq.ProcuderMessage{Queue: queue, Data: smessage, Timeout: timeout} 188 return producer.writeMessage(pmsg.Data) 189 } 190 191 //Close 关闭当前连接 192 func (producer *XMQProducer) Close() error { 193 producer.done = true 194 close(producer.closeCh) 195 return nil 196 } 197 198 type xmqResolver struct { 199 } 200 201 func (s *xmqResolver) Resolve(address []string, conf string) (queue.IQueue, error) { 202 return New(address, conf) 203 } 204 205 func init() { 206 queue.Register("xmq", &xmqResolver{}) 207 }