春・カフカカフカ統合深度クエストの春ブーツ

カフカの製品は、メッセージキューで、トピックのパーティションベースのデザインは非常に高いメッセージ送信処理性能を達成することができます。春は春カフカでプロジェクトを作成し、カフカ春プロジェクトの迅速な統合のために、Apacheのカフカ・クライアントをカプセル化します。シンプルなメッセージに加えて、春カフカものは、これらの利用クエストのそれぞれを見てみましょう、多くの高度な機能を提供しています

シンプルな統合

依存性の導入

<dependency>
  <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.2.6.RELEASE</version> </dependency>

設定を追加

spring.kafka.producer.bootstrap-サーバ= 127.0.0.1:9092

テストを送信し、受信

/**
 * @author: kl @kailing.pub
 * @date: 2019/5/30
 */
@SpringBootApplication @RestController public class Application { private final Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Autowired private KafkaTemplate<Object, Object> template; @GetMapping("/send/{input}") public void sendFoo(@PathVariable String input) { this.template.send("topic_input", input); } @KafkaListener(id = "webGroup", topics = "topic_input") public void listen(String input) { logger.info("input value: {}" , input); } }

アプリケーションを起動した後、ブラウザに入力します。http:// localhost:8080 / / KLを送ります。そこには、コンソール・ログ出力で見ることができます:入力値:「KL」。そのような基本的なシンプルを使用してください。コメントを追加し、メッセージKafkaTemplate注射を送信すると、メッセージを受信@KafkaListenerします。

春カフカテスト組み込みカフカサーバー

しかし、上記のコードは、正常に起動しますが、すでに私たちが展開パッケージをローカルに配置公式サイトからダウンロードすることができ、カフカがスカラ座+飼育係によって建設されたことを知って、サービス環境カフカサーバーを持って提供することができます。しかし、私はカフカ関連の機能を検証したリンクの開発を簡素化するために、春・カフカテストは、カフカ、テストパッケージされている、あなたに伝えたいカフカServerの機能の注釈型を使用して、超簡単です開くためのキーを提供します。カフカは、すべてのテストケース後でこの記事では、このサービス提供を使用して埋め込まれています。

依存性の導入

<dependency>
   <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka-test</artifactId> <version>2.2.6.RELEASE</version> <scope>test</scope> </dependency>

サービスを開始

以下の使用JUnitテストケースを直接4つのブローカーノードを含むカフカServerサービスを開始。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApplicationTests.class)
@EmbeddedKafka(count = 4,ports = {9092,9093,9094,9095}) public class ApplicationTests { @Test public void contextLoads(www.yuntianyuL.cn)throws IOException { System.in.read(); } }

上:ちょうどノート@EmbeddedKafka、あなたはフル機能のカフカのサービスを開始することができ、それはクールではありません。デフォルトでは、唯一の引数なしでメモを書く、ブローカーは、ランダムなポートを作成することです、ログは、特定の出力ポートと設定項目のデフォルト数を開始します。しかし、カフカのインストールパッケージの設定ファイルでこれらの設定項目は、次のパラメータを設定することができ@EmbeddedKafka詳細な注釈の下で、注釈パラメータで設定することができます。

  • 値:ブローカーノードの数
  • カウント:同じ値の役割を、単にノードブローカーの数の構成として、
  • controlledShutdownは:コントロールオフスイッチは、主にこのブローカーに予期せぬ時にブローカーパーティション使用不可時間をシャットダウン削減するために使用されます

      カフカは、高可用性サービス、対応する数のトピックパーティションのマルチブローカーアーキテクチャである、パーティションは、高可用性のために、これらのコピーは、複数のブローカーに格納された複製、複製の複数のコピーを有することができます。複数のパーティションのレプリカセットがあるが、現在の仕事が唯一のレプリカセットであるしかし、デフォルトでは書き込みと読み出したデータを担当するリーダー[用]レプリカセットのコピーの配布のための最初の選択肢です。必要性は、サービスを再起動するときに我々はブローカーブローカーの構成をアップグレードまたは更新すると、この時間は、使用可能なパーティションのブローカーに転送する必要があります。関連する以下の3例

  1.    直接閉鎖ブローカー:ブローカー閉じ、ブローカクラスタは、ホスト・オペレーティングは、パーティションのリーダーとして新しいブローカーを選ぶ再選出する、選挙パーティションは、この短い使用できないブローカーになります
  2.   オープンcontrolledShutdown:ブローカが閉じたときに、ブローカー自体が最初に他の利用可能なブローカーに転送リーダーの役割にしようとします
  3.   コマンドラインツールを使用します。bin / kafka-preferred-replica-election.shを使用して、手動でロールPartitionLeaderを転送トリガさ
  • ポート:ポートリストは配列です。カウントに対応するパラメータは、いくつかのブローカーがあり、いくつかのポート番号に対応します
  • brokerProperties:ブローカパラメータ設定は、アレイ構造は、以下のようブローカパラメータをサポートしています。
