從零開始搭建Kafka+SpringBoot分布式消息系統(tǒng)

前言

由于kafka強(qiáng)依賴于zookeeper,所以需先搭建好zookeeper集群。由于zookeeper是由java編寫的,需運(yùn)行在jvm上,所以首先應(yīng)具備java環(huán)境。(ps:默認(rèn)您的centos系統(tǒng)可聯(lián)網(wǎng),本教程就不教配置ip什么的了)(ps2:沒有wget的先裝一下:yum install wget)(ps3:人啊,就是要條理。東邊放一點(diǎn),西邊放一點(diǎn),過段時(shí)間就不知道自己裝在哪里了。本教程所有下載均放在/usr/local目錄下)(ps4:kafka可能有內(nèi)置zookeeper,感覺可以越過zookeeper教程,但是這里也配置出來了。我沒試過)

**文章首發(fā)公眾號:Java架構(gòu)師聯(lián)盟,每日更新技術(shù)好文**


一、配置jdk

因?yàn)閛racle 公司不允許直接通過wget 下載官網(wǎng)上的jdk包。所以你直接wget以下地址下載下來的是一個(gè)只有5k的網(wǎng)頁文件而已,并不是需要的jdk包。(壟斷地位就是任性)。(請通過java -version判斷是否自帶jdk,我的沒帶)

1、官網(wǎng)下載

下面是jdk8的官方下載地址:

https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8u211-later-5573849.html

2、上傳解壓

這里通過xftp上傳到服務(wù)器指定位置:/usr/local

對壓縮文件進(jìn)行解壓:

tar -zxvf jdk-8u221-linux-x64.tar.gz

對解壓后的文件夾進(jìn)行改名:

mv jdk1.8.0_221 jdk1.8

3、配置環(huán)境變量

vim /etc/profile

#java environment

export JAVA_HOME=/usr/local/jdk1.8

export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar

export PATH=$PATH:${JAVA_HOME}/bin

操作之后的界面如下:

運(yùn)行命令使環(huán)境生效

source /etc/profile

二、搭建zookeeper集群

1、下載zookeeper

創(chuàng)建zookeeper目錄,在該目錄下進(jìn)行下載:

mkdir /usr/local/zookeeper

這一步如果出現(xiàn)連接被拒絕時(shí)可多試幾次,我就是第二次請求才成功的。

wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz

等待下載完成之后解壓:

tar -zxvf zookeeper-3.4.6.tar.gz

重命名為zookeeper1

mv zookeeper-3.4.6 zookeeper1

cp -r zookeeper1 zookeeper2

cp -r zookeeper1 zookeeper3

2、創(chuàng)建data、logs文件夾

在zookeeper1目錄下創(chuàng)建

在data目錄下新建myid文件。內(nèi)容為1

3、修改zoo.cfg文件

cd /usr/local/zookeeper/zookeeper1/conf/

cp zoo_sample.cfg zoo.cfg

進(jìn)行過上面兩步之后,有zoo.cfg文件了,現(xiàn)在修改內(nèi)容為:

dataDir=/usr/local/zookeeper/zookeeper1/data

dataLogDir=/usr/local/zookeeper/zookeeper1/logs

server.1=192.168.233.11:2888:3888

server.2=192.168.233.11:2889:3889

server.3=192.168.233.11:2890:3890

4、搭建zookeeper2

首先,復(fù)制改名。

cd /usr/local/zookeeper/

cp -r zookeeper1 zookeeper2

然后修改具體的某些配置:

vim zookeeper2/conf/zoo.cfg

將下圖三個(gè)地方1改成2

vim zookeeper2/data/myid

同時(shí)將myid中的值改成2

5、搭建zookeeper3

同上,復(fù)制改名

cp -r zookeeper1 zookeeper3

vim zookeeper3/conf/zoo.cfg

修改為3

vim zookeeper3/data/myid

修改為3

6、測試zookeeper集群

cd /usr/local/zookeeper/zookeeper1/bin/

由于啟動(dòng)所需代碼比較多,這里簡單寫了一個(gè)啟動(dòng)腳本:

vim start

start的內(nèi)容如下

cd /usr/local/zookeeper/zookeeper1/bin/

./zkServer.sh start ../conf/zoo.cfg

