Kafka 概念、单机搭建与使用

官方网址:Apache Kafka® is a distributed streaming platform

基本概念介绍

在Kafka中有一些基本的概念,

Topic

  • 简介:Topic在Kafka中是一个抽象的概念,一个主题是已经发布的记录的种类。主题在Kafka中是可以被多重订阅的,这就意味着一个主题可能有0个、一个、或者许多个消费者去订阅这个主题中的消息。

  • Partitions:在每一个topic在Kafka中可以有多个分区,增加一个主题的分区可以提高Kafka的吞吐率,但是不是越多越好,因为如果分区数量越多的话生产者插入的效率也会降低。所以真正到生产环境时,需要权衡生产与消费的一个平衡关系,消费稍微大于生产者,不会产生消息的堆积,也能够充分提高Kafka的效率。

  • Replication Factor:复制因子,是对于当前的Topic是否需要副本。如果设置成1的话,代表当前Topic在整个Kafka中只有一份。这里有个限制Topic的数量不能够多于当前Kafka的Broker数量。

  • 存储方式:在Kafka的配置中(Server.properties)有logs.dir的配置,这个是Kafka存储消息的位置。如果Topic复制因子是1分区是1的话,在对应的文件夹下会有一个名称为topicname的文件夹;如果复制因子是2分区是2,假设存在两个Broker,在每个Broker中将会存在两个文件夹分别为topicname_0 topicname_1的文件夹

  • Leader与Follower:由于每个topic如果存在副本的话,是对于partition进行复制。这么多存在在不同的Broker上的副本,其中有一个partition是leader其他的是Followers,当一个broker宕机会在副本中选择一个充当Leader。关于Kafka中的选举机制以及Leader的确认可以查看这两篇文章:Leader确认选举机制

Producer

生产者,顾明思议是生产消息,允许应用发布一个流的消息到一个或者多个主题中,

Consumer

  • 简介:消费者是订阅某个topic消息。
  • Group:每个消费者都有个groupid 来标定当前消费者属于哪个group。Group的作用是,当同一个group的两个消费者订阅一个topic的时候,如果当前topic没有分区那么其中一个消费者是获得不了任何消息的;如果有分区的话,将会按照数量进行负载均衡,每个消费者获得不同的分区的消息。
  • 同一个Group下的消费者不会同时订阅一个主题下的同一个分区,如果消费者数量杜宇分区数量,则多出的消费者是不会有任何消息获得的。

Broker

Broker 是一个Kafka的Server,一台单物理机或者集群都可以拥有多个broker一个broker可以容纳多个主题,这个与复制因子、主题的分区都有关系。

Kafka单机配置,一个Broker

环境:

  • win10物理机
  • Wmare Centos7虚拟机
  • XShell 访问虚拟机

配置zookeeper

  • 下载
# zookeeper
wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz
  • 解压后进入目录
cd zookeeper-3.4.13/conf
  • 复制zookeeper的配置文件
cp zoo_sample.cfg zoo.cfg
  • 返回上级进入bin目录下,键入如下命令
./zkServer.sh start
  • 查看是否成功开启zookeeper服务
#注:这里提示一下开启后提示的成功不一定是真的成功,所以需要查看一下
netstat -tunlp|egrep 2181
# 如果没有结果查看统计目录下的 zookeeper.out文件 查看log信息
# 使用jps命令查看 QuorumPeerMain是zookeeper的守护进程
11089 QuorumPeerMain
11114 Jps

配置Kafka

  • 下载安装包
# Kafka
wget http://mirror.bit.edu.cn/apache/kafka/2.1.0/kafka_2.11-2.1.0.tgz
  • 解压后进入文件夹下bin目录下
# 第一个是start.sh位置第二个是server.rpoperties的位置,所以确认好路径的正确性
./kafka-server-start.sh ./../config/server.properties &
# 我们可以在Kafka的目录下直接执行,而不进入到bin下,命令看着更舒服些
./bin/kafka-server-start.sh ./config/server.properties &
  • 查看是否开启成功:默认的Kafka端口是9092,zookeeper是2181
netstat -tunlp|egrep "(2181|9092)"
# 结果如下
[root@localhost ~]# netstat -tunlp|egrep "(2181|9092)"
tcp6 0 0 :::9092 :::* LISTEN 1877/java tcp6 0 0 :::2181 :::* LISTEN 1820/java
# jps 查看
11089 QuorumPeerMain
11458 Kafka
11847 Jps
  • 至此Kafka配置成功

