Kafka消息队列
简介:Apache的顶级开源项目,是一个分布式(partition),多副本(replica),基于zookeerper(集群管理者) 协调的分布式消息队列,最大特性高吞吐量、实时处理大量数据满足各种场景需求,解决延时、处理性能....问题。
原理:数据缓冲队列,同时提高服务的可扩展性,来面对大量的访问请求及压力
特性:
高吞吐量 => kafka每秒处理万级别的消息
可扩展性 => kafka支持集群(热扩展)、数据的持久化(副本)
可靠性 => 消息被持久化到本地磁盘、实现数据的备份
容错 => 分片与分区技术(partition)使得每台kafka进行复制(replication),都有备份数据
高并发 => 支持千级别的客户端同时读写
组件
话题(Topic):是特定类型的消息流。(每条发布到 kafka 集群的消息属于的类别,即 kafka 是面向 topic
的。)
生产者(Producer):是能够发布消息到话题的任何对象(发布消息到 kafka 集群的终端或服务).
消费者(Consumer):可以订阅一个或多个话题,从而消费这些已发布的消息。
服务代理(Broker):已发布的消息保存在一组服务器中,它们被称为代理(Broker)或Kafka集群。
partition(区):每个 topic 包含一个或多个 partition。
replication:partition 的副本,保障 partition 的高可用。
leader:replica 中的一个角色, producer 和 consumer 只跟 leader 交互。
follower:replica 中的一个角色,从 leader 中复制数据。
zookeeper:kafka 通过 zookeeper 来存储集群的信息。
工作架构
1. 可以有多个brokers => 部署在linux主机上,可以说就相当于一个kafka 2. 当消息生产者(Produce) => logstash/filebeat程序发送topic(话题型消息)会进行分片技术(将信息截成一段第一段的),发往每一个borker(kafka),读写效率的提高 3. 为了提高分片技术的安全性,会将分片数据在进行分区(partition),在每一个borker上进行复制(replication) 保证了每一个broker上都有数据的副本,安全性 主要是由replication上的leader(可以说就是master)接受produce的数据,再交给follower(可以说是slave) 进行分区复制(replication) 4. 最后被消费者(Cosumers)消费 => 消费者可以有多个(可以说就是elasticsearch) 5. 在每一台broker(kafka)上安装zookeeper,保证每一台的集群状态(谁是master,谁是slave.....),实现服务的 高可用性。 6. 当其中有一台broker宕机了,zookeeper能即使通知生产者与消费者,保证整个消息系统的运行
一、部署kafka集群
🌍环境:ka1:192.168.178.30 ka2:192.168.178.31 ka3:192.168.178.32
pdf免费文档:https://download.csdn.net/download/weixin_56903457/21455547?spm=1001.2014.3001.5503
版本:kafka_2.12-2.8.0 自带zookeeper,无需安装zookeeper
💯 百度网盘:
链接:https://pan.baidu.com/s/1I2HB56-qhPevdux1FRilnQ 提取码:help
👀标明:本实验与上一次的ELK实战接在一起
链接:https://blog.csdn.net/weixin_56903457/article/details/119846702?spm=1001.2014.3001.5501
ka1
1. 对表ela1:yum -y install ntpdate #安装ntp客户端 ntpdate 192.168.178.24 #填写ntpd服务器IP 2. 修改主机名:hostname set-hostname ka1 3. 进行本地DNS解析:vim /etc/hosts 192.168.178.30 ka1 192.168.178.31 ka2 192.168.178.32 ka3 4. 安装jdk8.0:yum -y install epel-release && yum -y install java-1.8.0-openjdk 5. 解压缩包到指定目录:tar -xvzf kafka_2.12-2.8.0.tgz -C /usr/local/ mv /usr/local/kafka_2.12-2.8.0/ /usr/local/kafka #=====================配置zookeeper文件======================== 6. 将配置文件内容全注释: sed ‐i 's/^[^#]/#&/' /usr/local/kafka/config/zookeeper.properties #将不以 "#" 开头的行,在其前面加上"#" &(将前面的匹配结果引用) 7. 修改配置文件:vim /usr/local/kafka/config/zookeeper.propertie #添加: dataDir=/opt/data/zookeeper/data #数据存放目录 dataLogDir=/opt/data/zookeeper/logs #日志存放目录 clientPort=2181 #向外提供的端口 tickTime=2000 #zookeeper与客户端维持心跳的间隔(状态) initLimit=20 #leader与follower的初始化连接时间,超过时间连接失败 syncLimit=10 #leader与follower之间的通信,在设置时间内不能与leader通信,follower被丢弃 server.1=192.168.178.30:2888:3888 #2888端口是leader与follower之间交换信息的端口 server.2=192.168.178.31:2888:3888 #3888端口是leader挂了后,进行重新选举leader时其他服务之间 server.3=192.168.178.32:2888:3888 #通信的端口,填写ka1、ka2、ka3的IP地址 8. 创建数据与日志存放目录: mkdir -p /opt/data/zookeeper/{data,logs} 9. 创建myid身份证:echo 1 > /opt/data/zookeeper/data/myid #=====================配置kafka文件======================== 10. 将配置文件内容注释:sed -i 's/^[^#]/#&/' /usr/local/kafka/config/server.properties 11. 修改配置文件:vim /usr/local/kafka/config/server.properties 添加: broker.id=1 #集群标识符,集群中其他主机不一致 listeners=PLAINTEXT://192.168.178.30:9092 #监听地址,填本机 num.network.threads=3 #处理消息的最大进程数 num.io.threads=8 #处理磁盘IO的线程数,数值"大于"主机的磁盘数即可 socket.send.buffer.bytes=102400 #socket发送的缓冲区 socket.receive.buffer.bytes=102400 #接收的缓冲区 socket.request.max.bytes=104857600 #请求的最大数值 log.dirs=/opt/data/kafka/logs #存放日志的目录 num.partitions=6 #topic消息的分区个数 num.recovery.threads.per.data.dir=1 #每个日志(log.dir)使用的处理线程数 offsets.topic.replication.factor=2 #位置偏移量,对数据复制2份 transaction.state.log.replication.factor=1 #传输日志的复制状态 transaction.state.log.min.isr=1 log.retention.hours=168 #topic消息的生命周期 log.segment.bytes=1073741824 #最多一个分片能存储的大小 1G log.retention.check.interval.ms=300000 # 日志分片校验 zookeeper.connect=192.168.178.30:2181,192.168.178.31:2181,192.168.178.32:2181 #填写ka1/2/3 zookeeper.connection.timeout.ms=6000 #连接zookeeper的超时时间(6秒) group.initial.rebalance.delay.ms=0 #新的集群成员加入的延迟时间,选举master 12.创建kafka存放日志的目录: mkdir -p /opt/data/kafka/logs/ =======================Copy Config file for ka2/ka3=================== ▲注意:在拷贝前ka2/ka3先把kafka源码包解压好到指定目录!!!!!! 13. 拷贝DNS域名解析: scp -r /etc/hosts ka2:/etc/hosts scp -r /etc/hosts ka3:/etc/hosts 14. 拷贝zookeeper配置: scp -r /usr/local/kafka/config/zookeeper.properties ka2:/usr/local/kafka/config/ scp -r /usr/local/kafka/config/zookeeper.properties ka3:/usr/local/kafka/config/ 15. 拷贝kafka配置文件: scp -r /usr/local/kafka/config/server.properties ka2:/usr/local/kafka/config/ scp -r /usr/local/kafka/config/server.properties ka3:/usr/local/kafka/config/
ka2
1. 对表ela1:yum -y install ntpdate #安装ntp客户端 ntpdate 192.168.178.24 #填写ntpd服务器IP 2. 修改主机名:hostname set-hostname ka2 3. 安装jdk8.0:yum -y install epel-release && yum -y install java-1.8.0-openjdk 4. 解压缩包到指定目录:tar -xvzf kafka_2.12-2.8.0.tgz -C /usr/local/ mv /usr/local/kafka_2.12-2.8.0/ /usr/local/kafka 5. 创建数据与日志存放目录: mkdir -p /opt/data/zookeeper/{data,logs} 6. 创建myid身份证:echo 2 > /opt/data/zookeeper/data/myid #不要与集群中其他主机一样 7. 修改kafka配置文件: vim /usr/local/kafka/config/server.properties #找到修改 broker.id=2 #与myid相同即可 listeners=PLAINTEXT://192.168.178.31:9092 #监听地址,本机IP 8. 创建kafka存放日志的目录: mkdir -p /opt/data/kafka/logs/
ka3
1. 对表ela1:yum -y install ntpdate #安装ntp客户端 ntpdate 192.168.178.24 #填写ntpd服务器IP 2. 修改主机名:hostname set-hostname ka3 3. 安装jdk8.0:yum -y install epel-release && yum -y install java-1.8.0-openjdk 4. 解压缩包到指定目录:tar -xvzf kafka_2.12-2.8.0.tgz -C /usr/local/ mv /usr/local/kafka_2.12-2.8.0/ /usr/local/kafka 5. 创建数据与日志存放目录: mkdir -p /opt/data/zookeeper/{data,logs} 6. 创建myid身份证:echo 3 > /opt/data/zookeeper/data/myid #不要与集群中其他主机一样 7. 修改kafka配置文件: vim /usr/local/kafka/config/server.properties #找到修改 broker.id=3 #与myid相同即可 listeners=PLAINTEXT://192.168.178.32:9092 #监听地址,本机IP 8. 创建kafka存放日志的目录: mkdir -p /opt/data/kafka/logs/
二、启动zookeeper与kafka进行测试
ka1/ka2/ka3
#==================== 启动zookeeper集群 ====================== 1. ka1启动: nohup /usr/local/kafka/bin/zookeeper-server-start.sh /usr/local/kafka/config/zookeeper.properties & 2. ka2启动: nohup /usr/local/kafka/bin/zookeeper-server-start.sh /usr/local/kafka/config/zookeeper.properties & 3. ka3启动: nohup /usr/local/kafka/bin/zookeeper-server-start.sh /usr/local/kafka/config/zookeeper.properties & #==================== 启动kafka集群 ====================== 1. ka1启动: nohup /usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties & #在后台运行,报错可在当前nohup.out中查看 2. ka2启动: nohup /usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties & 3. ka3启动: nohup /usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties & #==================== 测试集群的可用性 ====================== ----------------示例:发送topic消息 => testtopic_pengge---------------- 1. ka1执行命令: /usr/local/kafka/bin/kafka-topics.sh --create --zookeeper 192.168.178.30:2181 --replication-factor 1 --partitions 1 --topic "testtopic_pengge" 2. ka2查看消息:/usr/local/kafka/bin/kafka‐topics.sh ‐‐zookeeper 192.168.19.30:2181 ‐‐list 3. ka3查看消息:/usr/local/kafka/bin/kafka‐topics.sh ‐‐zookeeper 192.168.19.30:2181 ‐‐list ----------------示例:模拟消息的生产与消费-------------------- 1. ka1生产消息:/usr/local/kafka/bin/kafka-console-producer.sh --broker-list 192.168.178.30:9092 --topic testtopic #本机的IP地址 >nihao #自己进行输入后回车,退出 ctrl+c >hello 2. ka2消费消息:/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server 192.168.178.31:9092 --topic testtopic --from-beginning #本机的IP >nihao #可以查到生产的消息 >hello 3. ka3消费消息:/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server 192.168.178.32:9092 --topic testtopic --from-beginning #本机的IP >nihao #可以查到生产的消息 >hello
三、启动与配置filebeat与logstash
🥇 原理:filebeat收集nginx的日志给kafka消息队列进行缓冲,kafka再给logstash进行收集,最后交到elastic上
logstash
1. 创建kafka配置文件:vim /usr/local/logstash/config/kafka.conf input{ #向kafka拿topic消息 kafka { type => "nginx_log" codec => "json" topics => ["nginx"] decorate_events => true #ka1/ka2/ka3的IP:Port bootstrap_servers => "192.168.178.30:9092, 192.168.178.31:9092, 192.168.178.32:9092" } } filter { #过滤字段 grok { match => {"message" => "%{COMBINEDAPACHELOG}"} } } output{ #输出给elastic进行存储 stdout { codec => rubydebug } #先输出到屏幕上 if [type] == "nginx_log" { #类型匹配成功,与上面一样即可 elasticsearch { index => "nginx-%{+YYYY.MM.dd}" #索引格式 nginx-时间戳 codec => "json" #ela1/ela2/ela3的IP:Port hosts => ["192.168.178.24:9200","192.168.178.25:9200","192.168.178.26:9200"] } } } 2. 执行:/usr/local/logstash/bin/logstash -f /usr/local/logstash/config/kafka.conf
filebeat
1. 修改配值文件:vim /usr/local/filebeat/filebeat.yml # ------------------------------ Logstash Output ------------------------------- #找到进行注释 #output.logstash: # hosts: ["192.168.178.28:5044"] #进行添加 # ------------------------------ Kafka Output ------------------------------- output.kafka: hosts: ["192.168.178.30:9092", "192.168.178.31:9092", "192.168.178.32:9092"] #kafka集群的IP:Port topic: 'nginx' #消息类型也可以 topic: 'filebeat1-nginx' 为了区别从哪个主机上来的日志 #相对应logstash上的 topics => ["filebeat1-nginx"] partition.round_robin: #分区存储的负载轮询策略 reachable_only: false #是否只写入一台 flase假的 true真的 required_acks: 1 compression: gzip #数据进行压缩 max_message_bytes: 1000000 #每条消息最大的字节数1M 2. 删除防重读缩:rm -rf /usr/local/filebeat/data/ 3. 执行:/usr/local/filebeat/filebeat -c /usr/local/filebeat/filebeat.yml -e
ela1/ela2/ela3查询存储的消息
1. 执行:[root@ela1 ~]# curl -X GET "192.168.178.24:9200/_cat/indices" green open nginx-2021.08.22 r8_phV2bT3mVFA2RzYNeSA 1 1 284068 green open localhost.localdomain-nginx-error-2021.08.21 UGwnNNsESlSaTKWl75l8jg 1 green open filebeat1-nginx-error-2021.08.21 CuvjMu05TLaZCb-3LG03xg 1 green open localhost.localdomain-nginx-access-2021.08.21 MWp1WjikQbesCafc47hxFA 1 green open .kibana_task_manager_7.13.2_001 TF0zFbBgQIK1I0oH1aUihA 1 green open filebeat1-nginx-access-2021.08.21 YiyagsrmSMSW4YoK-LLYHw 1 #可以看到 <nginx> 消息索引名 2. ela2/ela3分别查看: curl -X GET "192.168.178.25:9200/_cat/indices" curl -X GET "192.168.178.26:9200/_cat/indices"
kibana
1. 浏览器访问:http://192.168.178.29:5601 #===============增加索引模式================= 1. 左上角 "三" > Management > Stack Management 2. 左方找到 "索引模式" > 创建索引模式 > 文本框填写"nginx*" > 下一步 > 时间字段选择 @timestamp > 创建索引模式 #==============查看及分析索引字段=============== 1. 左上角 "三" > Discover > 在左方根据自己的需求选择查看的字段 #==============创建仪表板分析================ 1. 左上角 "三" > Overview > 仪表板 > 创建新的仪表板 > 根据需求拖动字段查看排名.......
四、扩展
需求:topic话题性消息的字段为它在哪个主机就以哪个主机命名, 有多个filebeat,各收集不同的日志
filebeat1(收集nginx日志)
修改主机名:hostname set-hostname filebeat1 1.修改配置文件:vim /usr/local/filebeat/filebeat.yml output.kafka: hosts: ["192.168.178.30:9092", "192.168.178.31:9092", "192.168.178.32:9092"] topic: 'filebeat1-nginx' #以自己主机名的方式命名 partition.round_robin: reachable_only: false required_acks: 1 compression: gzip max_message_bytes: 1000000 2. 安装nginx: yum -y install epel-release && yum -y install nginx 3. 产生nginx日志:浏览器访问即可 4. 开启filebeat自带的nginx收集模块: /usr/local/filebeat/filebeat -c /usr/local/filebeat/filebeat.yml modules enable nginx
filebeat2(收集apache日志)
修改主机名:hostname set-hostname filebeat2 1.修改配置文件:vim /usr/local/filebeat/filebeat.yml # ------------------------------ Logstash Output ------------------------------- #output.logstash: #将其注释 #hosts: ["localhost:5044"] # ------------------------------ Kafka Output ------------------------------- output.kafka: #找个位置添加 hosts: ["192.168.178.30:9092", "192.168.178.31:9092", "192.168.178.32:9092"] topic: 'filebeat2-apache' #填写自己主机名 partition.round_robin: reachable_only: false required_acks: 1 compression: gzip max_message_bytes: 1000000 2. 安装apache: yum -y install httpd 3. 产生httpd日志:浏览器访问即可 4. 开启filebeat自带的apache收集模块: /usr/local/filebeat/filebeat -c /usr/local/filebeat/filebeat.yml modules enable apache
logstash
1.修改配置文件:vim /usr/local/logstash/config/kafka.conf input{ kafka { #filebeat1 type => "filebeat1_nginx_log" codec => "json" topics => ["filebeat1-nginx"] decorate_events => true bootstrap_servers => "192.168.178.30:9092, 192.168.178.31:9092, 192.168.178.32:9092" } kafka { #filebeat2 type => "filebeat2_apache_log" codec => "json" topics => ["filebeat2-apache"] decorate_events => true bootstrap_servers => "192.168.178.30:9092, 192.168.178.31:9092, 192.168.178.32:9092" } } filter { grok { match => {"message" => "%{COMBINEDAPACHELOG}"} } } output { stdout { codec => rubydebug } #------------------------------Nginx Log-------------------------------------- if [type] == "filebeat1_nginx_log" { if [log][file][path] == "/var/log/nginx/access.log" { elasticsearch { hosts => ["192.168.178.24:9200","192.168.178.25:9200","192.168.178.26:9200"] index => "%{[host][hostname]}-nginx-access-%{+YYYY.MM.dd}" } } else if [log][file][path] == "/var/log/nginx/error.log" { elasticsearch { hosts => ["192.168.178.24:9200","192.168.178.25:9200","192.168.178.26:9200"] index => "%{[host][hostname]}-nginx-error-%{+YYYY.MM.dd}" } } } #------------------------------Apache Log-------------------------------------- if [type] == "filebeat2_apache_log" { if [log][file][path] == "/var/log/httpd/access_log" { elasticsearch { hosts => ["192.168.178.24:9200","192.168.178.25:9200","192.168.178.26:9200"] index => "%{[host][hostname]}-apache-access-%{+YYYY.MM.dd}" } } else if [log][file][path] == "/var/log/httpd/error_log" { elasticsearch { hosts => ["192.168.178.24:9200","192.168.178.25:9200","192.168.178.26:9200"] index => "%{[host][hostname]}-apache-error-%{+YYYY.MM.dd}" } } } } #======================================================================== #output{ # stdout { codec => rubydebug } # if [type] == "nginx_log" { # elasticsearch { # index => "%{[host][hostname]}-nginx-%{+YYYY.MM.dd}-access" # codec => "json" # hosts => ["192.168.178.24:9200","192.168.178.25:9200","192.168.178.26:9200"] # } # } #}