序文
この章を読む前に、必ず次の準備を行ってください。
1. Zookeeper [公式Web サイト]をインストールして起動します。ヘルプが必要な場合は、クリックして入力してください。
2. Kafka [公式Web サイト]をインストールして起動しました。ヘルプが必要な場合は、クリックして入力してください。
注: zk と kafka のインストールと導入については、この記事では紹介に焦点を当てていません。詳細については、上のリンクを参照してください。
¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥_ _
1. 準備
1.1. 新しい Spring Boot 2.x Web プロジェクトを作成する
1.1.1. プロジェクト作成手順のデモンストレーション
以下のオプションを必ずご確認ください。
1.1.2. プロジェクトカタログ表示
注:プロジェクトが正常に作成されたら、最初にパッケージと Java ファイルを作成して、次のコード作成作業への道を開きます。
1.2、pom.xml は spring-kafka 関連の依存関係を追加します
注: それには 3 つの主要な依存関係が追加されています。つまり、システムは自動的に構成されており、kafka コアの依存関係 + テストの依存関係、およびその他の関連する補助的な依存関係 (例: lombok) です。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.succ</groupId>
<artifactId>SpringBootKafaka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBootKafaka</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 阿里巴巴 fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.3. application.ymlファイルに、kafka 関連の設定を追加します。
spring:
kafka:
# 指定 kafka 地址,我这里部署在的虚拟机,开发环境是Windows,kafkahost是虚拟机的地址, 若外网地址,注意修改为外网的IP( 集群部署需用逗号分隔)
bootstrap-servers: kafkahost:9092
consumer:
# 指定 group_id
group-id: group_id
auto-offset-reset: earliest
# 指定消息key和消息体的序列化方式
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
producer:
# 指定消息key和消息体的序列化方式
key-deserializer: org.apache.kafka.common.serialization.StringSerializer
value-deserializer: org.apache.kafka.common.serialization.StringSerializer
注: kafkahost エイリアスは個別に設定する必要があります。ヘルプが必要な場合は、クリックして入力してください。もちろん、ここに仮想マシンの IP アドレスを直接書き込むこともできます(開発環境は Windows で、kafka は仮想マシンなので、ここに localhost (127.0 .0.1 に相当)を書くことはできません。そうしないと、アクセスは Windows の localhost になり、仮想マシンの Kafka にはまったくアクセスできません)。
auto.offset.reset には設定できる値が 3 つあります。
最も早い:各パーティションの下に提出されたオフセットがある場合は、提出されたオフセットから消費を開始し、提出されたオフセットがない場合は先頭から消費を開始します。
最新:各パーティションの下に送信されたオフセットがある場合は、送信されたオフセットから消費を開始します。送信されたオフセットがない場合は、パーティションの下に新しく生成されたデータを消費します。
none:トピックの各パーティションに送信されたオフセットがある場合、消費はオフセットの後に開始されます。送信されたオフセットのないパーティションがある限り、例外がスローされます。
デフォルトでは、earlyerist を使用することをお勧めします。このパラメータを設定すると、エラーが発生した後に Kafka が再起動されます。未使用のオフセットが見つかった場合は、引き続き使用できます。最新の設定はメッセージが失われやすいです。kafka に問題があり、トピックに書き込まれたデータがまだある場合は、この時点で kafka を再起動します。この設定では、最新のオフセットから消費が開始され、途中で問題があるものは消費されます。無視されます。
注:詳しい構成情報については、下部にある拡張機能を参照してください。
2. コードの書き方
2.1、Order (順序) Entity Bean のエンコード
package model;
import lombok.*;
import java.time.LocalDateTime;
/**
* @create 2022-10-08 1:25
* @describe 订单类javaBean实体
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Order {
/**
* 订单id
*/
private long orderId;
/**
* 订单号
*/
private String orderNum;
/**
* 订单创建时间
*/
private LocalDateTime createTime;
}
2.2. KafkaProvider (メッセージプロバイダー)の記述
package com.succ.springbootkafaka.provider;
import com.alibaba.fastjson.JSONObject;
import com.succ.springbootkafaka1.model.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import java.time.LocalDateTime;
/**
* @create 2022-10-14 21:39
* @describe 话题的创建类,使用它向kafka中创建一个关于Order的订单主题
*/
@Component
@Slf4j
public class KafkaProvider {
/**
* 消息 TOPIC
*/
private static final String TOPIC = "shopping";
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
public void sendMessage(long orderId, String orderNum, LocalDateTime createTime) {
// 构建一个订单类
Order order = Order.builder()
.orderId(orderId)
.orderNum(orderNum)
.createTime(createTime)
.build();
// 发送消息,订单类的 json 作为消息体
ListenableFuture<SendResult<String, String>> future =
kafkaTemplate.send(TOPIC, JSONObject.toJSONString(order));
// 监听回调
future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
@Override
public void onFailure(Throwable throwable) {
log.info("## Send message fail ...");
}
@Override
public void onSuccess(SendResult<String, String> result) {
log.info("## Send message success ...");
}
});
}
}
2.3、KafkaConsumer (コンシューマ)コードの記述
package consumer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
/**
* @create 2022-10-08 1:25
* @describe 通过指定的话题和分组来消费对应的话题
*/
@Component
@Slf4j
public class KafkaConsumer {
@KafkaListener(topics = "shopping", groupId = "group_id") //这个groupId是在yml中配置的
public void consumer(String message) {
log.info("## consumer message: {}", message);
}
}
3. 単体テスト
3.1. 準備
3.1.1. Zookeeperの起動ステータスの表示
cdコマンドを使用して、zk インストール ディレクトリに移動します。
bin ディレクトリ内のZookeeper-server-start.sh起動スクリプトを使用して、 zk 単一ノード インスタンスを起動します。
bin/zookeeper-server-start.sh -daemon config/zookeeper.properties
この仮想マシン zk の基本構成が整っているため、直接起動できます ( zk のインストールについてヘルプが必要な場合は、クリックして開始してください)
#zkServer.sh status 查看服务状态
#zkServer.sh start 启动zk
#zkServer.sh stop 停掉zk
#zkServer.sh restart 重启zk
上図に示すように、zk の起動モードはスタンドアロン シングルトン モード (非クラスタ) で起動されています。
3.1.2、kafkaを起動する
cd コマンドを使用して、kafka インストールディレクトリの下の bin ディレクトリに移動します。
解凍ディレクトリに入り、 bin ディレクトリ内のkafka-server-start.shスクリプトを使用してKafka をバックグラウンドで起動します。
pwd
./kafka-server-start.sh ../config/server.properties
次の図に示すように、通常どおりに起動します。
リマインダー: Kafka の起動エラーでホスト名が認識されない問題の解決策は、クリックして入力してください。
java.net.UnknownHostException|java.net.Inet6AddressImpl.lookupAllHost での不明なエラー
3.1.3. Kafka の起動ステータスを表示する3つの方法
jps -ml #方式一,通过jps命令查看(尾部的-ml为非必须参数)
netstat -nalpt | grep 9092 #方式二,通过查看端口号查看
lsof -i:9092 #方式三
3.2、単体テストコードの作成
package com.succ.springbootkafaka;
import com.succ.springbootkafaka.provider.KafkaProvider;
import org.junit.jupiter.api.Test;//注意,这个junit用自带的就可以
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@SpringBootTest
class SpringBootKafakaApplicationTests {
@Autowired
private KafkaProvider kafkaProvider;
@Test
public void sendMessage() throws InterruptedException {
//如果这里打印为null,要么是zk或kafka没正常启动,此时进入linux分别查看他们状态接口,另外也需要排查一下你的yum文件配置的kafka的地址,最后排查自己的注解是否引入错误的package
System.out.println("是否为空??+"+kafkaProvider);
// 发送 1000 个消息
for (int i = 0; i < 1000; i++) {
long orderId = i+1;
String orderNum = UUID.randomUUID().toString();
kafkaProvider.sendMessage(orderId, orderNum, LocalDateTime.now());
}
TimeUnit.MINUTES.sleep(1);
}
}
3.3. テスト
3.3.1. 1000 メッセージを送信して、メッセージが正常に公開および消費できるかどうかを確認します。
コンソールのログは次のとおりです。
3.3.2. Kafkaのトピックリストを確認し、トピック「ショッピング」が正常に作成されているか確認する
kafka-topics.shスクリプトを実行して、 bin ディレクトリ内のトピック リストを表示します。
注: Kafka バージョンが2.2+= より高い場合は、次のコマンドを使用して表示します。
bin/kafka-topics.sh --list --bootstrap-server kafkahost:9092
上の図に示すように、作成したテーマショッピング が表示されます。
注: Kafka バージョンが2.2 より前の場合は、次のコマンドを使用して表示します。
bin/kafka-topics.sh --list --zookeeper kafkahost:2181
上記の kafkahost はvim /etc/hostで構成されており、IP はifconfigコマンドを通じて取得されます。
これまでのところ、テストは成功しています。
4. なぜ最初に zk を起動し、次に kafka を起動するのか
kafkaの動作はzk の起動に依存しているためです。具体的には、 kafka解凍ディレクトリの /conf/ ディレクトリ
に入ることができます。
cd /usr/src/kafka_2.13-3.3.1/config/ && ls
vi server.properties
その他のKafka チュートリアルについては、クリックして入力してください
5.仕上げ作業
1. Zookeeper を閉じる
zkServer.sh status
zkServer.sh stop
zkServer.sh status
2. カフカを閉じる
cd /usr/src/kafka_2.13-3.3.1/ && ls
jps
bin/kafka-server-stop.sh
jps
注:初めて kafka をインストールして使用する場合、shutdown コマンドは有効になりません。次のように、kafka の設定ファイルを入力して設定を変更する必要があります。
vim bin/kafka-server-stop.sh
以下の図でコードを見つけて変更します。
#PIDS=$(ps ax | grep ' kafka\.Kafka ' | grep java | grep -v grep | awk '{print $1}') PIDS=$(jps -lm | grep -i 'kafka.Kafka' |
awk '{print $1}')
変更されたコマンドの機能: jps -lm コマンドを使用してすべての Java プロセスをリストし、パイプラインを使用して grep -i 'kafka. take out で kafka プロセスをフィルターで除外します。
要約する
この記事では、小さなケースを通じて、最初に Spring Boot の Kafka への統合を紹介し、Spring Boot からのプロデューサー (Kafka へのトピックの作成) とコンシューマー (情報の消費) の呼び出しを完了して、Kafka への呼び出しを完了します。
もちろん、kafka の使い方はそれだけではありません。さらに詳細な紹介は、後ほど別のページで紹介します。
エピローグ
先人たちが通った道をたどり、後発者のためにピットを踏みます。
統合の過程では、必ず衝突や衝突に遭遇しますが、幸いなことに、私は皆さんと一緒に歩んでおり、その中で遭遇するいくつかの落とし穴は基本的に顕著です。
記事が悪くないと思ったらいいね、コレクト大歓迎です!
拡大
yumファイルに関するより詳細な設定
spring:
kafka:
bootstrap-servers: 172.101.203.33:9092
producer:
# 发生错误后,消息重发的次数。
retries: 0
#当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
batch-size: 16384
# 设置生产者内存缓冲区的大小。
buffer-memory: 33554432
# 键的序列化方式
key-serializer: org.apache.kafka.common.serialization.StringSerializer
# 值的序列化方式
value-serializer: org.apache.kafka.common.serialization.StringSerializer
# acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应。
# acks=1 : 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。
# acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。
acks: 1
consumer:
# 自动提交的时间间隔 在spring boot 2.X 版本中这里采用的是值的类型为Duration 需要符合特定的格式,如1S,1M,2H,5D
auto-commit-interval: 1S
# 该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该作何处理:
# latest(默认值)在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录)
# earliest :在偏移量无效的情况下,消费者将从起始位置读取分区的记录
auto-offset-reset: earliest
# 是否自动提交偏移量,默认值是true,为了避免出现重复数据和数据丢失,可以把它设置为false,然后手动提交偏移量
enable-auto-commit: false
# 键的反序列化方式
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 值的反序列化方式
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
listener:
# 在侦听器容器中运行的线程数。
concurrency: 5
#listner负责ack,每调用一次,就立即commit
ack-mode: manual_immediate
missing-topics-fatal: false
ノート
1. ZK/Zookeeper のダウンロードとインストール | true/false クラスターの迅速な構築 | 概要は非常に詳細です