使用Kafka

创建topic

./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
# 返回结果
Created topic "test"

在虚拟机用sh脚本上作为生产者生产消息

  • 我们重新开一个Xshell窗口,CD到Kafka目录/bin下,我们先介绍这一节会使用到的 kafka-console-producer.sh
# 键入如下命令
./kafka-console-producer.sh --broker-list localhost:9092 --topic test
>today message
>
# 最近本的指定,broker-list与topic是必须的参数
# 成功命令行会进入一个>的情况,键入消息按回车键就是发送消息到Kafka了
# 发送一个【today message】
  • kafka-console-producer.sh参数说明,运行./kafka-console-producer.sh --help可查看

在虚拟机上用sh脚本作为消费者消费消息

  • 重新开另个一Xshell窗口CD到Kafka目录/bin下,我们先介绍这一节会使用到的 kafka-console-consumer.sh
# 键入如下命令
./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
# 最近本的指定,bootstrap-server与topic/whitelist是必须的参数
# 由于有 from-beginning 参数 会从头load所有消息
# 消费后返回如下
today message
#在生产端键入消息后,消费端会同步消息出现
  • kafka-console-consumer.sh参数说明运行./kafka-console-consumer.sh --help可查看

使用Python作为生产者、消费者

  • 在物理机上写一个Python生产者的脚本
from kafka.producer import KafkaProducer
import time
def send_data(data):
producer = KafkaProducer(bootstrap_servers='192.168.233.138:9092')
producer.send("test",b''+str(data)+'')
producer.flush()
print ("end") if __name__=="__main__":
send_data("physics python message");
  • 查看Xshell上消费的命令行
[root@localhost ~]# /home/kafka_2.11-2.1.0/bin/kafka-console-consumer.sh --bootstrap-server 192.168.233.138:9092 --topic test --from-beginning
111
333 1
12
physics python message
  • 在物理机上写一个消费者的脚本
from kafka import KafkaConsumer
import time
def get_data(data):
consumer = KafkaConsumer('test',bootstrap_servers='192.168.233.138:9092', group_id='my_favorite_group')
print ("end")
for msg in consumer:
print(msg) if __name__=="__main__":
get_data();
  • 物理机消费者的结果
# 我这边是先运行的消费者的脚本,所以实时接收到了物理机产生的消息
ConsumerRecord(topic=u'test', partition=0, offset=5, timestamp=1551762485911L, timestamp_type=0, key=None, value='physics python message', checksum=1520092583, serialized_key_size=-1, serialized_value_size=22)
  • 测试使用虚拟机sh端的生产者发送123 消息,查看物理机消费者结果
ConsumerRecord(topic=u'test', partition=0, offset=6, timestamp=1551762784609L, timestamp_type=0, key=None, value='123', checksum=1760815061, serialized_key_size=-1, serialized_value_size=3)
  • 几点注意
# 物理机连接时可能出现【kafka.errors.NoBrokersAvailable: NoBrokersAvailable】这个错误按照如下顺序依次更改
1. 查看虚拟机防火墙是否关闭
systemctl status firewalld
systemctl stop firewalld
2. 更改kafka服务端的server.properties:
增加 [ listeners=PLAINTEXT://192.168.233.138:9092 ]这一行
3. 修改物理机的hosts文件 C:\Windows\System32\drivers\etc\hosts
增加 【虚拟机ip 虚拟机主机名】 Eg:[192.168.233.138 localhost]

使用Springboot 作为生产者、消费者

注:我直接在我的一个寄存的Spring Boot Demo项目上更改

  • 在pom.xml中添加kafka依赖
 <dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<!-- 提示一件事情此处别指定version了,直接用最新的就可以,老的版本一些包找不到 -->
  • 写一个kafka 生产者配置类
package com.example.kane.config;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern; import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory; @Configuration
@EnableKafka
public class kafka_config {
public Map<String, Object> producerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.233.138:9092");
props.put(ProducerConfig.RETRIES_CONFIG, 0);
props.put(ProducerConfig.BATCH_SIZE_CONFIG, 4096);
props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 40960);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return props;
} public ProducerFactory<String, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
} @Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<String, String>(producerFactory());
} }
  • 创建一个生产数据的Controller