cd /usr/local/zookeeper/zookeeper2/bin/

./zkServer.sh start ../conf/zoo.cfg

cd /usr/local/zookeeper/zookeeper3/bin/

./zkServer.sh start ../conf/zoo.cfg

下面是連接腳本:

vim login

login內(nèi)容如下:

./zkCli.sh -server 192.168.233.11:2181,192.168.233.11:2182,192.168.233.11:2183

腳本編寫完成,接下來啟動(dòng):

sh start

sh login

啟動(dòng)集群成功,如下圖:

這里zookeeper就告一段落了,由于zookeeper占用著輸入窗口,這里可以在xshell右鍵標(biāo)簽,新建ssh渠道。然后就可以在新窗口繼續(xù)操作kafka了!

三、搭建kafka集群

1、下載kafka

首先創(chuàng)建kafka目錄:

mkdir /usr/local/kafka

然后在該目錄下載

cd /usr/local/kafka/

wget https://archive.apache.org/dist/kafka/1.1.0/kafka_2.11-1.1.0.tgz

下載成功之后解壓:

tar -zxvf kafka_2.11-1.1.0.tgz

2、修改集群配置

首先進(jìn)入conf目錄下:

cd /usr/local/kafka/kafka_2.11-1.1.0/config

修改server.properties修改內(nèi)容:

broker.id=0

log.dirs=/tmp/kafka-logs

listeners=PLAINTEXT://192.168.233.11:9092

復(fù)制兩份server.properties

cp server.properties server2.properties

cp server.properties server3.properties

修改server2.properties

vim server2.properties

修改主要內(nèi)容為:

broker.id=1

log.dirs=/tmp/kafka-logs1

listeners=PLAINTEXT://192.168.233.11:9093

如上,修改server3.properties修改內(nèi)容為:

broker.id=2

log.dirs=/tmp/kafka-logs2

listeners=PLAINTEXT://192.168.233.11:9094

3、啟動(dòng)kafka

這里還是在bin目錄編寫一個(gè)腳本:

cd ../bin/

vim start

腳本內(nèi)容為:

./kafka-server-start.sh ../config/server.properties &

./kafka-server-start.sh ../config/server2.properties &

./kafka-server-start.sh ../config/server3.properties &

通過jps命令可以查看到,共啟動(dòng)了3個(gè)kafka。

4、創(chuàng)建Topic

cd /usr/local/kafka/kafka_2.11-1.1.0

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 1 --topic my-replicated-topic

kafka打印了幾條日志

在啟動(dòng)的zookeeper中可以通過命令查詢到這條topic!

ls /brokers/topics

查看kafka狀態(tài)

bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic my-replicated-topic

可以看到此時(shí)有三個(gè)節(jié)點(diǎn) 1 , 2 , 0

Leader 是1 ,因?yàn)榉謪^(qū)只有一個(gè) 所以在0上面,Replicas:主從備份是 1,2,0,ISR(in-sync):現(xiàn)在存活的信息也是 1,2,0

5、啟動(dòng)生產(chǎn)者

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic my-replicated-topic

由于不能按刪除,不能按左右鍵去調(diào)整,所以語句有些亂啊。em…

6、啟動(dòng)消費(fèi)者

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --from-beginning --topic my-replicated-topic

可以看出,啟動(dòng)消費(fèi)者之后就會(huì)自動(dòng)消費(fèi)。

在生產(chǎn)者又造了一條。

消費(fèi)者自動(dòng)捕獲成功!

四、集成springboot

先貼一張kafka兼容性目錄:

不滿足的話啟動(dòng)springboot的時(shí)候會(huì)拋異常的?。。s:該走的岔路我都走了o(╥﹏╥)o(我的kafka-clients是1.1.0,spring-kafka是2.2.2,中間那列暫時(shí)不用管)

回歸正題,搞了兩個(gè)小時(shí),終于搞好了,想哭…遇到的問題基本就是jar版本不匹配。上面的步驟我也都會(huì)相應(yīng)的去修改,爭取大家按照本教程一遍過!!!

1、pom文件

<?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.1.1.RELEASE</version>

? ? ? ? <relativePath/> <!-- lookup parent from repository -->

? ? </parent>

