[实践篇]Go sarama包 创建生产者

1,061 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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 方法来获取发送消息的结果,建议是两个方法一起使用。