package com.example.kane.Controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @RestController
@RequestMapping("/kafka")
public class CollectController {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private KafkaTemplate kafkaTemplate; @RequestMapping(value = "/send", method = RequestMethod.GET)
public void sendKafka(HttpServletRequest request, HttpServletResponse response) {
try {
String message = request.getParameter("message");
logger.info("kafka的消息={}", message);
kafkaTemplate.send("test", "key", message);
logger.info("发送kafka成功.");
} catch (Exception e) {
logger.error("发送kafka失败", e);
}
} }
  • 启动项目后,在浏览器访问http://localhost:8080/kafka/send?message=url_producer
# 查看结果
2019-03-05 13:57:16.438 INFO 10208 --- [nio-8080-exec-1] c.e.kane.Controller.CollectController : 发送kafka成功.
2019-03-05 13:57:45.871 INFO 10208 --- [nio-8080-exec-5] c.e.kane.Controller.CollectController : kafka的消息=url_producer
2019-03-05 13:57:45.872 INFO 10208 --- [nio-8080-exec-5] c.e.kane.Controller.CollectController : 发送kafka成功.
# 查看虚拟机 Consumer结果 [root@localhost ~]# /home/kafka_2.11-2.1.0/bin/kafka-console-consumer.sh --bootstrap-server 192.168.233.138:9092 --topic test --from-beginning
physics python message
123
null
url_producer
  • 增加消费者的配置
package com.example.kane.config;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.config.KafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; import java.util.HashMap;
import java.util.Map; import com.example.kane.service.kafka_listener;
@Configuration
@EnableKafka
public class kafka_consumer_config {
@Bean
public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
} public ConsumerFactory<String, String> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
} public Map<String, Object> consumerConfigs() {
Map<String, Object> propsMap = new HashMap<>();
propsMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.233.138:9092");
propsMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
propsMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
propsMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
propsMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test");
return propsMap;
}
@Bean
public kafka_listener listener() {
return new kafka_listener();
}
}
  • 增加listener类
package com.example.kane.service;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener;
public class kafka_listener {
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @KafkaListener(topics = {"test"})
public void listen(ConsumerRecord<?, ?> record) {
logger.info(record.toString());
logger.info("kafka的key: " + record.key());
logger.info("kafka的value: " + record.value().toString());
}
}
  • 同样我们用访问http://localhost:8080/kafka/send?message=url_producer1重新发一个消息