@EmbeddedKafka(brokerProperties = {"log.index.interval.bytes = 4096","num.io.threads = 8"})
  • okerPropertiesLocation:ブローカーパラメータファイルの設定

  上記brokerProperties持つ関数が、カフカブローカパラメータはこの上記のように構成されているような多くの、182のように設定することができ、したがってような負荷ローカルプロファイル機能を提供する、確かに最適な解決策ではありません。

@EmbeddedKafka(brokerPropertiesLocation = "classpath:application.properties")

新しいトピックを作成します。

デフォルトでは、あなたがメッセージを送信するためにKafkaTemplateを使用する場合、トピックが存在しない、新しいトピック、パーティションのデフォルト数と、次のパラメータのブローカーに設定された部数を作成します

パーティションのnum.partitions = 1#デフォルトのトピックの数
コピーのnum.replica.fetchers = 1つの#のデフォルト数

プログラムの起動時にトピックを作成しました

/**
 * @author: kl @kailing.pub
 * @date: 2019/5/31
 */
@Configuration public class KafkaConfig { @Bean public KafkaAdmin admin(KafkaProperties properties){ KafkaAdmin admin = new KafkaAdmin(properties.buildAdminProperties()); admin.setFatalIfBrokerNotAvailable(true); return admin; } @Bean public NewTopic topic2(www.yongshiyule178.com) { return new NewTopic("topic-kl", 1, (short) 1); } }

カフカブローカーのサポート(1.0.0以降)であれば、それはセットよりも少ない既存のトピックパーティション番号パーティションの数は、新しいパーティションのパーティションを追加することが判明した場合。KafkaAdminについて次のように一般的に使用されるいくつかがあります。

setFatalIfBrokerNotAvailable(真):デフォルト値はFalseで、そしてときブローカーが使用できない、Springコンテキストの初期化には影響を与えません。あなたは、これはブローカーに影響すると考えられる場合はTrueに表示される利用でき、通常のビジネス上の価値ではありません

