易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 402|回复: 1
收起左侧

Kafka 快速搭建

[复制链接]
发表于 2022-12-30 09:08:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
在了解完 Kafka 的基本概念之后,我们通过搭建 Kafka 集群来进一步深刻认识一下 Kafka。
确保安装环境安装 Java 环境
在安装 Kafka 之前,先确保Linux 环境上是否有 Java 环境,使用 java -version 命令查看 Java 版本,推荐使用Jdk 1.8 ,如果没有安装 Java 环境的话,可以按照这篇文章进行安装(https://www.cnblogs.com/zs-notes/p/8535275.html
安装 Zookeeper 环境
Kafka 的底层使用 Zookeeper 储存元数据,确保一致性,所以安装 Kafka 前需要先安装 Zookeeper,Kafka 的发行版自带了 Zookeeper ,可以直接使用脚本来启动,不过安装一个 Zookeeper 也不费劲
Zookeeper 单机搭建
Zookeeper 单机搭建比较简单,直接从 https://www.apache.org/dyn/closer.cgi/zookeeper/ 官网下载一个稳定版本的 Zookeeper ,这里我使用的是 3.4.10,下载完成后,在 Linux 系统中的 /usr/local 目录下创建 zookeeper 文件夹,使用xftp 工具(xftp 和 xshell 工具都可以在官网 https://www.netsarang.com/zh/xshell/ 申请免费的家庭版)把下载好的 zookeeper 压缩包放到 /usr/local/zookeeper 目录下。
如果下载的是一个 tar.gz 包的话,直接使用 tar -zxvf zookeeper-3.4.10.tar.gz解压即可
如果下载的是 zip 包的话,还要检查一下 Linux 中是否有 unzip 工具,如果没有的话,使用 yum install unzip 安装 zip 解压工具,完成后使用 unzip zookeeper-3.4.10.zip 解压即可。
解压完成后,cd 到 /usr/local/zookeeper/zookeeper-3.4.10 ,创建一个 data 文件夹,然后进入到 conf 文件夹下,使用 mv zoo_sample.cfg zoo.cfg 进行重命名操作
然后使用 vi 打开 zoo.cfg ,更改一下dataDir = /usr/local/zookeeper/zookeeper-3.4.10/data ,保存。
进入bin目录,启动服务输入命令 ./zkServer.sh start 输出下面内容表示搭建成功
% E& _! B& @. E# v/ _9 d% `8 M
                               
登录/注册后可看大图
关闭服务输入命令,./zkServer.sh stop
$ {% q* H/ T0 h6 Z' V
                               
登录/注册后可看大图
使用 ./zkServer.sh status 可以查看状态信息。
Zookeeper 集群搭建准备条件
准备条件:需要三个服务器,这里我使用了CentOS7 并安装了三个虚拟机,并为各自的虚拟机分配了1GB的内存,在每个 /usr/local/ 下面新建 zookeeper 文件夹,把 zookeeper 的压缩包挪过来,解压,完成后会有 zookeeper-3.4.10 文件夹,进入到文件夹,新建两个文件夹,分别是 data 和 log 文件夹
注:上一节单机搭建中已经创建了一个data 文件夹,就不需要重新创建了,直接新建一个 log 文件夹,对另外两个新增的服务需要新建这两个文件夹。
设置集群
新建完成后,需要编辑 conf/zoo.cfg 文件,三个文件的内容如下
1$ A, c% L, q8 ?, V$ w# ^6 z* U
2
. K( g0 P5 k' l3 H3
0 _( `% Y( u/ N& Z8 l; F: c0 m4) ~6 H( q6 @0 S& O
5
4 I- R6 I! V  c9 S6
$ E8 {' ]" J# z0 I% P% Q' w73 r3 X3 u5 k$ v5 N% D
8
/ W# Z4 Z6 B* X1 c3 y9
tickTime=2000initLimit=10syncLimit=5dataDir=/usr/local/zookeeper/zookeeper-3.4.10/datadataLogDir=/usr/local/zookeeper/zookeeper-3.4.10/logclientPort=12181server.1=192.168.1.7:12888:13888server.2=192.168.1.8:12888:13888server.3=192.168.1.9:12888:13888
0 g0 h7 R  p  z; N% S/ o! Y1 S

0 e/ W) ]/ x5 ]0 ?4 X  d8 Y
server.1 中的这个 1 表示的是服务器的标识也可以是其他数字,表示这是第几号服务器,这个标识要和下面我们配置的 myid 的标识一致可以。
192.168.1.7:12888:13888 为集群中的 ip 地址,第一个端口表示的是 master 与 slave 之间的通信接口,默认是 2888,第二个端口是leader选举的端口,集群刚启动的时候选举或者leader挂掉之后进行新的选举的端口,默认是 3888
现在对上面的配置文件进行解释
tickTime: 这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
syncLimit: 这个配置项标识 Leader 与Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是5*2000=10秒
dataDir: 快照日志的存储路径
dataLogDir: 事务日志的存储路径,如果不配置这个那么事务日志会默认存储到dataDir指定的目录,这样会严重影响zk的性能,当zk吞吐量较大的时候,产生的事务日志、快照日志太多
clientPort: 这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
创建 myid 文件
在了解完其配置文件后,现在来创建每个集群节点的 myid ,我们上面说过,这个 myid 就是 server.1 的这个 1 ,类似的,需要为集群中的每个服务都指定标识,使用 echo 命令进行创建
1
) G% S: D% S" G* f4 Y2
+ Y! D6 \" d. ?; @4 P/ w! v7 k3/ I4 t0 v5 M( k" Q$ n& Z' ^+ f
4
+ C9 D% ~. v/ a6 x5& b4 @" v0 `) \  L
6
# server.1echo "1" > /usr/local/zookeeper/zookeeper-3.4.10/data/myid# server.2echo "2" > /usr/local/zookeeper/zookeeper-3.4.10/data/myid# server.3echo "3" > /usr/local/zookeeper/zookeeper-3.4.10/data/myid

$ @9 |8 g" B. [3 _# t8 Z

3 D0 v. N; ^7 H3 D$ m; D; z, w- `启动服务并测试
配置完成,为每个 zk 服务启动并测试,我在 windows 电脑的测试结果如下
启动服务(每台都需要执行)
19 W0 q$ i- ~. _& k+ V2 a5 a
2
cd /usr/local/zookeeper/zookeeper-3.4.10/bin./zkServer.sh start
' g6 w  X: n  t7 b5 S/ }

. D% o/ \, b' x: v+ r0 ~
检查服务状态
使用 ./zkServer.sh status 命令检查服务状态
192.168.1.7 — follower
( {+ E5 f2 ~: }6 j9 i, w
                               
登录/注册后可看大图
192.168.1.8 — leader
7 v# u0 ]+ N1 ?8 [$ c
                               
登录/注册后可看大图
192.168.1.9 — follower

  {3 `+ d8 n8 ?7 X- I  a  G2 H! a                               
登录/注册后可看大图
zk集群一般只有一个leader,多个follower,主一般是相应客户端的读写请求,而从主同步数据,当主挂掉之后就会从follower里投票选举一个leader出来。
Kafka 集群搭建准备条件
在 /usr/local 下新建 kafka 文件夹,然后把下载完成的 tar.gz 包移到 /usr/local/kafka 目录下,使用 tar -zxvf 压缩包 进行解压,解压完成后,进入到 kafka_2.12-2.3.0 目录下,新建 log 文件夹,进入到 config 目录下
我们可以看到有很多 properties 配置文件,这里主要关注 server.properties 这个文件即可。

3 R0 p" J2 x( T) Z2 u                               
登录/注册后可看大图
kafka 启动方式有两种,一种是使用 kafka 自带的 zookeeper 配置文件来启动(可以按照官网来进行启动,并使用单个服务多个节点来模拟集群http://kafka.apache.org/quickstart#quickstart_multibroker),一种是通过使用独立的zk集群来启动,这里推荐使用第二种方式,使用 zk 集群来启动
修改配置项
需要为每个服务都修改一下配置项,也就是server.properties, 需要更新和添加的内容有
1
5 S: C% |" ]$ ]7 j5 o4 P2: V- \" P& T9 T5 C
30 c) i/ d  w9 u# s
4; k5 w6 m% [3 e$ [. u+ ]3 h
5  E2 i' ^# x: u
62 ]" g1 Q/ R9 s% e
72 J7 F! _0 w( n
84 `$ ^, r# p8 B, j4 u; d" v; b
9' h8 {( X3 }  \1 g, x# V" c
10
broker.id=0 //初始是0,每个 server 的broker.id 都应该设置为不一样的,就和 myid 一样 我的三个服务分别设置的是 1,2,3log.dirs=/usr/local/kafka/kafka_2.12-2.3.0/log#在log.retention.hours=168 下面新增下面三项message.max.byte=5242880default.replication.factor=2replica.fetch.max.bytes=5242880#设置zookeeper的连接端口zookeeper.connect=192.168.1.7:2181,192.168.1.8:2181,192.168.1.9:2181
) y& l9 Y( A& z% L4 b* @/ Z

# @0 `* [( L, O* c! {; u
配置项的含义
1* q3 \: y- h7 V. }0 c, W
2) u4 i* e! B, u# n6 N
39 H9 G' ^4 z, e8 P9 z9 V1 ^2 J
43 P, z- Z! Y8 e" i! j8 P0 P
53 |6 k+ f9 X+ l/ d
6. `3 @! p9 a$ O$ a& L# J
7
: g4 [0 z, P9 ^; T9 n7 M87 I8 Z( Y: t0 _# ^
98 Q: z; }9 S- {2 P8 _
10* y4 Q2 d, s& e! t- {4 L% l: w' l  @7 P
11% |" i1 S* B, {$ R( |8 t: ~
12
2 e0 \; D7 k  i/ I9 I13
  F9 b" g( Q* ]# i2 f14
# h, ]: K: B0 ^/ X+ H15* _) b6 B+ i+ K$ b( G7 \- t$ c
163 g; U+ C: z* h3 k' k
17# J: T# b1 t6 V$ x' l% `; j
18
broker.id=0  #当前机器在集群中的唯一标识,和zookeeper的myid性质一样port=9092 #当前kafka对外提供服务的端口默认是9092host.name=192.168.1.7 #这个参数默认是关闭的,在0.8.1有个bug,DNS解析问题,失败率的问题。num.network.threads=3 #这个是borker进行网络处理的线程数num.io.threads=8 #这个是borker进行I/O处理的线程数log.dirs=/usr/local/kafka/kafka_2.12-2.3.0/log #消息存放的目录,这个目录可以配置为“,”逗号分割的表达式,上面的num.io.threads要大于这个目录的个数这个目录,如果配置多个目录,新创建的topic他把消息持久化的地方是,当前以逗号分割的目录中,那个分区数最少就放那一个socket.send.buffer.bytes=102400 #发送缓冲区buffer大小,数据不是一下子就发送的,先回存储到缓冲区了到达一定的大小后在发送,能提高性能socket.receive.buffer.bytes=102400 #kafka接收缓冲区大小,当数据到达一定大小后在序列化到磁盘socket.request.max.bytes=104857600 #这个参数是向kafka请求消息或者向kafka发送消息的请请求的最大数,这个值不能超过java的堆栈大小num.partitions=1 #默认的分区数,一个topic默认1个分区数log.retention.hours=168 #默认消息的最大持久化时间,168小时,7天message.max.byte=5242880  #消息保存的最大值5Mdefault.replication.factor=2  #kafka保存消息的副本数,如果一个副本失效了,另一个还可以继续提供服务replica.fetch.max.bytes=5242880  #取消息的最大直接数log.segment.bytes=1073741824 #这个参数是:因为kafka的消息是以追加的形式落地到文件,当超过这个值的时候,kafka会新起一个文件log.retention.check.interval.ms=300000 #每隔300000毫秒去检查上面配置的log失效时间(log.retention.hours=168 ),到目录查看是否有过期的消息如果有,删除log.cleaner.enable=false #是否启用log压缩,一般不用启用,启用的话可以提高性能zookeeper.connect=192.168.1.7:2181,192.168.1.8:2181,192.168.1.9:2181 #设置zookeeper的连接端口
* w) Y/ x4 O9 Q& A% d0 g8 K
  w# e' V# V4 A; S' n- m6 B
启动 Kafka 集群并测试
  • 启动服务,进入到 /usr/local/kafka/kafka_2.12-2.3.0/bin 目录下
    / _9 z( C- J0 t% @
1
8 A& V" `4 F, T' K  Z2
# 启动后台进程./kafka-server-start.sh -daemon ../config/server.properties
# q9 \$ Z3 d" q2 A1 i/ b

' N' Z3 l9 Z# [6 t' t
  • 检查服务是否启动5 j% i7 K$ d- Q6 w9 b5 {5 k* [1 w
1
8 I+ O# Z& d; N8 c" s' M! d; s20 B5 I0 }- ^* G4 ]. d1 a- g2 m4 \
31 c3 w( N2 L. O. Z7 h  p  |1 V
4
# 执行命令 jps6201 QuorumPeerMain7035 Jps6972 Kafka

  F( x% S+ \' y% ^4 n* r9 w2 s4 t
' u* N/ ^& N( P$ l' j  l  K
  • kafka 已经启动
  • 创建 Topic 来验证是否创建成功
    ( X8 `, E. B5 N
1
' {, A( `1 p: ]& `( c% C3 n2 {2
# cd .. 往回退一层 到 /usr/local/kafka/kafka_2.12-2.3.0 目录下bin/kafka-topics.sh --create --zookeeper 192.168.1.7:2181 --replication-factor 2 --partitions 1 --topic cxuan
9 S# Z. W# X1 z2 \2 c6 i
3 H  L+ k& s( @( H1 L% W& j
对上面的解释
–replication-factor 2 复制两份
–partitions 1 创建1个分区
–topic 创建主题
查看我们的主题是否出创建成功
1
bin/kafka-topics.sh --list --zookeeper 192.168.1.7:2181

! W# @1 e* Q  J- B
& |* K3 S0 C) ^) K% G* u

5 |  L! ~9 Q' E: G& o, c$ ^                               
登录/注册后可看大图
启动一个服务就能把集群启动起来
在一台机器上创建一个发布者
1, q7 m6 z: s$ `1 E
2
# 创建一个broker,发布者./kafka-console-producer.sh --broker-list 192.168.1.7:9092 --topic cxuantopic
' R5 a+ a/ P7 p2 V% M: \6 J3 d) S
  G9 V: v" M  B8 a5 Y9 l
在一台服务器上创建一个订阅者
1
+ i# c" [# ]/ t9 E2 Y! Y2
# 创建一个consumer, 消费者bin/kafka-console-consumer.sh --bootstrap-server 192.168.1.7:9092 --topic cxuantopic --from-beginning
1 Y$ P5 S1 ^7 S5 J! a: Z$ g
2 T: b* C' B8 }8 l/ R8 J  @
注意:这里使用 –zookeeper 的话可能出现 zookeeper is not a recognized option 的错误,这是因为 kafka 版本太高,需要使用 --bootstrap-server 指令
测试结果
发布

% {4 Y9 _( W% X0 O1 \3 d" s                               
登录/注册后可看大图
消费
! i0 M! p: U6 c2 r; l, ~
                               
登录/注册后可看大图
其他命令
显示 topic
1
5 y* T4 G9 U2 K% _2 o+ l9 r% S2! y& |( s, q$ @; ]  M
33 X; |( t$ l& _% M) H7 F& z
4
bin/kafka-topics.sh --list --zookeeper 192.168.1.7:2181# 显示cxuantopic
7 Y9 l* ~6 O( S1 M

- }# C# y* i  \- z7 ]* h) x
查看 topic 状态
1) ?" }2 r4 S( ], L4 {/ A
2
, f9 V8 ]# P# b5 m3
' q( P9 M+ m: @; x, I$ P! T44 I( {' w- Y# y- o' ^
5& W% Y' J' C% a- V3 N0 e
6" w* Z8 a9 R  n7 ]3 ~, c
7; n. I2 ]7 @& j+ I% O
8
bin/kafka-topics.sh --describe --zookeeper 192.168.1.7:2181 --topic cxuantopic# 下面是显示的详细信息Topic:cxuantopic PartitionCount:1 ReplicationFactor:2 Configs:Topic: cxuantopic Partition: 0 Leader: 1 Replicas: 1,2 Isr: 1,2# 分区为为1  复制因子为2   主题 cxuantopic 的分区为0 # Replicas: 0,1   复制的为1,2

9 |1 y* C4 R9 g4 i# m$ C1 I& `
8 l/ m' R' b* e- g( t/ M4 ^
Leader 负责给定分区的所有读取和写入的节点,每个节点都会通过随机选择成为 leader。
Replicas 是为该分区复制日志的节点列表,无论它们是 Leader 还是当前处于活动状态。
Isr 是同步副本的集合。它是副本列表的子集,当前仍处于活动状态并追随Leader。
至此,kafka 集群搭建完毕。
验证多节点接收数据
刚刚我们都使用的是 相同的ip 服务,下面使用其他集群中的节点,验证是否能够接受到服务
在另外两个节点上使用
1
bin/kafka-console-consumer.sh --bootstrap-server 192.168.1.7:9092 --topic cxuantopic --from-beginning
6 ]- x/ l! [+ c4 Y  _% s

, b! P0 ^( g/ I! @6 C( M
然后再使用 broker 进行消息发送,经测试三个节点都可以接受到消息。
配置详解
在搭建 Kafka 的时候我们简单介绍了一下 server.properties 中配置的含义,现在我们来详细介绍一下参数的配置和概念
常规配置
这些参数是 kafka 中最基本的配置
  • broker.id
    . w- C' e, q! N- p+ }
每个 broker 都需要有一个标识符,使用 broker.id 来表示。它的默认值是 0,它可以被设置成其他任意整数,在集群中需要保证每个节点的 broker.id 都是唯一的。
  • port' s* y: ?+ \1 Z7 o0 U9 @' F* ~2 e! e( Q
如果使用配置样本来启动 kafka ,它会监听 9092 端口,修改 port 配置参数可以把它设置成其他任意可用的端口。
  • zookeeper.connect0 X1 x0 M1 h8 K) y5 F& c5 w$ l
用于保存 broker 元数据的地址是通过 zookeeper.connect 来指定。 localhost:2181 表示运行在本地 2181 端口。该配置参数是用逗号分隔的一组 hostname:port/path 列表,每一部分含义如下:
hostname 是 zookeeper 服务器的服务名或 IP 地址
port 是 zookeeper 连接的端口
/path 是可选的 zookeeper 路径,作为 Kafka 集群的 chroot 环境。如果不指定,默认使用跟路径
  • log.dirs7 \8 B7 o! x% s/ x% P8 ]
Kafka 把消息都保存在磁盘上,存放这些日志片段的目录都是通过 log.dirs 来指定的。它是一组用逗号分隔的本地文件系统路径。如果指定了多个路径,那么 broker 会根据 “最少使用” 原则,把同一分区的日志片段保存到同一路径下。要注意,broker 会向拥有最少数目分区的路径新增分区,而不是向拥有最小磁盘空间的路径新增分区。
  • num.recovery.threads.per.data.dir/ R7 z$ {' y1 R* S; k7 |+ j
对于如下 3 种情况,Kafka 会使用可配置的线程池来处理日志片段
服务器正常启动,用于打开每个分区的日志片段;
服务器崩溃后启动,用于检查和截断每个分区的日志片段;
服务器正常关闭,用于关闭日志片段
默认情况下,每个日志目录只使用一个线程。因为这些线程只是在服务器启动和关闭时会用到,所以完全可以设置大量的线程来达到井行操作的目的。特别是对于包含大量分区的服务器来说,一旦发生崩愤,在进行恢复时使用井行操作可能会省下数小时的时间。设置此参数时需要注意,所配置的数字对应的是 log.dirs 指定的单个日志目录。也就是说,如果 num.recovery.threads.per.data.dir 被设为 8,并且 log.dir 指定了 3 个路径,那么总共需要 24 个线程。
  • auto.create.topics.enable
    ' f5 ~. o" A( ?* |) j. {: {6 Y. c
默认情况下,Kafka 会在如下 3 种情况下创建主题
当一个生产者开始往主题写入消息时
当一个消费者开始从主题读取消息时
当任意一个客户向主题发送元数据请求时
  • delete.topic.enable
    ! E* L) Q$ g& ?, f. S5 j8 p
如果你想要删除一个主题,你可以使用主题管理工具。默认情况下,是不允许删除主题的,delete.topic.enable 的默认值是 false 因此你不能随意删除主题。这是对生产环境的合理性保护,但是在开发环境和测试环境,是可以允许你删除主题的,所以,如果你想要删除主题,需要把 delete.topic.enable 设为 true。
主题默认配置
Kafka 为新创建的主题提供了很多默认配置参数,下面就来一起认识一下这些参数
  • num.partitions2 ~. f, i. B. ], C
num.partitions 参数指定了新创建的主题需要包含多少个分区。如果启用了主题自动创建功能(该功能是默认启用的),主题分区的个数就是该参数指定的值。该参数的默认值是 1。要注意,我们可以增加主题分区的个数,但不能减少分区的个数。
  • default.replication.factor
    3 s$ i! a* [2 }8 s5 v6 B
这个参数比较简单,它表示 kafka保存消息的副本数,如果一个副本失效了,另一个还可以继续提供服务default.replication.factor 的默认值为1,这个参数在你启用了主题自动创建功能后有效。
  • log.retention.ms; {$ e7 D% C: Q/ S; N, p, j
Kafka 通常根据时间来决定数据可以保留多久。默认使用 log.retention.hours 参数来配置时间,默认是 168 个小时,也就是一周。除此之外,还有两个参数 log.retention.minutes 和 log.retentiion.ms 。这三个参数作用是一样的,都是决定消息多久以后被删除,推荐使用 log.retention.ms。
  • log.retention.bytes
    3 a  p% _9 E" m# ~
另一种保留消息的方式是判断消息是否过期。它的值通过参数 log.retention.bytes 来指定,作用在每一个分区上。也就是说,如果有一个包含 8 个分区的主题,并且 log.retention.bytes 被设置为 1GB,那么这个主题最多可以保留 8GB 数据。所以,当主题的分区个数增加时,整个主题可以保留的数据也随之增加。
  • log.segment.bytes
    3 h! ~+ X* a9 O& y5 E/ a7 v" |, {
上述的日志都是作用在日志片段上,而不是作用在单个消息上。当消息到达 broker 时,它们被追加到分区的当前日志片段上,当日志片段大小到达 log.segment.bytes 指定上限(默认为 1GB)时,当前日志片段就会被关闭,一个新的日志片段被打开。如果一个日志片段被关闭,就开始等待过期。这个参数的值越小,就越会频繁的关闭和分配新文件,从而降低磁盘写入的整体效率。
  • log.segment.ms
      O' Q6 {) ^  z& Y/ J9 a
上面提到日志片段经关闭后需等待过期,那么 log.segment.ms 这个参数就是指定日志多长时间被关闭的参数和,log.segment.ms 和 log.retention.bytes 也不存在互斥问题。日志片段会在大小或时间到达上限时被关闭,就看哪个条件先得到满足。
  • message.max.bytes
    : c1 J0 W$ G3 [( s  c
broker 通过设置 message.max.bytes 参数来限制单个消息的大小,默认是 1000 000, 也就是 1MB,如果生产者尝试发送的消息超过这个大小,不仅消息不会被接收,还会收到 broker 返回的错误消息。跟其他与字节相关的配置参数一样,该参数指的是压缩后的消息大小,也就是说,只要压缩后的消息小于 mesage.max.bytes,那么消息的实际大小可以大于这个值
这个值对性能有显著的影响。值越大,那么负责处理网络连接和请求的线程就需要花越多的时间来处理这些请求。它还会增加磁盘写入块的大小,从而影响 IO 吞吐量。

- z" S; ?$ k" B+ {
 楼主| 发表于 2022-12-30 09:09:23 | 显示全部楼层
1、软件下载1.1 kakfa 下载
地址:http://kafka.apache.org/downloads3 I/ k4 R7 w  w8 Q" h5 J0 s

0 a: J7 [$ \4 i# t

' d8 s( e* Q+ M4 u                               
登录/注册后可看大图
: ?( ]; N8 l: o, j* P
$ c/ F) x( N# W8 g
1.2 zookeeper 下载
(1)因为 kafka 要依赖于 zookeeper 做调度,kafka 中实际自带的有 kafka,但是一般建议使用独立的 zookeeper,方便后续升级及公用。

* H; F' m( B" Q( F) d4 W( S% x4 Y, i
(2)下载地址:

7 Y3 M/ h: S% b
http://zookeeper.apache.org/
. b* ?- Q' {5 P, o% Q# K) u
  r; ^- G) U8 J1 H- s% g! E$ O0 ^
$ I7 l( B9 x) b* |8 r
                               
登录/注册后可看大图
# X3 X4 n, N" z. E$ K! w; Y( e
( b- I4 W0 c7 Y+ T
1.3 下载说明
文件都不大,zk 是 9m 多,kafka 是 50 多兆
- v$ `3 B' x& E5 \5 ]0 v1 V+ y

% }+ j4 X( a# O                               
登录/注册后可看大图
- P, E, ?3 }4 E% Q/ |
  T2 `- x; D! {9 }) m; w
2、 kafka 单机部署及集群部署
**说明:**北游在本地弄了三台虚拟机,ip 分别为:

6 Z: w0 h6 k: S$ U/ ~! b" G1 F0 a( w- e) w1 i
4 d; x. P/ [" o7 A& e8 t
192.168.85.158192.168.85.168192.168.85.178' h' A1 J" K; ]- J
9 a& c6 F! P' _7 _, V9 s. p+ i
8 }, t- ?# a; b1 b0 U
# m( Y9 r, a1 T! e! U1 n! V4 c% T

  |  J: U8 w  I
5 w- Y7 \# F1 N  e8 I" @! H3 A
; U9 {7 p, u+ o; `- Q
" \' k6 K' O7 M! o% q4 l/ [9 T. d3 u/ y+ B, g% F  v- @

% e, c+ Q0 ?" r- p
& F7 ?5 D3 g  H复制代码7 A* \" W: O  J1 h' L; r
5 @: Y7 m# G# u$ \6 L3 e: ^

. G( {$ \5 Y1 z
/ Z" C' J% A3 }5 c& N9 R7 Q+ u3 a& A' y& t, u2 h7 `

% B; Z2 O( Z! a- C+ n1 p  c. h
: b+ r. B* G; M# G$ _9 T; A
4 x% k/ p2 d, W2 W$ E
2.1 单机部署
(1)上传 jar 包,就不再新建用户了,直接在 root 账户下执行,将 kafka 和 zookeeper 的 tar 包上传到/root/tools 目录下。

" u; i) I3 B* e4 j
(2)解压

% f4 H3 v( p$ A* c' q& M/ |* C
2 q2 S2 l  P) v8 V4 V, ~

3 K0 A1 p  V, `2 H' f7 N. i[root@ruanjianlaowang158 tools]# tar -zxvf kafka_2.12-2.4.1.tgz [root@ruanjianlaowang158 tools]# tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz  ! p; w2 p" {* K
9 ]# [3 K, o* A' N
( K9 {8 ~9 ]; c. `0 k! X7 i
0 A- v7 A+ v$ Q, ]2 ^0 z, g

' {. H  l/ K, ~" U  e3 `+ }9 a/ Y8 x: N
/ b5 @2 q9 i$ d2 U0 L! l) a
+ g% k& v. l) L8 g* g0 R

5 B: f/ v# i2 j, q$ ?* I4 z1 o: U# e9 H; k! U* `: L( \
5 e- F' @7 J6 v" I3 A$ Y
复制代码  A: t/ s8 s% o3 l. @; J
2 |. j* r) J, l6 |
& z7 @- x4 d1 R# b: r
$ W; I/ b% l5 |
( g% @' W3 g# L- W& b( |7 S
: ~6 V( U2 ]$ f, j
8 Y- h: K8 P/ D( ~
$ O! d; |1 g- S" @9 U" c1 N
(3)配置 zookeeper 及启动
6 E4 H5 X* T, c) o7 l
* R5 i' \5 V" a# x6 B( M9 m
! s4 t4 h5 e- S6 m* A
[root@ruanjianlaowang158 apache-zookeeper-3.5.7-bin]# cd /root/tools/apache-zookeeper-3.5.7-bin#北游,首先创建个空文件夹,在接下来的配置文件中配置[root@ruanjianlaowang158 apache-zookeeper-3.5.7-bin]# mkdir data[root@ruanjianlaowang158 conf]# cd /root/tools/apache-zookeeper-3.5.7-bin/conf[root@ruanjianlaowang158 conf]# cp zoo_sample.cfg  zoo.cfg [root@ruanjianlaowang158 conf]# vi  zoo.cfg #单机只改一个值,保存退出。#dataDir=/tmp/zookeeperdataDir=/root/tools/apache-zookeeper-3.5.7-bin/data/ @3 S/ {3 ~( c
#启动zookeeper[root@ruanjianlaowang158 bin]# cd /root/tools/apache-zookeeper-3.5.7-bin/bin[root@ruanjianlaowang158 bin]# ./zkServer.sh  start0 z& `, A+ s; B  f/ c, x- K( Y* x

2 R$ T. Q1 N1 c7 b# l2 F' c; ~/ E2 {! h0 U$ \& g/ K% J
' _# ?$ n% a: ~. ]6 x
/ ?( ~' s6 ]$ s6 E2 o* Q

% a, a: ?) x+ l
+ Y; v7 M2 v3 W& T9 d7 i
# h! Q8 _& `, i3 ?  V- T! z) ~4 W' V4 U1 k1 r

' f2 O3 ?% Q: F2 k) p% @7 k2 i4 y
7 F3 L: R; ?1 q3 N& {复制代码0 l  {! l( O& o4 D5 O
/ W; _* ]$ Z, z2 n

; s9 s6 d4 Z. @3 Y9 p6 r" y# q/ t4 C1 W" |

$ x% `4 o2 \, S: a; m+ O0 E
" ^/ @5 b8 O: ~
/ C4 |$ t$ f  @2 F
- Q: E- \4 q; D- Z5 q; W* \. g; p5 \1 U+ @3 J- \5 @6 s

% {& L: E6 R/ T
: @  O8 L$ ^9 }' r/ `
2 O% f' i# n5 K! I" ^+ t4 P  f9 ?
7 p; d+ I6 v8 Q' C; _! E# i  \
! |0 @1 F. [: C4 q  f

: }4 [2 D7 t3 p- h8 |! y
6 F3 v, x) L# t  B

( N! q; ~1 n4 w" O& M) t3 e6 \0 S: U" l2 x4 n4 {9 P
(4)配置 kafka 及启动

; I$ P. c7 ]& B5 `! f
) Z1 H) @2 h" J4 Q4 x& L

" b  |( O  X4 _+ e8 M[root@ruanjianlaowang158 kafka_2.12-2.4.1]# cd /root/tools/kafka_2.12-2.4.1* B. Z: F5 h% k9 C; H3 [
#北游,新建个空文件夹[root@ruanjianlaowang158 kafka_2.12-2.4.1]# mkdir data
5 k" m* G8 ~" }& G! o) Q; E9 X4 `#北游,更改配置文件[root@ruanjianlaowang158 config]# cd /root/tools/kafka_2.12-2.4.1/config[root@ruanjianlaowang158 config]# vi server.properties
2 a8 V$ b! Y* i; X1 P#需要改3个值#log.dirs=/tmp/kafka-logslog.dirs=/root/tools/kafka_2.12-2.4.1/data#listeners = PLAINTEXT://your.host.name:9092listeners=PLAINTEXT://192.168.85.158:9092#zookeeper.connect=localhost:2181zookeeper.connect=192.168.85.158:2181
* W( r  C& B4 R- h#启动kafka[root@ruanjianlaowang158 bin]# cd /root/tools/kafka_2.12-2.4.1/bin[root@ruanjianlaowang158 bin]# ./zookeeper-server-start.sh ../config/server.properties &
7 [3 |7 N% N; D5 R- X% `5 V- h7 T! C7 b6 \: s
, o$ D9 B4 m% O
+ C8 ~" x& L$ U9 P6 l

, O" a4 J8 N6 J* N
1 d0 s* @* b( U+ F+ K
* `: r2 W( J  i7 p8 R# k0 @. _3 g
8 _7 X& J/ V  b, ?
" L0 O$ ^$ _) T( b- {0 O

. P0 d% U. A$ m4 s  x, a$ a' D复制代码' p* u1 g, v& v$ `
5 H9 {/ J" F( d5 h) y7 \

% ?3 o5 b! l- M: X! e
7 `* w& E; c) P) S. u0 I- O
% s; H) ?7 Z5 O6 Q: p3 H: y! i9 L$ z, I8 T& J+ Y
4 w2 k, N% u4 I/ O* i6 ~% n
4 m' `9 v8 N: F3 H4 e, f

' @4 A# C$ q7 N% B. \! _- F" X6 N* N0 ~: y
& y$ F1 _9 S/ ], k( G. r% H

# R; |# S" U( i" F% A% `3 t6 K$ c6 E" a9 \% C
6 F& P: C. f% a, O7 D

1 K' X, X, h( L) w; a% Y) m, b
* w& n( k0 n( \4 T
$ x5 J7 u. I" r1 p8 {8 o/ R
6 S) F- @$ d" O- ?9 ^/ [$ X! U2 ?7 e, U/ n/ A: A7 l
0 S* i% x/ q1 ^
: Y  D" E- u* N; m# l

5 q9 s$ w' K1 ~; ?/ f+ Z  A% {
/ }+ F3 p$ q& \) {! Z) m
3 o+ P, O3 j2 J: K) A. @
& s- [; v9 a) c% d0 g: }

0 I0 y0 I& I1 e# M7 i2 N
启动完毕,单机验证就不验证了,直接在集群中进行验证。
2.2 集群部署
(1)集群方式,首先把上面的单机模式,再在 192.168.85.168 和 192.168.85.178 服务器上先解压配置一遍。
. J. Z0 K' ^: [+ F2 a! S
(2)zookeeper 是还是更改 zoo.cfg
( b# A3 M# N) L+ M
158,168,178 三台服务器一样:
, f5 f% R( N, K& X

; z9 L( O2 G. E/ z& v8 @3 e
$ O$ R/ }5 r  n/ J2 c
[root@ruanjianlaowang158 conf]# cd /root/tools/apache-zookeeper-3.5.7-bin/conf
. v8 g  p  Q; ~# y- y1 a[root@ruanjianlaowang158 conf]# vi zoo.cfg#其他不变,最后面新加,三行,三台服务器配置一样,北游server.1=192.168.85.158:2888:3888server.2=192.168.85.168:2888:3888server.3=192.168.85.178:2888:3888
  Z( r3 a8 w+ z' \' v* K, s/ V% n158服务器执行:echo "1" > /root/tools/apache-zookeeper-3.5.7-bin/data/myid168服务器执行:echo "2" > /root/tools/apache-zookeeper-3.5.7-bin/data/myid178服务器执行:echo "3" > /root/tools/apache-zookeeper-3.5.7-bin/data/myid( k1 v, q- ~- m) |9 v

: d, _, A- U1 [9 b, A0 ^+ U, n6 z) [. @0 q3 R7 J' z

. Q1 U' S: e* D: |5 F7 c  j3 K' B' [8 y3 R$ h: j6 x& h+ [
; J! J5 d2 {5 x( l8 J
  c& d# F8 O, n8 y" ^$ ^

. N4 }) B$ g/ \0 Y; j' ]
3 F: Q% Z3 h5 s9 [2 C8 p$ P5 y
2 A  B5 s' m) A% w& Q
. V7 }' ^+ ~  {/ a2 U6 O) ~复制代码1 \' {0 r9 G! g, q$ k
6 x! `8 Y; J# ^. {$ q3 e
5 s' L7 g7 G" ~: `2 W) b+ b; Q' t

) j8 i. \2 r$ b" s( v
1 R  |" V- m2 ]- y6 o" R4 H
/ h! k9 V% D$ G- T8 `  _& j7 t8 J$ Q

. u' Q: X5 h" i& B  b* L
% @0 R; Z; n" x( F8 c
5 h2 o  R, X3 i, E: J0 t  C! W0 w0 v9 n+ M
! J8 v: F; u8 v9 n+ D8 F+ m) \

  @2 J  {. @' T) A3 n8 z. A: ?) m# w* P  T

$ w$ _6 F- d  l$ Z1 z7 i( ~! n2 _4 ?5 F' b8 g3 a+ s

* s6 [: z- ^( K# h1 i
+ K* }% x9 J  L, t

& W: M( K) {8 D- \. Q) m* _9 v# X( c# w2 v; g  k
(3)kafka 集群配置
! S' q# z- ^9 Y6 X
0 |5 r5 G$ N6 z# \( l

5 q- @4 Y9 t4 T+ s  y; z4 {$ M[root@ruanjianlaowang158 config]# cd /root/tools/kafka_2.12-2.4.1/config[root@ruanjianlaowang158 config]# vi server.properties #broker.id 三台服务器不一样,158服务器设置为1,168服务器设置为2,178服务器设置为3
+ \" Z6 {* ~1 k4 Dbroker.id=1#三个服务器配置一样zookeeper.connect=192.168.85.158:2181,192.168.85.168:2181,192.168.85.178:2181
- t/ L% [/ X" y- W% S# n* m5 t
; d9 W" U7 [' K  G1 g6 e* y0 J# C6 P. X8 O
* o- z" T2 Y$ k2 O

8 O; ^' `' C1 V9 \$ F: }9 p
) k$ h; ^; l% X' R2 }! S& [' T' h2 K# |' P7 j" v
. t+ W5 E' m% G
( W) O% g4 S# O' S

# E: J7 l# U/ F% o% p, l
4 Q$ D9 N, ^3 A2 X4 y  T复制代码
( V; `" G' w+ s" t% B
) z7 }6 V0 L( j% S. C% ]! s8 |
  S* ^( d" S. Z2 c) p: n' u
+ \: r# ~7 z& H. [7 }; o4 Q" S3 E+ ~1 }! R+ J
/ A: E8 n8 c: r0 x5 l, o6 S# w

: I+ Z* F2 r5 |: T2 C- b' u! S
. Q/ ^+ l: A# p  }) `0 }3 b6 {/ ]2 b$ E. M4 j4 f* W% ^

. l1 p2 u/ ?: a7 v& D+ A* p& v# n1 Z  g$ ^+ ^/ d

8 K* }7 H9 t9 g$ J9 i. N* F- i$ y9 U5 y* X3 V, O$ T" N/ q2 I
Kafka 常用 Broker 配置说明:

; s5 O- V% L; s( x% z; Y3 Z3 Z  ~9 D( w
0 N, p( w0 W+ z. D' _4 Z
) U' \) F0 F9 n7 a8 P
192.168.85.168:2181,192.168.85.178:2181 | ZooKeeper 服务器地址,多台用","间隔 |
2 `" y. b1 H7 p& ?
(4)集群启动

! W# l4 C# e9 x+ y
启动方式跟单机一样:
! O# A3 J$ M2 [

3 T* k7 @8 b1 A8 h

0 Z2 a' H1 P5 `& g- n$ {#启动zookeeper[root@ruanjianlaowang158 bin]# cd /root/tools/apache-zookeeper-3.5.7-bin/bin[root@ruanjianlaowang158 bin]# ./zkServer.sh  start
/ F2 D7 N+ F/ v4 ^; A3 {" Q#启动kafka[root@ruanjianlaowang158 bin]# cd /root/tools/kafka_2.12-2.4.1/bin[root@ruanjianlaowang158 bin]# ./zookeeper-server-start.sh ../config/server.properties &+ a( b$ B) L8 _+ p& U
( {+ A' S! |) U) n# o, g

+ o; r7 q6 _: a, I+ r  f+ d" k) z; c
+ g2 j' `' k3 ?: f# ~
- t! g$ G2 O0 h+ V  Q  l

0 r  P  F1 U% n% V' k/ }. m
2 L- Z, \; Q5 F; E0 J. e% N8 e2 Q
# ?# {: Q2 S) l9 v  }# z" U5 V7 d' }0 Q8 X  C# I
! X* Y; ?. S& J. Y
复制代码+ |8 l+ T3 S6 q3 e

" h4 p0 u' P( r$ h) G8 [" K5 P, ?) v

7 X% V( Z3 @5 E0 l7 ^" C
2 b2 n( {! F- M& W
- h% h8 s& {, N. L, P' R2 F
' C& U: F. P. Q8 @) X& H; ^0 n/ K9 A0 v
' K+ g4 J0 S4 g- i8 H$ x
. y  H& S5 R$ q4 B6 O

" y" g5 G" J7 \! x

* h0 |# m; W$ q4 N/ A4 g# |3 d
" w, g  J) b1 G$ m
(5)注意点
2 |6 Q" `4 B& r' {' n

5 w( F# f8 g; K4 r

6 v; N. ?. J$ {, C- L: U& \集群启动的时候,单机那台服务器(158)可能会报:Kafka:Configured broker.id 2 doesn't match stored broker.id 0 in meta.properties.方案:在158服务器data中有个文件:meta.properties,文件中的broker.id也需要修改成与server.properties中的broker.id一样,所以造成了这个问题。
2 @- H6 V5 {8 K+ f: a4 }" ]
& e9 m: Z! M: f5 ~* v3 w" o* z& D) r+ L' S8 z

8 ~0 G" I4 Y8 g- A7 Q, H1 w
& c3 c* X6 d+ h& T
7 `) h. Q9 i) E: |9 M( H& E1 a: ]7 A0 N! D2 B+ I  z/ \0 s% `

& R# M: h6 a0 ], }8 G" x7 T$ X9 Z
7 ?8 ^6 n7 N5 K, c- b# u; R% A9 W
) g' R' p' ^8 A5 s7 a3 ?" G1 F& b7 l1 n% _- e

4 E8 `9 `. {$ o+ }* P0 s" U3 U复制代码
, Z! i5 k6 W; w& i: ^4 H. o' y* i8 z, K' a

7 h9 R' B+ ~  m1 S* J
1 c1 s: N  K5 ^3 O2 B0 ^
5 h/ w- }( S: X2 G* ]' Y8 E- D9 r! U, d4 K9 y* H8 E8 L" ~3 l) u

+ N7 ~7 ?( y/ _' u' s  G3 N1 ?) ~& I
(6)创建个 topic,后面 springboot 项目测试使用。

/ k1 M7 @% o$ u7 X# D% t0 L! g  `4 x( z
: k& }( Q2 C, z
[root@ruanjianlaowang158 bin]# cd /root/tools/kafka_2.12-2.4.1/bin[root@ruanjianlaowang158 bin]# ./kafka-topics.sh --create --zookeeper 192.168.85.158:2181,192.168.85.168:2181,192.168.85.178:2181 --replication-factor 3 --partitions 5 --topic aaaa
. D* V6 p) b1 _9 X8 y
0 G* E% `& ~$ B4 m( D6 E
" u9 b! C/ m- x
2 p; k4 w- n* P, z4 ]7 r8 p# c& o: f8 g9 r

% c4 k2 h" j$ W
2 T" ^+ ]; g% O0 E3 e% R2 x; D; S" V" J/ J
6 `& \$ p* `- o
2 X( U* L/ z$ H- J: `

' B; u  ~/ X# j% }( |/ {& D
: w6 C- e4 ]( Q复制代码4 {; L" Z9 S  l

  S4 j% i' U# P9 x% g6 e, v, n  {; [7 P% E3 t$ x# ]' d
6 q: H! U' u* s0 c7 a& S1 X
& V2 k! n+ A) k
$ C, b# [$ L0 A1 d4 b8 _$ A  H- k
4 }* h0 A, S! E) r
3、结合 springboot 项目3.1 pom 文件# g! T" H9 \! }' Q1 W# A
$ p$ E( r+ g# R: ]& ?
<?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.2.0.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.itany</groupId>    <artifactId>kafka</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>kafka</name>    <description>Demo project for Spring Boot</description>' J8 z9 b5 S, V( g$ Q
    <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.kafka</groupId>            <artifactId>spring-kafka</artifactId>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build>
* g7 y$ M$ G- s! U</project>6 Q" h" G0 @2 {! b+ N" `

( {2 g6 ]8 R) ^5 o4 j7 E, q" A$ I* {: R& z7 x6 r

( g+ ]; m! h2 g$ m5 H. F- M; w+ X1 K' t. m

% }% u, v; l& F( {: J% G/ F/ p$ q( n  j# C6 m$ C+ ^
. D7 q3 x$ c/ p7 Y- {9 `

  m. v% [" e+ l8 T( B+ [1 n. q4 K% r$ @8 N# l/ ], n. V

! f% b7 q/ {( }, |' N' B. @0 f3 {1 A" p
) D! V6 D/ G- H7 l7 x* L复制代码
6 M2 A, `& K2 ~8 F0 j4 Z* L4 g3 z. I" S% O
' o6 g/ @- ?  {* T# x7 g

8 z- _" }, ]7 p) G
7 G4 y7 r4 p6 ~. f! D! R7 z+ V. x4 m5 X0 \/ w

8 ~# \6 F4 Y, O9 H9 v% I$ N. M
0 u! g; s4 w& q5 Z9 ^0 z8 J
3 F* L7 r* x& C5 R. a1 C  }9 D8 u* O
5 G& I! s4 j; `$ Q
  P! k2 k( A& P% Y- e
- u* J! F1 v, q/ o! C. d  Z/ z% ?  ~$ Q+ z& T

9 h3 H: K, U  t) g" Y/ N& v7 d) F
; ^* ?6 y/ R7 r5 d  n" r$ r3 D; ~  R4 y

- C) G  |& M4 Y; f: n9 Y7 t8 v2 z
! H; R- \+ U6 \2 ]: g6 c
) c: X% N  |7 m6 G1 m) w8 g

2 p. C" {+ _# F% b0 E
3 S8 p9 _1 s; a* e. X6 x" }; Z( I# D3 ~! @
2 P. C8 i  T- b
$ |3 w1 }  y; K, y; \7 t; a5 t

1 D3 S/ t: Z; o
- K, L* N9 t! Z% }+ q; f- N8 J6 Q3 V

" ^# w) `* p6 u- H0 P! r! Y) ?4 [' K2 r# K1 S! v. s. U# T
: j( `: X4 V' a5 w. e
+ v/ c7 c6 }; q' X

3 g  X! p# m! N$ T9 S- X
2 S! |' y! M( t; Y2 _3 E. a- I+ X' }6 ^
4 w, B; I9 `) F+ f0 O1 G" |6 Z0 _% l+ W, a' e  _1 i. k, X
) h. o# U* B) G/ p3 d0 H
+ w" V( C; a( O) L# c4 T5 e  w  d+ q
" J9 i8 m+ k$ b! d! ]
/ a4 R& o- y# s( p( w% R4 ?
' H  S1 \! ]) v2 ^

2 {0 K! a% W: A
. @" S9 n' f5 m3 d0 V
. [2 C% m# m( v
7 ?. w2 W9 g2 ?3 A
说明:
  v; h# K: s2 y
主要就两个 gav,一个是 spring-boot-starter-web,启动 web 服务使用;一个是 spring-kafka,这个是 springboot 集成额 kafka 核心包。
3.2 application.yml; n# ]5 f4 j# x

' Q, ^, m" V  P. b6 R/ \spring:  kafka:    # 北游,kafka集群服务器地址    bootstrap-servers: 192.168.85.158:9092,192.168.85.168:9092,192.168.85.178:9092    producer:      key-serializer: org.apache.kafka.common.serialization.StringSerializer      value-serializer: org.apache.kafka.common.serialization.StringSerializer    consumer:      group-id: test      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer: K; O  t, r/ H- G; B$ |  _
$ v9 {' `* h. W3 f. |4 }. S
* z+ p0 x- Q* N4 M/ f$ x

! v8 E4 I0 m3 L) u
- n  |. A" v& b& T% F
6 @/ {1 J9 D( F8 e' K; T+ n! {6 y; O* ]6 e) f; N9 {
0 _6 ]* c' X# ^% d) ^! b

! c% O% @& `- R
+ E3 c1 d% H( k2 d5 a: E7 b6 z9 R; @3 x8 A  [4 O8 `5 D
复制代码- Z, O8 g4 d6 X- L8 I8 t
2 W( H2 A% E4 x+ M- G7 u6 d5 Q% j
+ o% i4 i6 N3 v# E2 ?& r2 P

0 @9 l$ v$ N5 Z+ d7 [: H
0 k! i8 s5 \: k; G8 F% I/ R8 Q9 j1 ~( ^8 f" V/ M. B. Y7 B
4 W0 N) K2 x1 {, T) @) E

) T$ z4 V" q6 v% R. |, b* }' {0 t) c0 T
, s& b7 V# ]$ g5 e: |3 c( ?1 J# |& m8 s& B0 K6 p1 p! E( h
5 W9 s1 [+ d! `1 q; C+ y' L  c
+ u* Z" u' W6 M) @) h! Y& C

  u2 D  u6 K5 \! P# P+ G9 e
2 |2 \5 ?8 P/ N$ k5 h; Y2 n6 e" d( }

) J. V$ \! ^- h0 g$ J9 N3.3 producer(消息生产者)
2 @( ]; _* T% f! z

8 w2 u0 b: r& H6 n8 Z& S@RestControllerpublic class KafkaProducer {    @Autowired    private KafkaTemplate template;     //北游,topic使用上测试创建的aaaa    @RequestMapping("/sendMsg")    public String sendMsg(String topic, String message){        template.send(topic,message);        return "success";    }}
" Y6 g$ j9 e8 q, g# t. m4 a$ ?' |6 F* K. ]8 l. q& K% s
4 j: x2 E3 J: Y8 R) R  x2 l  i

7 g$ f8 T; @% q& ^
' J9 O" u8 c* s* i
0 U/ R3 y! \* l5 j1 s6 m. \9 l: `. i) h+ c  B3 M

" O1 A! _2 {1 U/ y9 T
, t. v% N+ Z: y3 A+ T$ J; L9 V+ Z- b" ~
8 g$ z  d; L8 S" Y9 U0 j4 `& V/ P
复制代码5 s- k& W4 v7 Z; o
8 G0 o: `# Q/ T8 N" J* p
- l. g3 j1 @- R( g# ~
7 U1 Z& p2 z% X+ ?# z  e; z
2 H! B+ F. m; ~/ S* i+ V! W
4 V% N$ c8 m' Z  ]- _& d; p5 _) X
) B! Y  e) B& B* E4 `+ k4 W2 q
- T! d4 @  i6 ^: a; L
# z4 D" I3 z6 q( T

( @( |# Y# A4 n) E* }' s. k, d! I4 n+ {

1 `8 B1 j2 }: o6 D- `, M* o# ?/ {( A1 F  s" v8 c6 A6 [0 ^3 R% H1 m# d
* E6 G( J3 O3 O8 Z
6 J. z' ]& ~6 R7 X- [* R9 X7 p4 Z

/ V' r9 ~/ S  z, j3.4 consumer(消费者)# ?9 S* h( w" X& g+ [8 D5 i) Y8 r
; R3 I4 r7 g& ^0 @" _1 F
@Componentpublic class KafkaConsumer {   //北游,这里是监控aaaa这个topic,直接打印到idea中,北游    @KafkaListener(topics = {"aaaa"})    public void listen(ConsumerRecord record){        System.out.println(record.topic()+":"+record.value());    }}/ D4 L/ [* v7 u8 i

. Q1 U+ E0 e6 ^) r) o  b  ^/ Y4 O
$ W* }  u  Q2 Y% H( R1 @; \4 {3 x2 p0 y9 E% C

0 t6 [8 Y% \2 ^
' E: t& v# W2 }( ?- l7 P: @& [+ V" k9 e  j1 n. O; V

4 r9 l% P3 B! A9 E
3 g# z! c$ \, P$ s/ A' e+ B$ R3 x$ n7 f4 o6 t

: P% y( ^6 R1 _  P5 t, L  }复制代码
% ?" M! g, X9 x! b0 v- Q2 w# s  O  ]! A5 p

2 s! \( x8 V. p$ W; x6 _% \7 U$ m
$ J8 {& }' |( r1 ~+ N( N, m: x
& l& T  C! ~  [3 K' u
! ]" ]: m# M5 ^: H" J" _( I6 t+ U/ j% L2 i  t5 s  e6 G! m

; y( t0 v/ n$ N  ]  |# ^! {) @) _4 i% e" {9 j# H
6 ^; t+ a$ u$ x! P2 n- [: p0 _! h
1 \8 Y! E) k8 y5 V+ f5 I8 {8 v% |% @
: C; D% `2 H5 R7 a- s
( @/ ~) E$ k" i0 g. N5 P
3.5 验证结果
(1)浏览器上输入

( M9 B2 C( d0 D) W- p/ P, K+ E! g4 g6 }

4 R! }6 D/ s5 Yhttp://localhost:8080/sendMsg?topic=aaaa&message=bbbb9 I' X+ v1 B$ Z% L: |  j4 t
$ X- K8 _1 d- w9 m  Q; |* X

& L" E1 u" d# r- k
! h8 o. ?% i+ i7 H
& N5 H: ~/ b5 L7 l7 Z/ D& d, b9 r6 }: g
5 Z4 q$ H  h7 ^; L" u/ U, ^
) |, A9 E# W0 r* K' T1 i8 z  n
; V7 u! w# b& T; V6 H9 L  ~: i$ n% b2 Q; `

/ T- w, [/ c6 G/ o2 M& Y7 K) L; `0 e( L# C
复制代码+ C- t3 M5 o# `/ A

" W9 m" I$ _  N/ ^: Q8 l7 V& w+ w' d1 ~& C  `
9 @: G; b9 @, I7 ]
0 P- z- R' w2 R7 l8 Z! ^( M
4 I$ n9 \0 p1 t) ]  b$ X

) W; E' Z; i  R' m5 A
(2)北游的 idea 控制台打印信息

1 O( \& A; e; v' }8 Q4 Z

" l' h* R5 \8 W+ S% g                               
登录/注册后可看大图
3 Y$ J; d7 g) n4 u& `. M9 \. `
3 X& W+ E$ N( t! ^0 v

- a! }# ~0 x, w6 u" ?0 S) I/ i# A. F6 |二、Kafka 副本机制1、什么是副本机制:
通常是指分布式系统在多台网络互联的机器上保存有相同的数据拷贝
2、副本机制的好处:2.1 提供数据冗余
系统部分组件失效,系统依然能够继续运转,因而增加了整体可用性以及数据持久性
2.2 提供高伸缩性
支持横向扩展,能够通过增加机器的方式来提升读性能,进而提高读操作吞吐量
2.3 改善数据局部性
允许将数据放入与用户地理位置相近的地方,从而降低系统延时。
3、kafka 的副本
(1)、 本质就是一个只能追加写消息的日志文件

- S/ {+ E* h- y
(2)、同一个分区下的所有副本保存有相同的消息序列

( ]' h3 F  Y& w! k% Z. ^
(3)、副本分散保存在不同的 Broker 上,从而能够对抗部分 Broker 宕机带来的数据不可用(Kafka 是有若干主题概,每个主题可进一步划分成若干个分区。每个分区配置有若干个副本)
4 R; ]$ J7 c8 b% x9 S6 @( w
如下:有 3 台 Broker 的 Kafka 集群上的副本分布情况

: ~- K% n& o0 d8 R6 h
' m/ U/ K  ?, [" f% P7 T8 ?" y& _
                               
登录/注册后可看大图

1 I) F& d/ W: ?+ J  y

1 c/ P/ l5 B2 c3 h$ O1 J# |/ Q$ G4、kafka 如何保证同一个分区下的所有副本保存有相同的消息序列:
基于领导者(Leader-based)的副本机制
1 Z# Y4 O+ [! F' u7 b/ _
工作原理如图:
6 M. O2 {9 ]8 V' b, |! e
5 j. X: a0 C8 ^4 P0 d% l$ I
                               
登录/注册后可看大图

6 b7 ?+ ~5 k$ E/ u7 e# Y
% h% I9 v1 C( B8 E8 ?3 |9 N3 c6 F
% {* W" S& y1 N/ i  K2 {  j2 b: G. Z
(1)、Kafka 中分成两类副本:领导者副本(Leader Replica)和追随者副本(Follower Replica)。每个分区在创建时都要选举一个副本,称为领导者副本,其余的副本自动称为追随者副本。

: O* S& x5 _: `" V9 h
(2)、Kafka 中,追随者副本是不对外提供服务的。追随者副本不处理客户端请求,它唯一的任务就是从领导者副本,所有的读写请求都必须发往领导者副本所在的 Broker,由该 Broker 负责处理。(因此目前 kafka 只能享受到副本机制带来的第 1 个好处,也就是提供数据冗余实现高可用性和高持久性)

- H! I7 M* a: g* ~3 j; k
(3)、领导者副本所在的 Broker 宕机时,Kafka 依托于 ZooKeeper 提供的监控功能能够实时感知到,并立即开启新一轮的领导者选举,从追随者副本中选一个作为新的领导者。老 Leader 副本重启回来后,只能作为追随者副本加入到集群中。
5、kafka 追随者副本到底在什么条件下才算与 Leader 同步
Kafka 引入了 In-sync Replicas,也就是所谓的 ISR 副本集合。ISR 中的副本都是与 Leader 同步的副本,相反,不在 ISR 中的追随者副本就被认为是与 Leader 不同步的
6、kafka In-sync Replicas(ISR)
(1)、ISR 不只是追随者副本集合,它必然包括 Leader 副本。甚至在某些情况下,ISR 只有 Leader 这一个副本

3 x5 T- G) }- d7 w7 U
(2)、通过 Broker 端 replica.lag.time.max.ms 参数(Follower 副本能够落后 Leader 副本的最长时间间隔)值来控制哪个追随者副本与 Leader 同步?只要一个 Follower 副本落后 Leader 副本的时间不连续超过 10 秒,那么 Kafka 就认为该 Follower 副本与 Leader 是同步的,即使此时 Follower 副本中保存的消息明显少于 Leader 副本中的消息。
& @. @5 O1 T3 y# G7 G
(3)、ISR 是一个动态调整的集合,而非静态不变的。

, h( _4 t3 D+ i1 S
某个追随者副本从领导者副本中拉取数据的过程持续慢于 Leader 副本的消息写入速度,那么在 replica.lag.time.max.ms 时间后,此 Follower 副本就会被认为是与 Leader 副本不同步的,因此不能再放入 ISR 中。此时,Kafka 会自动收缩 ISR 集合,将该副本“踢出”ISR。

$ L- S4 F3 d, g/ |# H
倘若该副本后面慢慢地追上了 Leader 的进度,那么它是能够重新被加回 ISR 的。

# e! _' b9 K7 L$ B# x7 x3 e; A  k
(4)、ISR 集合为空则 leader 副本也挂了,这个分区就不可用了,producer 也无法向这个分区发送任何消息了。(反之 leader 副本挂了可以从 ISR 集合中选举 leader 副本)
7、kafka leader 副本所在 broker 挂了,leader 副本如何选举
(1)、ISR 不为空,从 ISR 中选举
5 O$ y6 d2 z+ @2 O$ h$ S
(2)、ISR 为空,Kafka 也可以从不在 ISR 中的存活副本中选举,这个过程称为 Unclean 领导者选举,通过 Broker 端参数unclean.leader.election.enable控制是否允许 Unclean 领导者选举。

7 J: e0 D/ `" p, I
开启 Unclean 领导者选举可能会造成数据丢失,但好处是,它使得分区 Leader 副本一直存在,不至于停止对外提供服务,因此提升了高可用性。反之,禁止 Unclean 领导者选举的好处在于维护了数据的一致性,避免了消息丢失,但牺牲了高可用性。

6 g: s9 E9 S' O" s9 k+ s
一个分布式系统通常只能同时满足一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)中的两个。显然,在这个问题上,Kafka 赋予你选择 C 或 A 的权利。
& t9 l& X  P& ?# ~# e8 ]" c
强烈建议不要开启 unclean leader election,毕竟我们还可以通过其他的方式来提升高可用性。如果为了这点儿高可用性的改善,牺牲了数据一致性,那就非常不值当了。

8 v4 m) _! R( H; _# d  m7 t; h; d
ps1:leader 副本的选举也可以理解为分区 leader 的选举

& ?' A) O! w# f
ps2:broker 的 leader 选举与分区 leader 的选举不同,
1 ]9 y% f5 O0 a( j8 G3 x
Kafka 的 Leader 选举是通过在 zookeeper 上创建/controller 临时节点来实现 leader 选举,并在该节点中写入当前 broker 的信息
# X; q! d6 L, L# E
& s' W5 C/ Y: t% W

: |. V, q9 {9 N1 f, j' q9 i8 m, C{“version”:1,”brokerid”:1,”timestamp”:”1512018424988”}
* n% ]+ V+ c: j5 ]+ P2 b
9 A/ |2 Q9 B" A
) C& A+ @8 Q% \% j  u
$ _3 ?0 r( o, Q" j# p+ W2 n. d- w4 {" P6 y+ C! f" T$ v- P7 q

- r. }0 p: u7 }$ T
0 z, E7 T: L! |" v4 M7 m1 @3 b" L
6 b- J- c- a7 f& }9 z& P$ s! _
- ^+ `0 B* r* Z& h" o+ p' Q
4 s  ^' A9 _1 ?+ ^* L1 ]. n7 b) ?
复制代码
3 P$ |0 B/ a# H6 ?
( I* M; x/ y2 C
/ p  j+ D3 s- y8 g  X# c' P' g+ z, u: u: K2 w2 \6 b) c5 {4 J
" C' F3 ?7 v, \; H) |6 g' Q5 c

+ H  E  d6 }1 d% M) h! X' z% u9 J7 r' R
利用 Zookeeper 的强一致性特性,一个节点只能被一个客户端创建成功,创建成功的 broker 即为 leader,即先到先得原则,leader 也就是集群中的 controller,负责集群中所有大小事务。
1 @. Y6 W, O! v3 L- r2 L  Q
当 leader 和 zookeeper 失去连接时,临时节点会删除,而其他 broker 会监听该节点的变化,当节点删除时,其他 broker 会收到事件通知,重新发起 leader 选举
/ d3 B6 M+ R' W  E- \2 @
再给你们留个小问题:如果允许 Follower 副本对外提供读服务,你觉得应该如何避免或缓解因 Follower 副本与 Leader 副本不同步而导致的数据不一致的情形?
三、实时日志统计流程1、项目流程
在整合这套方案的时候,项目组也是经过一番讨论,在讨论中,观点很多,有人认为直接使用 Storm 进行实时处理,去掉 Kafka 环节;也有认为直接使用 Kafka 的 API 去消费,去掉 Storm 的消费环节等等,但是最终组内还是一致决定使用这套方案,原因有如下几点:
5 z. k; q: ?8 s+ ^, I1 r
  • 业务模块化
  • 功能组件化
    7 R0 h4 S' T9 a9 m6 ^
  _3 _, s/ n# M+ h; `
我们认为,Kafka 在整个环节中充当的职责应该单一,这项目的整个环节她就是一个中间件,下面用一个图来说明这个原因,如下图所示:

5 r; Z4 `& ^! B6 d1 S7 T6 i

5 `3 i5 ?6 f6 s3 ^1 x7 L- i4 ]. a                               
登录/注册后可看大图
+ N- u4 W. W: U8 W, N; I
+ o' c- c1 P2 \: v- k9 U& g

2 x2 [4 w4 d) @" p/ _# ]7 r- _  R& H0 g) {
整个项目流程如上图所示,这样划分使得各个业务模块化,功能更加的清晰明了。

' l8 A% s6 @) V1 L$ x2 ~4 k
  • Data Collection

    ' M$ _# Y1 y4 s. I3 u9 N+ O( Z. ]9 S

! `- _' s5 }. y  q9 o$ }3 W
负责从各个节点上实时收集用户上报的日志数据,我们选用的是 Apache 的 Flume NG 来实现。
& e! a$ [2 A7 I9 b0 ]# _! U
  • Data Access

    5 c& R% d: U1 g5 ^4 U+ q# ]
6 {+ \7 w* m; M% g
由于收集的数据的速度和数据处理的速度不一定是一致的,因此,这里添加了一个中间件来做处理,所使用的是 Apache 的 Kafka,关于 Kafka 集群部署。另外,有一部分数据是流向 HDFS 分布式文件系统了的,方便于为离线统计业务提供数据源。
1 |% m! V3 ~8 v' U% i1 [
  • Stream Computing
    * n+ s( i" r2 Q: t

4 L  k# c# l; }& x6 m/ B
在收集到数据后,我们需要对这些数据做实时处理,所选用的是 Apache 的 Storm。关于 Storm 的集群搭建部署博客后面补上,较为简单。

: @* M2 J8 l! U
  • Data Output

    7 P, |( M( e8 m0 `/ J3 v" d5 g7 E( \
! d% @4 ]& N: e2 f' _1 b! n
在使用 Storm 对数据做处理后,我们需要将处理后的结果做持久化,由于对响应速度要求较高,这里采用 Redis+MySQL 来做持久化。整个项目的流程架构图,如下图所示:

% }+ ^, Z3 v1 n( G& k
/ A4 d: c  g  B7 ^& h
                               
登录/注册后可看大图
: ?* {) G# Z1 v$ V

- Q! v+ w  B6 _% X6 t* b7 ~2、Flume
Flume 是一个分布式的、高可用的海量日志收集、聚合和传输日志收集系统,支持在日志系统中定制各类数据发送方(如:Kafka,HDFS 等),便于收集数据。Flume 提供了丰富的日志源收集类型,有:Console、RPC、Text、Tail、Syslog、Exec 等数据源的收集,在我们的日志系统中目前我们所使用的是 spooldir 方式进行日志文件采集,配置内容信息如下所示:
! x9 v7 Y9 `" Q. |. \) k# k

) ^! H- k; {" s; t" E2 B
  B/ m) U9 p5 m. L. W) h, h
producer.sources.s.type = spooldirproducer.sources.s.spoolDir = /home/hadoop/dir/logdfs
. A! P) i0 p+ i+ i; d
8 q: Q# R8 p/ L8 R& h7 K- l
/ [  I% ^1 _6 \: O# _" Q6 g
4 y+ B7 q6 m! V" Y
9 G2 p6 O/ ?5 \; o. ~
( I7 r' x  G: T, I* C
( L! E) \+ ~6 h7 q3 ^- _* k: s
5 E' A1 h# E, {- L' V9 g2 ?2 ]& Q, E- l5 f

+ |% ^5 I  l, W9 D" m6 I# _) P% W
复制代码
. J* ^- W) T. a- l4 J, V
1 m$ G: @' H4 y( \  `7 E4 L- _% {' G

8 a* O9 P+ t# o( E6 O1 k" l3 e
- ~2 K3 h0 k. J/ y+ t
2 T% ~' y: }  O9 G5 U3 U
* B$ ~# L! [; I2 r% U3 p! k6 o1 e5 d

9 B" J; z6 M) J' f9 F
当然,Flume 的数据发送方类型也是多种类型的,有:Console、Text、HDFS、RPC 等,这里我们系统所使用的是 Kafka 中间件来接收,配置内容如下所示:
( d0 L7 u+ b  G: e& @$ X+ [

9 s1 Z7 V7 g% u' p. n( o, \

3 J9 k  f4 F8 W& \/ p% z$ Q* N7 Eproducer.sinks.r.type = org.apache.flume.plugins.KafkaSinkproducer.sinks.r.metadata.broker.list=dn1:9092,dn2:9092,dn3:9092producer.sinks.r.partition.key=0producer.sinks.r.partitioner.class=org.apache.flume.plugins.SinglePartitionproducer.sinks.r.serializer.class=kafka.serializer.StringEncoderproducer.sinks.r.request.required.acks=0producer.sinks.r.max.message.size=1000000producer.sinks.r.producer.type=syncproducer.sinks.r.custom.encoding=UTF-8producer.sinks.r.custom.topic.name=test
1 f6 Y8 {3 H4 o, o( f  ^) B
) F/ G1 H( w5 m; F0 e: j: f1 v, _" \6 f

4 {+ }. _" C& E, h6 [) C* b! O$ |$ L
- G! y; z, p( \$ ]& M

7 \2 ]9 ?( q9 o9 }+ I) o9 j
) q4 Z. q6 ?7 X; y4 ], d' s
$ P+ L+ G( c  ^% K; ]& Z& y' T  D0 [  w" }7 T

) ~. }" P% C1 ~$ w7 k) C3 G/ |复制代码
( H9 |6 {7 Y2 @* y9 E: J; l, ?2 L" E  ~3 J

% P# @! C6 }4 i$ A2 E. C1 H7 {) ]. `
0 o" ]$ a- f0 ~. R" \# F. ~5 r4 K

% ^) w+ f; b! q- O" n+ r: l& c6 C3 \+ j+ M

* |: \) N' t: O) w+ i0 c: w0 f# y" T

2 R0 {$ O  z" v! u
" c' q* k- F* J& C4 ^8 a7 u4 j# H! B- r# m" s
: v! ?; z# O; y/ F  M

* g; I0 |8 |- c* }7 Y7 T# A5 Q
0 ~8 O. Z3 [2 p% q
3、Kafka
Kafka 是一种提供高吞吐量的分布式发布订阅消息系统,她的特性如下所示:
! F2 g5 c7 k* s! ]; p. [. K
  • 通过磁盘数据结构提供消息的持久化,这种结构对于即使数据达到 TB+级别的消息,存储也能够保持长时间的稳定。
  • 搞吞吐特性使得 Kafka 即使使用普通的机器硬件,也可以支持每秒数 10W 的消息。
  • 能够通过 Kafka Cluster 和 Consumer Cluster 来 Partition 消息。

    0 r8 c+ f* f' E, f. ~; ]$ }0 p
6 m; `, b$ J, H& [
Kafka 的目的是提供一个发布订阅解决方案,他可以处理 Consumer 网站中的所有流动数据,在网页浏览,搜索以及用户的一些行为,这些动作是较为关键的因素。这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。对于 Hadoop 这样的日志数据和离线计算系统,这样的方案是一个解决实时处理较好的一种方案。
$ [2 e1 [4 y8 ^3 x
关于 Kafka 集群的搭建部署和使用,上面已经写了,不会的朋友翻上去再看一下,这里就不赘述了。
4、Storm
Twitter 将 Storm 开源了,这是一个分布式的、容错的实时计算系统,已被贡献到 Apache 基金会,下载地址如下所示:

& [* p4 X# M5 A  K+ E% h8 \9 \6 Z
9 N2 b  t9 H2 S, X. I

, t: h- X2 z& T$ L; Fhttp://storm.apache.org/downloads.html
0 t$ P- r3 M' l( T5 p" |; c8 D4 s- ~
( P9 Q0 D& _5 T5 q. S
" |. B5 C3 K% ]" S6 k: ~
. l% g; C( k3 j% j$ F1 ?% r
- C+ N- h) j2 }* p% j  l
4 T$ Y3 t) C: R) c* S
: Y5 g% T7 c$ @0 A7 m. `# L7 i
4 X8 b( ^& i& r5 \% M0 v
; y5 P+ `: _& q* A+ N3 X1 t
* {* l& t+ h; c* j6 K
复制代码; s: _% J1 u  i% k+ Q7 M3 f1 `

; p  d- n3 j, X# N
! K$ X' j6 _& w# j7 J* {& s$ F. k: G* Q1 J! h
9 q7 s1 k+ {$ z9 x  b
: o' k6 v; s8 q8 K1 S
& U5 z; |1 v, N4 p+ T
Storm 的主要特点如下:
1 ~9 q' x% |$ K+ H
  • 简单的编程模型。类似于 MapReduce 降低了并行批处理复杂性,Storm 降低了进行实时处理的复杂性。
  • 可以使用各种编程语言。你可以在 Storm 之上使用各种编程语言。默认支持 Clojure、Java、Ruby 和 Python。要增加对其他语言的支持,只需实现一个简单的 Storm 通信协议即可。
  • 容错性。Storm 会管理工作进程和节点的故障。
  • 水平扩展。计算是在多个线程、进程和服务器之间并行进行的。
  • 可靠的消息处理。Storm 保证每个消息至少能得到一次完整处理。任务失败时,它会负责从消息源重试消息。
  • 快速。系统的设计保证了消息能得到快速的处理,使用ØMQ 作为其底层消息队列。
  • 本地模式。Storm 有一个本地模式,可以在处理过程中完全模拟 Storm 集群。这让你可以快速进行开发和单元测试。

    : H7 H) x" K7 X4 M# [0 {- w0 m

6 v' L  g# V. x9 b" M& I) P6 p
Storm 集群由一个主节点和多个工作节点组成。主节点运行了一个名为“Nimbus”的守护进程,用于分配代码、布置任务及故障检测。每个工作节 点都运行了一个名为“Supervisor”的守护进程,用于监听工作,开始并终止工作进程。

- q% J9 g3 R/ H, V0 I& E, R0 P
Nimbus 和 Supervisor 都能快速失败,而且是无 状态的,这样一来它们就变得十分健壮,两者的协调工作是由 Apache 的 ZooKeeper 来完成的。

" I6 ?7 y+ z) I/ W! _
Storm 的术语包括Stream、Spout、Bolt、Task、Worker、Stream Grouping和Topology。

8 g( p3 Z/ h$ F
  • Stream 是被处理的数据。
  • Spout 是数据源。
  • Bolt 处理数据。
  • Task 是运行于 Spout 或 Bolt 中的 线程。
  • Worker 是运行这些线程的进程。
  • Stream Grouping 规定了 Bolt 接收什么东西作为输入数据。数据可以随机分配(术语为 Shuffle),或者根据字段值分配(术语为 Fields),或者广播(术语为 All),或者总是发给一个 Task(术语为 Global),也可以不关心该数据(术语为 None),或者由自定义逻辑来决定(术语为 Direct)。
  • Topology 是由 Stream Grouping 连接起来的 Spout 和 Bolt 节点网络。在 Storm Concepts 页面里对这些术语有更详细的描述。
    . d& J( i7 J8 M2 O5 p1 l2 `

/ @; n  t. c4 m, N1 i
关于 Storm 集群的搭建部署,博客在下一篇中更新,到时候会将更新地址附在这里,这里就先不对 Storm 集群的搭建部署做过多的赘述了。
5、总结
Kafka 日志消息保存时间总结 Kafka 作为一个高吞吐的消息中间件和传统的消息中间件一个很大的不同点就在于它的日志实际上是以日志的方式默认保存在/kafka-logs 文件夹中的。虽然默认有 7 天清楚的机制,但是在数据量大,而磁盘容量不足的情况下,经常出现无法写入的情况。如何调整 Kafka 的一些默认参数就显得比较关键了。这里笔者整理了一些常见的配置参数供大家参考:

! w( Z' F4 B  z/ S3 r
分段策略属性
1 \% H( a; S' |! Q) a0 d

7 s( a6 P9 F1 A  i
+ G6 q6 l. J+ o# U4 t
# ?; k9 M# Y" X, T( ^/ L6 T
日志刷新策略
, \4 x; T. e( Z
Kafka 的日志实际上是开始是在缓存中的,然后根据策略定期一批一批写入到日志文件中去,以提高吞吐率。
" I" U5 e& P8 l! E, j. @1 g

' b- V2 k0 h! D/ j8 T  F

1 |: G# c0 g3 f+ b8 O! ~+ T& [' D( Y3 x! F
日志保存清理策略
! [/ l8 v9 E# Q6 R9 I& J  Z
- R1 z8 i8 s+ O% j, a8 _

8 _1 A9 i& w& A+ f% g  n( f; f
8 {# o* \( ^+ A) f! G/ p% P
这里特别说明一下,日志的真正清楚时间。当删除的条件满足以后,日志将被“删除”,但是这里的删除其实只是将该日志进行了“delete”标注,文件只是无法被索引到了而已。

4 P( S# A, t/ a
但是文件本身,仍然是存在的,只有当过了 log.segment.delete.delay.ms 这个时间以后,文件才会被真正的从文件系统中删除。
+ c/ e' K  S4 ^) O8 ]* L8 {

- q- X$ J/ P( f8 _- Y
文章写到这里差不多了,比我预计要写得短一些,因为还有一些东西要写出来难免长篇大论,篇幅不允许,想更透彻的掌握 kafka 的同学可以领取我整理的完整版kafka学习笔记,最近要准备面试的同学可以看看我这份kafka高频面试题整理
( }3 j% f. D6 s) k. k8 Q
后面我会把另外两个中间件也分别写文章分析,可以给我点个关注第一时间接到通知
$ J. `0 t+ k1 Q# h+ P' l
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-8 21:39 , Processed in 0.072006 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表