Kafka ナレッジ ベース - インデックス ディレクトリ
1.KafkaプロデューサーAPI
1. メッセージを送信する
Go 言語で Kafka プロデューサー API を使用するには、まず Kafka の Go クライアント ライブラリが必要です。
一般的に使用されるライブラリには、sarama または confluent-kafka-go などがあります。
sarama は Go 言語の Kafka クライアント ライブラリであり、Kafka と統合し、Kafka プロデューサーとコンシューマーの機能を実装するために使用されます。
ここでは sarama を使用して簡単な例を見てみましょう。手順は次のとおりです。
ステップ 1: Sarama ライブラリをインストールする
go get github.com/Shopify/sarama
ステップ 2: プロデューサー コードを作成する
package main
import (
"fmt"
"log"
"os"
"os/signal"
"github.com/Shopify/sarama"
)
func main() {
// 设置 Kafka broker 地址,创建配置
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll
config.Producer.Retry.Max = 5
config.Producer.Return.Successes = true
// 创建生产者
producer, err := sarama.NewSyncProducer([]string{
"kafka-broker1:9092", "kafka-broker2:9092"}, config)
if err != nil {
log.Fatalf("Error creating producer: %s", err.Error())
}
defer func() {
if err := producer.Close(); err != nil {
log.Fatalf("Error closing producer: %s", err.Error())
}
}()
// 构造消息
message := &sarama.ProducerMessage{
Topic: "your_topic", // 设置消息发送到的主题
Value: sarama.StringEncoder("Hello, Kafka!"), // 设置消息内容
}
// 发送消息
partition, offset, err := producer.SendMessage(message)
if err != nil {
log.Fatalf("Failed to send message: %s", err.Error())
}
fmt.Printf("Message sent to partition %d at offset %d\n", partition, offset)
// 处理退出信号
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
<-sigchan
}
コードの説明
- saramaライブラリを導入し、Kafkaの接続構成を設定します。
- プロデューサー インスタンスを作成します。
- Kafka トピックに送信するメッセージを作成します。
- プロデューサのメソッドを使用して
SendMessage
メッセージを送信します。 - 送信が成功した後、パーティションとオフセットを処理します。
- 信号処理を設定し、プログラムを閉じる割り込み信号を待ちます。
2. メッセージの圧縮
Kafka プロデューサー API でのメッセージ圧縮について話すときは、ネットワーク上で送信されるデータ量を削減し、送信効率を向上させるために、Kafka に送信する前にメッセージを圧縮することを指します。
Kafka は、GZIP、Snappy、LZ4 などの複数のメッセージ圧縮アルゴリズムを提供します。
ステップ 1: Sarama ライブラリをインポートする
まず、Sarama ライブラリがインストールされていることを確認します。これは、次のコマンドを使用してインストールできます。
go get github.com/Shopify/sarama
ステップ 2: メッセージ圧縮コードを作成する
package main
import (
"fmt"
"log"
"os"
"os/signal"
"github.com/Shopify/sarama"
)
func main() {
// 设置 Kafka broker 地址,创建配置
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll
config.Producer.Retry.Max = 5
config.Producer.Return.Successes = true
config.Producer.Compression = sarama.CompressionGZIP // 设置消息压缩算法
// 创建生产者
producer, err := sarama.NewSyncProducer([]string{
"kafka-broker1:9092", "kafka-broker2:9092"}, config)
if err != nil {
log.Fatalf("Error creating producer: %s", err.Error())
}
defer func() {
if err := producer.Close(); err != nil {
log.Fatalf("Error closing producer: %s", err.Error())
}
}()
// 构造消息
message := &sarama.ProducerMessage{
Topic: "your_topic", // 设置消息发送到的主题
Value: sarama.StringEncoder("Hello, Kafka!"), // 设置消息内容
}
// 发送消息
partition, offset, err := producer.SendMessage(message)
if err != nil {
log.Fatalf("Failed to send message: %s", err.Error())
}
fmt.Printf("Message sent to partition %d at offset %d\n", partition, offset)
// 处理退出信号
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
<-sigchan
}
ステップ 3: コードを説明する
この例では、Kafka プロデューサの作成時にメッセージ圧縮アルゴリズムを設定します。
config.Producer.Compression = sarama.CompressionGZIP // 设置消息压缩算法
ここでは GZIP 圧縮アルゴリズムを選択しましたが、Snappy や LZ4 などの他のアルゴリズムを選択することもできます。
圧縮アルゴリズムが設定されると、プロデューサーによって送信されるメッセージは、ネットワーク上で送信されるデータ量を削減するために、送信前に圧縮されます。
Kafka コンシューマはメッセージを受信した後に自動的に解凍するため、圧縮はコンシューマにとって透過的です。
3. プロデューサーの設定
ステップ 1: Sarama ライブラリをインポートする
まず、Sarama ライブラリがインストールされていることを確認します。これは、次のコマンドを使用してインストールできます。
go get github.com/Shopify/sarama
ステップ 2: プロデューサー構成コードを作成する
package main
import (
"fmt"
"log"
"os"
"os/signal"
"github.com/Shopify/sarama"
)
func main() {
// 创建配置
config := sarama.NewConfig()
// 设置生产者参数
config.Producer.RequiredAcks = sarama.WaitForAll // 设置等待所有副本确认消息
config.Producer.Retry.Max = 5 // 设置最大的重试次数
config.Producer.Return.Successes = true // 设置是否返回成功的消息
config.Producer.Compression = sarama.CompressionGZIP // 设置消息压缩算法
config.Producer.Partitioner = sarama.NewRandomPartitioner // 设置分区策略为随机分区
// 创建生产者
producer, err := sarama.NewSyncProducer([]string{
"kafka-broker1:9092", "kafka-broker2:9092"}, config)
if err != nil {
log.Fatalf("Error creating producer: %s", err.Error())
}
defer func() {
if err := producer.Close(); err != nil {
log.Fatalf("Error closing producer: %s", err.Error())
}
}()
// 构造消息
message := &sarama.ProducerMessage{
Topic: "your_topic", // 设置消息发送到的主题
Value: sarama.StringEncoder("Hello, Kafka!"), // 设置消息内容
}
// 发送消息
partition, offset, err := producer.SendMessage(message)
if err != nil {
log.Fatalf("Failed to send message: %s", err.Error())
}
fmt.Printf("Message sent to partition %d at offset %d\n", partition, offset)
// 处理退出信号
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
<-sigchan
}
ステップ 3: コードを説明する
この例では、sarama.Config
オブジェクトを作成し、いくつかの一般的なプロデューサー構成パラメーターを設定します。
-
config.Producer.RequiredAcks
: すべてのレプリカがメッセージを確認するまで待機するように設定します。つまり、プロデューサーは、メッセージが正常に送信されたと判断する前に、すべてのレプリカがメッセージを正常に書き込むのを待機します。 -
config.Producer.Retry.Max
: 最大再試行回数を設定します。メッセージの送信に失敗した場合、プロデューサーは最大回数だけメッセージの再送信を試みます。 -
config.Producer.Return.Successes
: 成功メッセージを返すかどうかを設定します。 に設定するとtrue
、プロデューサはメッセージの送信が成功したときにメッセージを返しますsuccess
。 -
config.Producer.Compression
: メッセージ圧縮アルゴリズムを設定します。ここでは GZIP が選択されています。必要に応じて他のアルゴリズムを選択できます。 -
config.Producer.Partitioner
: パーティショニング戦略を設定します。ここではランダム パーティショニング戦略が選択されます。つまり、メッセージはランダム パーティションに送信されます。
この例では、同期プロデューサー ( NewSyncProducer
) を使用していますが、NewAsyncProducer
必要に応じて非同期プロデューサー ( ) を選択することもできます。
4. パーティショナー
Kafka プロデューサー API のパーティショナーについて話すときは、メッセージがどのパーティションに送信されるかを決定するメカニズムを指します。
パーティショナーは、プロデューサーが Kafka トピックのどのパーティションにメッセージを書き込むかを決定するのに役立ちます。これは、メッセージの順序付け、ロード バランシング、および並列処理に影響を与えるため、設計上の重要な決定事項となります。
4.1 パーティショナーの役割
Kafka トピックは通常、複数のパーティションに分割されており、各パーティションは順序付けられたログです。メッセージは特定のパーティションに送信されるため、メッセージの順序が維持されます。パーティショナーのタスクは、特定のルールに基づいてメッセージがどのパーティションに属するかを決定することです。
4.2 例と詳細な説明
package main
import (
"fmt"
"log"
"os"
"os/signal"
"github.com/Shopify/sarama"
)
// CustomPartitioner 自定义分区器
type CustomPartitioner struct{
}
// Partition 实现sarama.Partitioner接口
func (p *CustomPartitioner) Partition(message *sarama.ProducerMessage, numPartitions int32) (int32, error) {
// 在这里,设置自定义的分区逻辑
// 这里简单地使用消息的 key 的哈希值对分区数取余
key := message.Key
if key == nil {
// 如果消息没有 key,使用默认分区(随机分区)
return int32(sarama.NewRandomPartitioner.RandomPartition(message, numPartitions)), nil
}
return int32(sarama.NewHashPartitioner.Hash(key, numPartitions)), nil
}
func main() {
// 创建配置
config := sarama.NewConfig()
// 设置自定义分区器
config.Producer.Partitioner = &CustomPartitioner{
}
// 创建生产者
producer, err := sarama.NewSyncProducer([]string{
"kafka-broker1:9092", "kafka-broker2:9092"}, config)
if err != nil {
log.Fatalf("Error creating producer: %s", err.Error())
}
defer func() {
if err := producer.Close(); err != nil {
log.Fatalf("Error closing producer: %s", err.Error())
}
}()
// 构造消息
message := &sarama.ProducerMessage{
Topic: "your_topic", // 设置消息发送到的主题
Value: sarama.StringEncoder("Hello, Kafka!"), // 设置消息内容
Key: sarama.StringEncoder("some_key"), // 设置消息的 key
}
// 发送消息
partition, offset, err := producer.SendMessage(message)
if err != nil {
log.Fatalf("Failed to send message: %s", err.Error())
}
fmt.Printf("Message sent to partition %d at offset %d\n", partition, offset)
// 处理退出信号
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
<-sigchan
}
4.3 コードの説明
この例では、最初にカスタム パーティショナーを作成しCustomPartitioner
、sarama.Partitioner
インターフェイスのPartition
メソッドを実装します。このメソッドではPartition
、独自のパーティショニング ロジックを定義できます。ここでは、メッセージのキーのハッシュ値を使用してパーティションの数を調整します。メッセージにキーがない場合は、デフォルトのランダム パーティションが使用されます。
func (p *CustomPartitioner) Partition(message *sarama.ProducerMessage, numPartitions int32) (int32, error) {
key := message.Key
if key == nil {
return int32(sarama.NewRandomPartitioner.RandomPartition(message, numPartitions)), nil
}
return int32(sarama.NewHashPartitioner.Hash(key, numPartitions)), nil
}
次に、このカスタム パーティショナーをプロデューサーの構成に設定します。
config.Producer.Partitioner = &CustomPartitioner{
}
このようにして、メッセージを送信するときに、プロデューサーはカスタム パーティショニング ロジックを使用して、メッセージをどのパーティションに送信するかを決定します。
5.シリアライザ
Kafka プロデューサー API のシリアライザーについて話すときは、メッセージをネットワーク経由で送信できるようにメッセージをバイト ストリームに変換するプロセスを指します。
Kafka では、プロデューサーによってメッセージが Kafka クラスターに送信される前に、メッセージをバイト ストリームにシリアル化する必要があります。シリアライザーは、メッセージ オブジェクトをバイト ストリームに変換し、そのバイト ストリームをコンシューマ側で元のメッセージ オブジェクトに逆シリアル化する役割を果たします。
このプロセスは、メッセージを効率的に送信し、ネットワークに保存できるようにするためのものです。
5.1 なぜシリアル化が必要なのでしょうか?
Kafka は分散メッセージング システムであり、メッセージは異なるノード間で配信される必要があります。このネットワーク間送信を実現するには、メッセージをバイト ストリームの形式で表現する必要があります。シリアル化は、メッセージ オブジェクトをバイト ストリームに変換するプロセスです。
5.2 例と詳細な説明
簡単な例でシリアル化プロセスを説明してみましょう。
次のようなメッセージ構造があるとします。
type MyMessage struct {
ID int
Body string
}
まず、この構造体をバイト ストリームに変換するシリアライザーを定義する必要があります。
package main
import (
"bytes"
"encoding/gob"
"fmt"
"log"
)
// MyMessage 结构体
type MyMessage struct {
ID int
Body string
}
// Serializer 序列化器
type Serializer struct{
}
// Serialize 将消息对象序列化为字节流
func (s *Serializer) Serialize(message *MyMessage) ([]byte, error) {
var buffer bytes.Buffer
encoder := gob.NewEncoder(&buffer)
err := encoder.Encode(message)
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
// Deserialize 将字节流反序列化为消息对象
func (s *Serializer) Deserialize(data []byte) (*MyMessage, error) {
var message MyMessage
decoder := gob.NewDecoder(bytes.NewReader(data))
err := decoder.Decode(&message)
if err != nil {
return nil, err
}
return &message, nil
}
func main() {
// 创建消息对象
message := &MyMessage{
ID: 1,
Body: "Hello, Kafka!",
}
// 创建序列化器
serializer := &Serializer{
}
// 序列化消息
serializedData, err := serializer.Serialize(message)
if err != nil {
log.Fatalf("Error serializing message: %s", err.Error())
}
// 打印序列化后的字节流
fmt.Printf("Serialized data: %v\n", serializedData)
// 反序列化消息
deserializedMessage, err := serializer.Deserialize(serializedData)
if err != nil {
log.Fatalf("Error deserializing message: %s", err.Error())
}
// 打印反序列化后的消息对象
fmt.Printf("Deserialized message: %+v\n", deserializedMessage)
}
5.3 コードの解釈
この例では、最初に単純なメッセージ構造を定義し、次にメソッドとメソッドを実装するMyMessage
シリアライザーを作成します。メソッドはメッセージ オブジェクトをバイト ストリームに変換し、メソッドはバイト ストリームをメッセージ オブジェクトに逆シリアル化します。Serializer
Serialize
Deserialize
Serialize
Deserialize
encoding/gob
シリアル化と逆シリアル化にはパッケージを使用します。実際のアプリケーションでは、ニーズやシステムの互換性に応じて、JSON や Avro などの他のシリアル化方法を選択できます。
最後に、メッセージ オブジェクトを作成し、シリアライザーを使用してそれをバイト ストリームにシリアル化し、結果を出力します。次に、バイト ストリームをメッセージ オブジェクトに逆シリアル化し、結果を出力します。これは、実際のアプリケーションにおけるシリアル化の基本的な使用法を示しています。