setAutoCreate(偽):カフカは、オブジェクトがNewTopicをインスタンス化されている作成し、自動的にインスタンス化した後、デフォルト値は、つまり、真であります

)(初期設定:setAutoCreateがfalseの場合、我々はNewTopicオブジェクトを初期化するプログラム表示のinitialize()メソッドの管理者を呼び出す必要があります

コードロジックを作成します

時には我々は、適切なパーティションのトピックの必要性の数の何を知りませんが、プログラムの起動時にBrokerのデフォルト設定を使用して直接落ちることができない、あなたはカフカ・クライアントを使用する必要があり、この時間は、処理のためにAdminClientをしています。KafkaAdminパッケージ上の春のAdminClientはに対処するために使用されています。以下のような:

	@Autowired
	private KafkaProperties properties;
	@Test
	public void testCreateToipc(){ AdminClient client = AdminClient.create(properties.buildAdminProperties()); if(client !=null){ try { Collection<NewTopic> newTopics = new ArrayList<>(1); newTopics.add(new NewTopic("topic-kl",1,(short) 1)); client.createTopics(newTopics); }catch (Throwable e){ e.printStackTrace(); }finally { client.close(www.honglpt.cn); } } }

PS:トピックを作成する他の方法

春-kafka2.x版のみ春boot2.xのバージョンをサポートしているためトピック前提を作成するには、これらの方法の上、上記のあなたの春のブートバージョン2.xです。1.xのバージョンではこれらのAPIを持っていません。道Kafka_2.10によって以下を追加するためのプログラムは、トピックを作成します

依存性の導入

        <dependency>
            <groupId>org.apache.kafka</groupId> <artifactId>kafka_2.10</artifactId> <version>0.8.2.2</version> </dependency> 

道のAPIを作成します。

	@Test
	public void testCreateTopic()throws Exception{ ZkClient zkClient =new ZkClient("127.0.0.1:2181", 3000, 3000, ZKStringSerializer$.MODULE$) String topicName = "topic-kl"; int partitions = 1; int replication = 1; AdminUtils.createTopic(zkClient,topicName,partitions,replication,new Properties()); }

上院へZkClient最後のコンストラクタ次のノートは、シリアル化されたインタフェースデシリアライズされ、ZKで作成し、あなたがそれを埋めるしない場合ブロガーは、テストデータのトピックに問題がある、デフォルトカフカの実装は非常に簡単です、私は、UTF-8エンコードされた文字列の処理を行いました。ZKStringSerializer $カフカが達成された、優れたインターフェイスインスタンスであるScalaのコンパニオンオブジェクトで、Javaで直接ポイントMODULE $を呼び出すには、インスタンスを取得することができます

コマンドモードを作成します。

	@Test
	public void testCreateTopic(){ String [] options= new String[]{ "--create", "--zookeeper","127.0.0.1:2181", "--replication-factor", "3", "--partitions", "3", "--topic", "topic-kl" }; TopicCommand.main(options); }

クエストのKafkaTemplateメッセージ

送信結果を取得します

非同期買収

		template.send("","").addCallback(new ListenableFutureCallback<SendResult<Object, Object>>() {
			@Override
			public void onFailure(Throwable throwable) { ...... } @Override public void onSuccess(SendResult<Object, Object> objectObjectSendResult) { .... } });

同期獲得

		ListenableFuture<SendResult<Object,Object>> future = template.send("topic-kl","kl");
		try {
			SendResult<Object,Object> result = future.get();
		}catch (Throwable e){
			e.printStackTrace();
		}

カフカの取引メッセージ

デフォルトでは、KafkaTemplate春カフカのインスタンスが自動的に生成され、トランザクションメッセージング機能ではありません。トランザクションを有効に次の機能を使用する必要があります。取引が活性化された後、送信されたすべてのメッセージは、それ以外の場合は、異常な取引トランザクションをスローしません、発生した取引の方法で行うことができます

spring.kafka.producer.transaction-id-prefix=kafka_tx.

すべてのメッセージが正常に送信された場合、例えば、トランザクションを必要とするメッセージを送信するとき、次の例のように、成功する:異常を発行すると、最初に送信された第2のメッセージで発生した前に、送信後の最初の消費者を仮定メッセージはロールバックされます。通常は、それが第2のメッセージを送信し、メッセージを送信した後、時間の休止期間を想定している、唯一の方法で行われる消費者側がトランザクション完了メッセージを受信します

	@GetMapping("/send/{input}")
	public void sendFoo(@PathVariable String input) { template.executeInTransaction(t ->{ t.send("topic_input","kl"); if("error".equals(input)){ throw new RuntimeException("failed"); } t.send("topic_input","ckl"); return true; }); }

場合は、トランザクション機能も上記の方法で活性化、プラス@Transactionalノートが発効します

	@GetMapping("/send/{input}")
	@Transactional(rollbackFor = RuntimeException.class)
	public void sendFoo(@PathVariable String input) { template.send("topic_input", "kl"); if ("error".equals(input)) { throw new RuntimeException("failed"); } template.send("topic_input", "ckl"); }

春カフカトランザクションメッセージは、カフカが提供するトランザクションベースのメッセージング機能です。サービスおよび設定の高可用性のための3つ以上のブローカーのとカフカブローカーのデフォルト設定。テストが埋め込まれたサービスは、カフカサービスの単一ブローカーを作成し、使用するための簡単で便利であるときここで、いくつかの問題がありますなど、

1、トランザクションログがブローカーを設定するコピーの数よりも大きい場合、次の例外がスローされます。

Number of alive brokers '1' does not meet the required replication factor '3' 
for the transactions state topic (configured via 'transaction.state.log.replication.factor'). This error can be ignored if the cluster is starting up and not all brokers are up yet.

ブローカデフォルト設定transaction.state.log.replication.factor = 3、シングルノードに調整することができます

2は、コピー数がコピーの同期キュー数未満である、次の例外がスローされます

Number of insync replicas for partition __transaction_state-13 is [1], below required minimum [2]

2 = transaction.state.log.min.isrブローカのデフォルト設定は、単一のノードを1に調整されています

メッセージ応答を取得ReplyingKafkaTemplate

ReplyingKafkaTemplate KafkaTemplateは、継承されたメソッドに加えて、親クラスのサブクラスである新しい方法sendAndReceive、メッセージ伝送\返信セマンティクスを実装します

RequestReplyFuture<K, V, R> sendAndReceive(ProducerRecord<K, V> record);

つまり、私は返される結果を得ることができ、消費者にメッセージを送信します。その伝統的なRPCの相互作用などがあります。メッセージの送信者がニュースの消費者の特定の消費量を知るために必要がある場合は、このAPIのための理想的です。例えば、データのバッチで送信されたメッセージは、消費者が正常に処理されるデータを知る必要があります。次のコードは統合とReplyingKafkaTemplateを使用する方法を示しています

/**
 * @author: kl @kailing.pub
 * @date: 2019/5/30
 */
@SpringBootApplication @RestController public class Application { private final Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public ConcurrentMessageListenerContainer<String, String> repliesContainer(ConcurrentKafkaListenerContainerFactory<String, String> containerFactory) { ConcurrentMessageListenerContainer<String, String> repliesContainer = containerFactory.createContainer("replies"); repliesContainer.getContainerProperties().setGroupId("repliesGroup"); repliesContainer.setAutoStartup(false); return repliesContainer; } @Bean public ReplyingKafkaTemplate<String, String, String> replyingTemplate(ProducerFactory<String, String> pf, ConcurrentMessageListenerContainer<String, String> repliesContainer) { return new ReplyingKafkaTemplate(pf, repliesContainer); } @Bean public KafkaTemplate kafkaTemplate(ProducerFactory<String, String> pf) { return new KafkaTemplate(pf); } @Autowired private ReplyingKafkaTemplate template; @GetMapping("/send/{input}") @Transactional(rollbackFor = RuntimeException.class) public void sendFoo(@PathVariable String input) throws Exception { ProducerRecord<String, String> record = new ProducerRecord<>("topic-kl", input); RequestReplyFuture<String, String, String> replyFuture = template.sendAndReceive(record); ConsumerRecord<String, String> consumerRecord = replyFuture.get(); System.err.println("Return value: " + consumerRecord.value()); } @KafkaListener(id = "webGroup", topics = "topic-kl") @SendTo public String listen(String input) { logger.info("input value: {}", input); return "successful"; } }

春カフカのニュース消費者の利用クエスト

使用@KafkaListener

次のように簡単に統合の前には、それはすでにメッセージを受信する@KafkaListener能力が、より多くのそれよりも、他のより一般的な、より多くの使用シナリオのファンクションポイント@KafkaListener機能を説明してきました。

  • トピックは、メッセージの消費とディスプレイを分割を指定します、
  • 各パーティションはオフセット提供し、トピックが初期化され、
  • 設定し消費者のスレッドの同時実行
  • 設定されたメッセージの例外ハンドラ
	@KafkaListener(id = "webGroup", topicPartitions = {
			@TopicPartition(topic = "topic1", partitions = {"0", "1"}), @TopicPartition(topic = "topic2", partitions = "0", partitionOffsets = @PartitionOffset(partition = "1", initialOffset = "100")) },concurrency = "6",errorHandler = "myErrorHandler") public String listen(String input) { logger.info("input value: {}", input); return "successful"; }

他の注釈パラメータが十分に理解されている、のErrorHandlerインターフェースKafkaListenerErrorHandlerを実装する必要があり、注意してこのパラメータを設定する必要があります。そして構成のノートは、あなたが春のコンテキストでカスタム実装の名前インスタンスです。例えば、上記構成のErrorHandler =「myErrorHandler」。春のインスタンス上のラインがあるはずです。

/**
 * @author: kl @kailing.pub
 * @date: 2019/5/31
 */
@Service("myErrorHandler") public class MyKafkaListenerErrorHandler implements KafkaListenerErrorHandler { Logger logger =LoggerFactory.getLogger(getClass()); @Override public Object handleError(Message<?> message, ListenerExecutionFailedException exception) { logger.info(message.getPayload().toString()); return null; } @Override public Object handleError(Message<?> message, ListenerExecutionFailedException exception, Consumer<?, ?> consumer) { logger.info(message.getPayload().toString()); return null; } }

Ackを手動モード

ACKマニュアルモードは、サービスによって制御ロジックはオフセット提出しました。例えば、プログラム支出は、この意味論がある場合、それは提出オフセットされていない、特に異常な状況下で、ACKを、確認しない場合、あなただけのAckを行うには、マニュアルモードを使用することができます。あなたが最初に手動で自動送信をオフにする必要があり、その後、消費者の支出パターンを下に設定

=偽spring.kafka.consumer.enable-自動コミット
spring.kafka.listener.ackモード=マニュアル

さて上記の設定後、消費者には、唯一の謝辞に参加する@KafkaListenerリスナーメソッドでは、オフセットに代わって提出)(ack.acknowledgeするために実行することができます

	@KafkaListener(id = "webGroup", topics = "topic-kl")
	public String listen(String input, Acknowledgment ack) { logger.info("input value: {}", input); if ("kl".equals(input)) { ack.acknowledge(); } return "successful"; }

ライフサイクルリスナーのコメント@KafkaListener

@KafkaListenerコメントのライフサイクルのリスナーは、デフォルトでは、制御することができ、パラメータの自動起動@ KafkaListener =「true」を。それは自動的にアクティブ消費ですが、またKafkaListenerEndpointRegistryを通して彼のライフサイクルに干渉することができます。スタート()、一時停止()、履歴書()/、停止、起動を続行:KafkaListenerEndpointRegistryアクションのように3つの方法があります。次のコードは、詳細に、この機能を示しています。

/**
 * @author: kl @kailing.pub
 * @date: 2019/5/30
 */
@SpringBootApplication @RestController public class Application { private final Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Autowired private KafkaTemplate template; @GetMapping("/send/{input}") @Transactional(rollbackFor = RuntimeException.class) public void sendFoo(@PathVariable String input) throws Exception { ProducerRecord<String, String> record = new ProducerRecord<>("topic-kl", input); template.send(record); } @Autowired private KafkaListenerEndpointRegistry registry; @GetMapping("/stop/{listenerID}") public void stop(@PathVariable String listenerID){ registry.getListenerContainer(listenerID).pause(); } @GetMapping("/resume/{listenerID}") public void resume(@PathVariable String listenerID){ registry.getListenerContainer(listenerID).resume(); } @GetMapping("/start/{listenerID}") public void start(@PathVariable String listenerID){ registry.getListenerContainer(listenerID).start(); } @KafkaListener(id = "webGroup", topics = "topic-kl",autoStartup = "false") public String listen(String input) { logger.info("input value: {}", input); return "successful"; } }

上記のコードでは、listenerID @KafkaListener「はwebGroup」のid値です。プロジェクトの良いスタートした後、それぞれ、以下のURLを行い、あなたが効果を見ることができます。

します。http:// localhost:8081 /送信/ CKLメッセージを送信します。自動起動=「false」をするので、そのためのリスナーへのメッセージは表示されません。

その後、リスナーを開始します。http:// localhost:8081 / / webGroupを開始します。私たちは、来るメッセージがある見ることができます。

一時停止と同様の方法を使用して、消費効果を再開する試すことができます。

SendToのメッセージ転送

@SendToが、実際には、意味の外側を行うために応答を送信する以外には、@のSendToアノテーションは、さらにパラメータを取ることができます見られているアプリケーションに応答して送信される前のメッセージは、トピックの転送キューを指定します。このようなメッセージのような一般的なシナリオでは、それはトピックと異なるホスト上の異なる横切って展開消費者によって解決することができ、複数の加工、消費矛盾カップ異なる処理リソースを実行する必要があります。以下のような:

	@KafkaListener(id = "webGroup", topics = "topic-kl")
	@SendTo("topic-ckl") public String listen(String input) { logger.info("input value: {www.oushengyule.com}", input); return input + "hello!"; } @KafkaListener(id = "webGroup1", topics = "topic-ckl") public void listen2(String input) { logger.info("input value: {}", input); }

アプリケーションメッセージの再試行とデッドレターキュー

上記シフト量に加えて、手動Ackメッセージモードによって制御され、また、メッセージのセマンティクス消費を再試行することができるパッケージ内事実春カフカ、それは異常な消費量データは、メッセージを再試行し、発生したときに提供されます。メッセージは、スケジュールトピックを入力するようにした後、あなたは、到達を再試行する回数を設定することができます。これは、デッドレターキューです。次のコードは、この効果を示しています。

	@Autowired
	private KafkaTemplate template;

	@Bean
	public ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory(
			ConcurrentKafkaListenerContainerFactoryConfigurer configurer,
			ConsumerFactory<Object, Object> kafkaConsumerFactory,
			KafkaTemplate<Object, Object> template) {
		ConcurrentKafkaListenerContainerFactory<www.gouyiflb.cn Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>(); configurer.configure(factory, kafkaConsumerFactory); //最大重试三次 factory.setErrorHandler(new SeekToCurrentErrorHandler(new DeadLetterPublishingRecoverer(template), 3)); return factory; } @GetMapping("/send/{input}") public void sendFoo(@PathVariable String input) { template.send(www.chengmyuLegw.cn"topic-kl", input); } @KafkaListener(id = "webGroup", topics = "topic-kl") public String listen(String input) { logger.info("input value: {}", input); throw new RuntimeException("dlt"); } @KafkaListener(id = "dltGroup", topics = "topic-kl.DLT") public void dltListen(String input) { logger.info("Received from DLT: " + input); } 

上記の応用、話題は-KLその後、リスナーは最大再試行回数に達した後、呼び出しを3回試みます、異常動作をトリガしたメッセージに耳を傾けます。再試行メッセージが配信不能キュー内で行くことに破棄されます。デッドレターキュートピックルールは、そのビジネストピック名+「DLT」です。「トピック-KL」について上述したように、ビジネスのトピック名は、その後、該当するトピック不能キュー「トピックkl.DLT」であります

結論を終了

最近、RPC呼び出しのように、そのようなコメントオープン埋め込まれたカフカサービスとしてそう体系、春カフカカフカのサービスを使用使用春カフカの下で様々な用途を模索楽しいクールな機能の多くを発見しました\応答セマンティクスを送ると同様トランザクションメッセージやその他の機能を呼び出します。私はこのブログが使用している人たちを助けることができるか、春カフカが少ない一部の迂回路が少ない小さなピットを踏む取る使うことを願っています。

おすすめ

転載: www.cnblogs.com/qwangxiao/p/10958886.html