持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
要往 Kafka 写入消息,要先创建一个生产对象并设置一些属性。Kafka 生产者 3个必选属性:
-
servers :设置指定 Broker 地址清单,地址格式:host:port。
- 清单里无需包含所有的 Broker 地址,因生产者会从给定的Broker 地址中找到其他的 Broker 信息
- 至少提供 2个 Broker 地址,防止其中一个宕机时,生产者仍可连接到集群上
-
key.serializer:键的序列化,即Broker 希望接收到的是字节数组数据
-
Value.serializer:值的序列化
创建生产者
分析使用 github.com/Shopify/sarama 包,创建生产者并发送消息:
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll
config.Producer.Partitioner = sarama.NewRandomPartitioner
config.Producer.Return.Successes = true
// 构造一个消息
msg := &sarama.ProducerMessage{}
msg.Topic = "web_log"
msg.Value = sarama.StringEncoder("test log message 2022-06-21")
// 连接kafka
client, err := sarama.NewSyncProducer([]string{"127.0.0.1:9092"}, config)
if err != nil {
fmt.Println("producer closed, err:", err)
return
}
defer client.Close()
// 发送消息
pid, offset, err := client.SendMessage(msg)
if err != nil {
fmt.Println("send msg failed, err:", err)
return
}
fmt.Printf("pid:%v offset:%v\n", pid, offset)
定义配置项
设置生产者的一些配置项:
-
RequiredAcks:指定必须要有多少个分区副本收到消息,生产者才认为消息写入成功。该配置有三个选项
const ( NoResponse RequiredAcks = 0 WaitForLocal RequiredAcks = 1 WaitForAll RequiredAcks = -1 )- acks = 0,NoResponse 生产者在成功写入消息之前不会等待任何来自服务器的相应。即如果服务没有收到消息,没有反馈,生产者也不知道是否发送成功
- acks=1 只要集群的 Leader 节点收到消息,生产者就会收到服务器的一个响应。只要 Leader 节点没收到,生产者都会收到一个错误响应,
- acks=-1 当所有的参与的节点都收到消息是,生产者才会收到服务器的成功响应
构造消息
msg := &sarama.ProducerMessage{}
type ProducerMessage struct {
Topic string
Key Encoder
Value Encoder
Headers []RecordHeader
Metadata interface{}
Offset int64
Partition int32
Timestamp time.Time
retries int
flags flagSet
expectation chan *ProducerError
sequenceNumber int32
producerEpoch int16
hasSequence bool
}
- Topic 消息的主题
- Key 消息的分区 Key ,前置序列化编码器 StringEncoder 和 ByteEncoder。
- Value 存储在 kafka 内的真正消息,前置序列化编码器 StringEncoder 和 ByteEncoder。
- Headers 键值对的头,在生产者和消费者之间传递
-
// The headers are key-value pairs that are transparently passed // by Kafka between producers and consumers. - Metadata 元数据
-
// This field is used to hold arbitrary data you wish to include so it // will be available when receiving on the Successes and Errors channels. // Sarama completely ignores this field and is only to be used for // pass-through data. - Partition 分区
- retries 发送失败次数然后再进行重试
创建生产者
- NewSyncProducer方法 是通过 Broker 地址和配置项创建一个同步生产者
func NewSyncProducer(addrs []string, config *Config) (SyncProducer, error) {
if config == nil {
config = NewConfig()
config.Producer.Return.Successes = true
}
if err := verifyProducerConfig(config); err != nil {
return nil, err
}
p, err := NewAsyncProducer(addrs, config)
if err != nil {
return nil, err
}
return newSyncProducerFromAsyncProducer(p.(*asyncProducer)), nil
}
- NewAsyncProducer方法是通过 Broker 地址和配置项创建一个异步生产者
func NewAsyncProducer(addrs []string, conf *Config) (AsyncProducer, error) {
client, err := NewClient(addrs, conf)
if err != nil {
return nil, err
}
return newAsyncProducer(client)
}
发送消息
- 同步发送消息
SendMessage(msg *ProducerMessage) (partition int32, offset int64, err error)
SendMessages(msgs []*ProducerMessage) error
同步发送提供2个方法:一个是逐条发送,返回结果是分区,消息的偏移量,和当发送失败的错误信息;一个是按批发送消息,如果部分发送势必啊或全部发送失败都会返回错误。
- 异步发送消息
Input() chan<- *ProducerMessage
Successes() <-chan *ProducerMessage
异步发送消息使用了Channel 来处理。input 进行发送消息,然后读取 Successes 方法来获取发送消息的结果,建议是两个方法一起使用。
-
参考资料:
- docs.confluent.io/kafka-clien…
- 《kafka 权威指南》