1. 下载安装kafka第三方工具包 我这使用的是1.27.2版本
go get github.com/Shopify/sarama@v1.27.2
2. 同步 生产者发送消息
func getSyncProducer() (sarama.SyncProducer, error) {
config := sarama.NewConfig()
// 返回指定要填充的通道。如果它们设置为true,则必须从相应的通道中读取,以防止死锁。
// 但是,如果此配置用于创建“SyncProducer”,则两者都必须设置为true,并且您不能从通道中读取,因为生产者在内部执行此操作。
config.Producer.Return.Successes = true
config.Producer.Return.Errors = true
producer, err := sarama.NewSyncProducer([]string{"localhost:9092"}, config)
return producer, err
}
func SyncProducer() {
producer, err := getSyncProducer()
if err != nil {
log.Fatalln(err)
}
defer func() {
if err := producer.Close(); err != nil {
log.Fatalln(err)
}
}()
msg := &sarama.ProducerMessage{Topic: "test_topic", Value: sarama.StringEncoder("hello 123")}
partition, offset, err := producer.SendMessage(msg)
if err != nil {
log.Printf("FAILED to send message: %s\n", err)
} else {
log.Printf("> message sent to partition %d at offset %d\n", partition, offset)
}
}
3. 异步 生产者发送消息 适用于并发量大场景
func getAsyncProducer() (sarama.AsyncProducer, error) {
config := sarama.NewConfig()
// 返回指定要填充的通道。如果它们设置为true,则必须从相应的通道中读取,以防止死锁。
// 但是,如果此配置用于创建“SyncProducer”,则两者都必须设置为true,并且您不能从通道中读取,因为生产者在内部执行此操作。
config.Producer.Return.Successes = true
config.Producer.Return.Errors = true
// 控制消息被批量处理并发送到代理的频率。默认情况下,消息会尽可能快地发送
config.Producer.Flush.Frequency = 500 * time.Millisecond //Flush batches every 500ms
// 对消息使用的压缩类型(默认为无压缩)
//config.Producer.Compression = sarama.CompressionSnappy //Compress messages
producer, err := sarama.NewAsyncProducer([]string{"localhost:9092"}, config)
// 生产环境下应这样操作
//if err != nil {
// return nil, err
//}
//go func() {
// for {
// select {
// // 此处可以做一些事情
// case <-producer.Successes():
// // 此处可以做一些事情
// case fail := <-producer.Errors():
// if fail != nil {
// fmt.Println(fail.Error())
// }
// }
// }
//}()
return producer, err
}
// 适用于并发量大场景
func AsyncProducer() {
producer, err := getAsyncProducer()
if err != nil {
panic(err)
}
defer func() {
if err := producer.Close(); err != nil {
log.Fatalln(err)
}
}()
// 发送消息
message := &sarama.ProducerMessage{Topic: "test_topic", Value: sarama.StringEncoder("hello 6666")}
producer.Input() <- message
// 此处为了测试 打印结果 开始
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
// 注意 如果 Return.Successes 和 Return.Errors 设置为true,则必须从相应的通道中读取,以防止死锁。
select {
case d := <-producer.Successes():
fmt.Println(d)
break
case err := <-producer.Errors():
fmt.Println(err)
break
}
}()
// 此处为了测试 打印结果 结束
wg.Wait()
}
4. 消费消息
// 消费者
func Consumer() {
consumer, err := sarama.NewConsumer([]string{"192.168.223.134:9092"}, nil)
if err != nil {
panic(err)
}
defer func() {
if err := consumer.Close(); err != nil {
log.Fatalln(err)
}
}()
partitionConsumer, err := consumer.ConsumePartition("test_topic", 0, sarama.OffsetNewest)
if err != nil {
panic(err)
}
defer func() {
if err := partitionConsumer.Close(); err != nil {
log.Fatalln(err)
}
}()
// Trap SIGINT to trigger a shutdown.
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt)
consumed := 0
ConsumerLoop:
for {
select {
case msg := <-partitionConsumer.Messages():
log.Printf("Consumed message offset %d\n", msg.Offset)
fmt.Println(string(msg.Value))
consumed++
case <-signals:
break ConsumerLoop
}
}
}