1.シリアルメッセージ
キーメッセージと値があります。
カフカは、カスタムクラスのサービスのためのデータ型ツールのシーケンスのための基礎は、自己のシリアル化を達成するために必要提供します
KVとヘッダーを含むProducerRecordオブジェクト、またはこの場合のオブジェクトKV
KVはKVのバイト配列を取得するためにKafkaProducer#doSendでシリアル化されます
その後、ヘッダーとProducerBatchのバイト配列に追加
コードは、以下を参照してください。
org.apache.kafka.clients.producer.internals.ProducerBatch#recordsBuilder
org.apache.kafka.common.record.MemoryRecordsBuilder#appendStream
TCPパケットの2カフカ
スキーマ構造体を使用してProducerBatch TCPパケットマッチング形式カフカにデータを変換します
例えば、メッセージを送信するには
org.apache.kafka.common.requests.AbstractRequest#toSend
org.apache.kafka.common.requests.AbstractRequest#シリアライズの
org.apache.kafka.common.requests.AbstractRequestResponse位シリアライズ
org.apache.kafka.common.requests.ProduceRequestを#toStruct
org.apache.kafka.common.protocol.types.Schema番号の書き込み
org.apache.kafka.common.requests.RequestHeader#toStruct
パブリック構造体toStruct(){ スキーマのスキーマ = スキーマ(apiKey.id、apiVersion)。 構造体構造体 = 新しい構造体(スキーマ)。 struct.set(API_KEY_FIELD_NAME、apiKey.id)。 struct.set(API_VERSION_FIELD_NAME、apiVersion)。 // のみ制御されたシャットダウン要求のV0のclientIdが欠落している 場合(struct.hasField(CLIENT_ID_FIELD_NAME)) struct.set(CLIENT_ID_FIELD_NAME、のclientId); struct.set(CORRELATION_ID_FIELD_NAME、correlationIdに)。 戻り値の構造体。 }
org.apache.kafka.common.requests.ProduceRequest#toStruct
パブリック構造体toStruct(){ // 同時更新から保護するために、ローカル変数に格納 地図<TopicPartition、MemoryRecords> partitionRecords = partitionRecordsOrFail(); 短いバージョン= バージョン()。 構造体構造体 = 新しい構造体(ApiKeys.PRODUCE.requestSchema(バージョン)); 地図 <文字列、地図<Integer型、MemoryRecords >> recordsByTopic = CollectionUtils.groupDataByTopic(partitionRecords)。 struct.set(ACKS_KEY_NAME、ACKの); struct.set(TIMEOUT_KEY_NAME、タイムアウト)。 struct.setIfExists(NULLABLE_TRANSACTIONAL_ID、transactionalId)。 リストの<struct> topicDatas =新しいのArrayList <> (recordsByTopic.size()); 用(のMap.Entry <文字列、マップ<整数、MemoryRecords >> topicEntry:recordsByTopic.entrySet()){ 構造体topicData = struct.instance(TOPIC_DATA_KEY_NAME)。 topicData.set(TOPIC_NAME、topicEntry.getKey())。 リストの<struct> partitionArray = 新しい ArrayListを<> (); 用(のMap.Entry <整数、MemoryRecords> partitionEntry:topicEntry.getValue()のentrySet()){ MemoryRecordsレコード = partitionEntry.getValue()。 構造体の一部 = topicData。 .SET(PARTITION_ID、partitionEntry.getKey()) .SET(RECORD_SET_KEY_NAME、レコード)。 partitionArray.add(部分)。 } topicData.set(PARTITION_DATA_KEY_NAME、partitionArray.toArray())。 topicDatas.add(topicData)。 } struct.set(TOPIC_DATA_KEY_NAME、topicDatas.toArray())。 戻り値の構造体。 }
パケットの組み立て
パブリック 抽象 クラスAbstractRequestResponse { / ** *テストのために目に見えます。 * / パブリック 静的のByteBufferのシリアライズ(構造体headerStruct、構造体bodyStruct){ ByteBufferのバッファ = ByteBuffer.allocate(headerStruct.sizeOf()+ bodyStruct.sizeOf())。 headerStruct.writeTo(バッファ) bodyStruct.writeTo(バッファ) buffer.rewind(); リターンバッファ; } } パブリック クラス NetworkSendが延びByteBufferSend { 公共NetworkSend(文字列先、ByteBufferのバッファ){ スーパー(宛先、sizeDelimit(緩衝液))。 } プライベート 静的のByteBuffer [] sizeDelimit(ByteBufferの緩衝液){ 戻り 新規のByteBuffer [] {sizeBuffer(buffer.remaining())、バッファ}。 } プライベート 静的のByteBuffer sizeBuffer(int型のサイズ){ ByteBufferのsizeBuffer = ByteBuffer.allocate(4 )。 sizeBuffer.putInt(サイズ)。 sizeBuffer.rewind(); 返すsizeBufferを。 } }
カフカのメッセージフォーマットを推測することが可能である:4バイトの記憶領域の長さ、headerStruct、bodyStruct
もちろん、NetworkSendやコメントでもNetworkReceive見ることができます