# 结果
2019-03-05 14:31:04.787 INFO 10208 --- [nio-8080-exec-1] c.e.kane.Controller.CollectController : 发送kafka成功.
2019-03-05 14:31:04.848 INFO 10208 --- [ntainer#0-0-C-1] com.example.kane.service.kafka_listener : ConsumerRecord(topic = test, partition = 0, offset = 10, CreateTime = 1551767464787, serialized key size = 3, serialized value size = 13, headers = RecordHeaders(headers = [], isReadOnly = false), key = key, value = url_producer1)
2019-03-05 14:31:04.848 INFO 10208 --- [ntainer#0-0-C-1] com.example.kane.service.kafka_listener : kafka的key: key
2019-03-05 14:31:04.848 INFO 10208 --- [ntainer#0-0-C-1] com.example.kane.service.kafka_listener : kafka的value: url_producer1
# 查看虚拟机 消费者信息
physics python message
123
null
url_producer
url_producer1
url_producer1

一些需要注意的问题

  1. 现在kafka官方提供自带zookeeper版本,不建议使用自带的,还是建议自己安装zookeeper
  2. 物理机没法访问的时候,看文中的注意事项,依次更改一定能访问

Kafka 概念、单机搭建与使用的更多相关文章

  1. Kafka【第一篇】Kafka集群搭建

    Kafka初识 1.Kafka使用背景 在我们大量使用分布式数据库.分布式计算集群的时候,是否会遇到这样的一些问题: 我们想分析下用户行为(pageviews),以便我们设计出更好的广告位 我想对用户 ...

  2. 【转】kafka集群搭建

    转:http://www.cnblogs.com/luotianshuai/p/5206662.html Kafka初识 1.Kafka使用背景 在我们大量使用分布式数据库.分布式计算集群的时候,是否 ...

  3. zookeeper与Kafka集群搭建及python代码测试

    Kafka初识 1.Kafka使用背景 在我们大量使用分布式数据库.分布式计算集群的时候,是否会遇到这样的一些问题: 我们想分析下用户行为(pageviews),以便我们设计出更好的广告位 我想对用户 ...

  4. Linux下kafka集群搭建过程记录

    环境准备 zookeeper集群环境kafka是依赖于zookeeper注册中心的一款分布式消息对列,所以需要有zookeeper单机或者集群环境. 三台服务器: 172.16.18.198 k8s- ...

  5. Linux下kafka集群搭建

    环境准备 zookeeper集群环境 kafka是依赖于zookeeper注册中心的一款分布式消息对列,所以需要有zookeeper单机或者集群环境. 三台服务器: 172.16.18.198 k8s ...

  6. kafka集群搭建及结合springboot使用

    1.场景描述 因kafka以前用的不多,只往topic中写入和读取过数据,这次刚好又要用到,记录下kafka集群搭建及结合springboot使用. 2. 解决方案 2.1 简单介绍 (一)关于kaf ...

  7. 消息队列之 kafka 集群搭建

    我们先弄清楚kafka集群环境首先需要些什么 JDK 10+ Zookeeper Kafka 2.x 首先准备三台虚拟机 centos7 ,更改IP地址为静态地址分别为,29.30.31 cd /et ...

  8. kafka集群搭建和使用Java写kafka生产者消费者

    1 kafka集群搭建 1.zookeeper集群  搭建在110, 111,112 2.kafka使用3个节点110, 111,112 修改配置文件config/server.properties ...

  9. 单机搭建Android开发环境(二)

    前文介绍了如何优化SSD和内存,以发挥开发主机的最佳性能,同时提到在SSD上创建虚拟机.为什么不装双系统呢?双系统性能应该会更好!采用Windows+虚拟机的方式,主要是考虑到安卓开发和日常办公两方面 ...

随机推荐

  1. jsp 修饰 Request 及Response

    Servlet API包含4个可修饰的类,用于改变Servlet Request以及Servlet Response.这种修饰允许修改 ServletRequest以及ServletResponse或 ...

  2. LabView(控件部分)

    1.虚拟仪器的概述: 虚拟仪器是基于计算机的的仪器,计算机和仪器的密切结合是目前仪器的一个发展方向,大概有两种结合方式,一种是将计算机装入仪器中,实例就是只能化的仪器,流行的嵌入式系统的仪器,另一种就 ...

  3. cf1084d 非常巧妙的树形dp

    /* 给定n城市,m条道路,每条路耗油w,每个点有油a[i],从任意点出发,求最大可以剩下的油 dp[i]表示从i开始往下走的最大收益,ans表示最大结果 因为走过的路不能走,所以可以想到最优解肯定经 ...

  4. js变量前的+是什么意思

    js变量前的+是什么意思   if (+value >= distance) {} 这个+什么意思 可以理解为 Number(value) 会将其按照Number函数的规则转换为数值或者NaN, ...

  5. java读取pdf和MS Office文档

    有时候PDF中的文字无法复制,这可能是因为PDF文件加密了,不过使用PDFBox开源软件就可以把它读出来. 还有一个用于创建PDF文件的项目----iText. PDFBox下面有两个子项目:Font ...

  6. 集腋成裘-06-angularJS -angular_02

    1.0 选项卡 其中涉及到了三目运算符号; <!DOCTYPE html> <html ng-app="test"> <head> <me ...

  7. Java利用POI读取Excel

    官网直接下载POI  http://poi.apache.org/ package com.CommonUtil; import java.io.File; import java.io.FileIn ...

  8. 常见的爬虫分析库(2)-xpath语法

    xpath简介 1.xpath使用路径表达式在xml和html中进行导航 2.xpath包含标准函数库 3.xpath是一个w3c的标准 xpath节点关系 1.父节点 2.子节点 3.同胞节点 4. ...

  9. 设置git记住用户和密码

     git config --global credential.helper store

  10. webpack学习笔记--配置devServer

    devServer 1-6 使用DevServer 介绍过用来提高开发效率的 DevServer ,它提供了一些配置项可以改变 DevServer 的默认行为. 要配置 DevServer ,除了在配 ...