? ? <groupId>com.gzky</groupId>

? ? <artifactId>study</artifactId>

? ? <version>0.0.1-SNAPSHOT</version>

? ? <name>study</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-starter-test</artifactId>

? ? ? ? ? ? <scope>test</scope>

? ? ? ? ? ? <exclusions>

? ? ? ? ? ? ? ? <exclusion>

? ? ? ? ? ? ? ? ? ? <groupId>org.junit.vintage</groupId>

? ? ? ? ? ? ? ? ? ? <artifactId>junit-vintage-engine</artifactId>

? ? ? ? ? ? ? ? </exclusion>

? ? ? ? ? ? </exclusions>

? ? ? ? </dependency>

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>org.springframework.boot</groupId>

? ? ? ? ? ? <artifactId>spring-boot-starter-redis</artifactId>

? ? ? ? ? ? <version>1.3.8.RELEASE</version>

? ? ? ? </dependency>

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>redis.clients</groupId>

? ? ? ? ? ? <artifactId>jedis</artifactId>

? ? ? ? </dependency>

? ? ? ? <!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka -->

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>org.springframework.kafka</groupId>

? ? ? ? ? ? <artifactId>spring-kafka</artifactId>

? ? ? ? ? ? <version>2.2.0.RELEASE</version>

? ? ? ? </dependency>

? ? ? ? <!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->

? ? ? ? <dependency>

? ? ? ? ? ? <groupId>org.apache.kafka</groupId>

? ? ? ? ? ? <artifactId>kafka-clients</artifactId>

? ? ? ? </dependency>

? ? </dependencies>

? ? <build>

? ? ? ? <plugins>

? ? ? ? ? ? <plugin>

? ? ? ? ? ? ? ? <groupId>org.springframework.boot</groupId>

? ? ? ? ? ? ? ? <artifactId>spring-boot-maven-plugin</artifactId>

? ? ? ? ? ? </plugin>

? ? ? ? </plugins>

? ? </build>

</project>

pom文件中,重點(diǎn)是下面這兩個(gè)版本。

<parent>

? ? ? <groupId>org.springframework.boot</groupId>

? ? ? <artifactId>spring-boot-starter-parent</artifactId>

? ? ? <version>2.1.1.RELEASE</version>

? ? ? <relativePath/> <!-- lookup parent from repository -->

? </parent>

<dependency>

? ? ? <groupId>org.springframework.kafka</groupId>

? ? ? <artifactId>spring-kafka</artifactId>

? ? ? <version>2.2.0.RELEASE</version>

</dependency>

2、application.yml

spring:

? redis:

? ? cluster:

? ? ? #設(shè)置key的生存時(shí)間,當(dāng)key過期時(shí),它會(huì)被自動(dòng)刪除;

? ? ? expire-seconds: 120

? ? ? #設(shè)置命令的執(zhí)行時(shí)間,如果超過這個(gè)時(shí)間,則報(bào)錯(cuò);

? ? ? command-timeout: 5000

? ? ? #設(shè)置redis集群的節(jié)點(diǎn)信息,其中namenode為域名解析,通過解析域名來獲取相應(yīng)的地址;

? ? ? nodes: 192.168.233.11:9001,192.168.233.11:9002,192.168.233.11:9003,192.168.233.11:9004,192.168.233.11:9005,192.168.233.11:9006

? kafka:

? ? # 指定kafka 代理地址,可以多個(gè)

? ? bootstrap-servers: 192.168.233.11:9092,192.168.233.11:9093,192.168.233.11:9094

? ? producer:

? ? ? retries: 0

? ? ? # 每次批量發(fā)送消息的數(shù)量

? ? ? batch-size: 16384

? ? ? buffer-memory: 33554432

? ? ? # 指定消息key和消息體的編解碼方式

? ? ? key-serializer: org.apache.kafka.common.serialization.StringSerializer

? ? ? value-serializer: org.apache.kafka.common.serialization.StringSerializer

? ? consumer:

? ? ? # 指定默認(rèn)消費(fèi)者group id

? ? ? group-id: test-group

? ? ? auto-offset-reset: earliest

? ? ? enable-auto-commit: true

? ? ? auto-commit-interval: 100

