github.com/teng231/kafclient@v1.2.9/publisher.go (about) 1 package kafclient 2 3 import ( 4 "encoding/json" 5 "errors" 6 "log" 7 "strings" 8 9 "github.com/Shopify/sarama" 10 ) 11 12 func makeKafkaConfigPublisher(partitioner sarama.PartitionerConstructor) *sarama.Config { 13 config := sarama.NewConfig() 14 config.Producer.Retry.Max = 5 15 config.Producer.RequiredAcks = sarama.WaitForAll 16 config.Producer.Return.Successes = true 17 // config.Producer.Partitioner = sarama.NewManualPartitioner() 18 config.Producer.Partitioner = partitioner 19 // publisherConfig = config 20 return config 21 } 22 23 func newPublisher(topic string, brokerURLs ...string) (sarama.SyncProducer, error) { 24 config := makeKafkaConfigPublisher(sarama.NewRandomPartitioner) 25 prd, err := sarama.NewSyncProducer(brokerURLs, config) 26 if err != nil { 27 return nil, err 28 } 29 return prd, nil 30 } 31 32 func newAsyncPublisher(topic string, brokerURLs ...string) (sarama.AsyncProducer, error) { 33 config := makeKafkaConfigPublisher(sarama.NewRandomPartitioner) 34 prd, err := sarama.NewAsyncProducer(brokerURLs, config) 35 if err != nil { 36 return nil, err 37 } 38 return prd, nil 39 } 40 41 func newPublisherWithConfigPartitioner(topic *Topic, brokerURLs ...string) (sarama.SyncProducer, error) { 42 var config *sarama.Config 43 if topic.Partition == nil { 44 config = makeKafkaConfigPublisher(sarama.NewRandomPartitioner) 45 } else if ToInt32(topic.Partition) >= 0 { 46 config = makeKafkaConfigPublisher(sarama.NewManualPartitioner) 47 } 48 prd, err := sarama.NewSyncProducer(brokerURLs, config) 49 if err != nil { 50 return nil, err 51 } 52 return prd, nil 53 } 54 55 // InitPublisher init with addr is url of lookupd 56 func (ps *Client) InitPublisher(brokerURLs ...string) { 57 ps.brokerURLs = brokerURLs 58 // ps.producers = make(map[string]sarama.SyncProducer) 59 } 60 61 // Publish sync publish message 62 func (p *Client) Publish(topic string, messages ...interface{}) error { 63 if strings.Contains(topic, "__consumer_offsets") { 64 return errors.New("topic fail") 65 } 66 67 if _, ok := p.mProducer.Load(topic); !ok { 68 producer, err := newPublisher(topic, p.brokerURLs...) 69 if err != nil { 70 log.Print("[sarama]:", err, "]: topic", topic) 71 return err 72 } 73 p.mProducer.Store(topic, producer) 74 } 75 listMsg := make([]*sarama.ProducerMessage, 0) 76 for _, msg := range messages { 77 bin, err := json.Marshal(msg) 78 if err != nil { 79 log.Printf("[sarama] error: %v[sarama] msg: %v", err, msg) 80 } 81 msg := &sarama.ProducerMessage{ 82 Topic: topic, 83 Value: sarama.StringEncoder(bin), 84 Partition: -1, 85 } 86 // asyncProducer.(sarama.AsyncProducer).Input() <- msg 87 listMsg = append(listMsg, msg) 88 } 89 syncProducer, ok := p.mProducer.Load(topic) 90 if !ok { 91 log.Print("not found any sync Producer") 92 } 93 err := syncProducer.(sarama.SyncProducer).SendMessages(listMsg) 94 return err 95 } 96 97 // AsyncPublish async publish message 98 func (p *Client) AsyncPublish(topic string, messages ...interface{}) error { 99 if strings.Contains(topic, "__consumer_offsets") { 100 return errors.New("topic fail") 101 } 102 103 if _, ok := p.mProducer.Load(topic); !ok { 104 producer, err := newAsyncPublisher(topic, p.brokerURLs...) 105 if err != nil { 106 log.Print("[sarama]:", err, "]: topic", topic) 107 return err 108 } 109 p.mProducer.Store(topic, producer) 110 } 111 asyncProducer, _ := p.mProducer.Load(topic) 112 for _, msg := range messages { 113 bin, err := json.Marshal(msg) 114 if err != nil { 115 log.Printf("[sarama] error: %v[sarama] msg: %v", err, msg) 116 } 117 msg := &sarama.ProducerMessage{ 118 Topic: topic, 119 Value: sarama.StringEncoder(bin), 120 Partition: -1, 121 } 122 asyncProducer.(sarama.AsyncProducer).Input() <- msg 123 } 124 return nil 125 } 126 127 // PublishWithConfig sync publish message with select config 128 // Sender config help config producerMessage 129 func (p *Client) PublishWithConfig(topic *Topic, config *SenderConfig, messages ...interface{}) error { 130 if strings.Contains(topic.Name, "__consumer_offsets") { 131 return errors.New("topic fail") 132 } 133 if _, ok := p.mProducer.Load(topic); !ok { 134 producer, err := newPublisherWithConfigPartitioner(topic, p.brokerURLs...) 135 if err != nil { 136 log.Print("[sarama]:", err, "]: topic", topic) 137 return err 138 } 139 p.mProducer.Store(topic, producer) 140 } 141 listMsg := make([]*sarama.ProducerMessage, 0) 142 for _, msg := range messages { 143 bin, err := json.Marshal(msg) 144 if err != nil { 145 log.Printf("[sarama] error: %v[sarama] msg: %v", err, msg) 146 } 147 pmsg := &sarama.ProducerMessage{ 148 Topic: topic.Name, 149 Value: sarama.StringEncoder(bin), 150 Partition: -1, 151 } 152 if topic.Partition != nil { 153 pmsg.Partition = ToInt32(topic.Partition) 154 } 155 156 if config != nil { 157 pmsg.Metadata = config.Metadata 158 if len(config.Headers) > 0 { 159 for k, v := range config.Headers { 160 pmsg.Headers = append(pmsg.Headers, sarama.RecordHeader{Key: []byte(k), Value: []byte(v)}) 161 } 162 } 163 } 164 listMsg = append(listMsg, pmsg) 165 166 } 167 syncProducer, ok := p.mProducer.Load(topic) 168 if !ok { 169 log.Print("not found any sync Producer") 170 } 171 err := syncProducer.(sarama.SyncProducer).SendMessages(listMsg) 172 return err 173 }