? ? ? # 指定消息key和消息體的編解碼方式

? ? ? key-serializer: org.apache.kafka.common.serialization.StringSerializer

? ? ? value-serializer: org.apache.kafka.common.serialization.StringSerializer

server:

? port: 8085

? servlet:

? ? #context-path: /redis

? ? context-path: /kafka

沒有配置Redis的可以把Redis部分刪掉,也就是下圖:想學(xué)習(xí)配置Redis集群的可以參考:《Redis集群redis-cluster的搭建及集成springboot》

3、生產(chǎn)者

package com.gzky.study.utils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.kafka.core.KafkaTemplate;

import org.springframework.stereotype.Component;

/**

* kafka生產(chǎn)者工具類

*

* @author biws

* @date 2019/12/17

**/

@Component

public class KfkaProducer {

? ? private static Logger logger = LoggerFactory.getLogger(KfkaProducer.class);

? ? @Autowired

? ? private KafkaTemplate<String, String> kafkaTemplate;

? ? /**

? ? * 生產(chǎn)數(shù)據(jù)

? ? * @param str 具體數(shù)據(jù)

? ? */

? ? public void send(String str) {

? ? ? ? logger.info("生產(chǎn)數(shù)據(jù):" + str);

? ? ? ? kafkaTemplate.send("testTopic", str);

? ? }

}

4、消費(fèi)者

package com.gzky.study.utils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.kafka.annotation.KafkaListener;

import org.springframework.stereotype.Component;

/**

* kafka消費(fèi)者監(jiān)聽消息

*

* @author biws

* @date 2019/12/17

**/

@Component

public class KafkaConsumerListener {

? ? private static Logger logger = LoggerFactory.getLogger(KafkaConsumerListener.class);

? ? @KafkaListener(topics = "testTopic")

? ? public void onMessage(String str){

? ? ? ? //insert(str);//這里為插入數(shù)據(jù)庫代碼

? ? ? ? logger.info("監(jiān)聽到:" + str);

? ? ? ? System.out.println("監(jiān)聽到:" + str);

? ? }

}

5、對外接口

package com.gzky.study.controller;

import com.gzky.study.utils.KfkaProducer;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

/**

* kafka對外接口

*

* @author biws

* @date 2019/12/17

**/

@RestController

public class KafkaController {

? ? @Autowired

? ? KfkaProducer kfkaProducer;

? ? /**

? ? * 生產(chǎn)消息

? ? * @param str

? ? * @return

? ? */

? ? @RequestMapping(value = "/sendKafkaWithTestTopic",method = RequestMethod.GET)

? ? @ResponseBody

? ? public boolean sendTopic(@RequestParam String str){

? ? ? ? kfkaProducer.send(str);

? ? ? ? return true;

? ? }

}

6、postman測試

這里首先應(yīng)該在服務(wù)器啟動(dòng)監(jiān)聽器(kafka根目錄),下面命令必須是具體的服務(wù)器ip,不能是localhost,是我踩過的坑:

推薦此處重啟一下集群關(guān)閉kafka命令:

cd /usr/local/kafka/kafka_2.11-1.1.0/bin

./kafka-server-stop.sh ../config/server.properties &

./kafka-server-stop.sh ../config/server2.properties &

./kafka-server-stop.sh ../config/server3.properties &

此處應(yīng)該jps看一下,等待所有的kafka都關(guān)閉(關(guān)不掉的kill掉),再重新啟動(dòng)kafka:

./kafka-server-start.sh ../config/server.properties &

./kafka-server-start.sh ../config/server2.properties &

./kafka-server-start.sh ../config/server3.properties &

等待kafka啟動(dòng)成功后,啟動(dòng)消費(fèi)者監(jiān)聽端口:

cd /usr/local/kafka/kafka_2.11-1.1.0

bin/kafka-console-consumer.sh --bootstrap-server 192.168.233.11:9092 --from-beginning --topic testTopic

曾經(jīng)我亂輸?shù)臏y試信息全部被監(jiān)聽過來了!

啟動(dòng)springboot服務(wù)

然后用postman生產(chǎn)消息:

然后享受成果,服務(wù)器端監(jiān)聽成功。

項(xiàng)目中也監(jiān)聽成功!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,536評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內(nèi)容