Spring Boot2.0 整合 Kafka
Kafka 概述
Apache Kafka 是一个分布式流处理平台,用于构建实时的数据管道和流式的应用.它可以让你发布和订阅流式的记录,可以储存流式的记录,并且有较好的容错性,可以在流式记录产生时就进行处理。
Apache Kafka是分布式发布-订阅消息系统,在 kafka官网上对 Kafka 的定义:一个分布式发布-订阅消息传递系统。
Kafka 特性
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作;
- 可扩展性:kafka集群支持热扩展;
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失;
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败);
- 高并发:支持数千个客户端同时读写;
- 支持实时在线处理和离线处理:可以使用Storm这种实时流处理系统对消息进行实时进行处理,同时还可以使用Hadoop这种批处理系统进行离线处理;
Kafka 使用场景
- 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如Hadoop、Hbase、Solr等;
- 消息系统:解耦和生产者和消费者、缓存消息等;
- 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到Hadoop、数据仓库中做离线分析和挖掘;
- 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告;
- 流式处理:比如spark streaming和storm;
- 事件源;
Spring Boot2.0 + Kafka
1,安装配置Kafka ,Zookeeper
安装和配置过程很简单,就不详细说了,参考官网:http://kafka.apache.org/quickstart
使用命令启动Kafka: bin``/kafka-server-start``.sh config``/server``.properties
下面给出我的环境:
Centos 7.5, Kafka 2.11, Zookeeper-3.4.13, JDK1.8+
2,创建 Spring Boot 项目
注意版本:该项目使用Spring Boot 2.0 +,低版本可能不对
- pom.xml引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
- 定义消息生产者
直接使用 KafkaTemplate 发送消息 ,Spring Boot自动装配,不需要自己定义一个Kafka配置类,吐槽一下网站的文章,全都是互相抄,全都写一个 ProduceConfig Consumerconfig 类, Kafka 的参数配置 硬编码在代码中,简直无法直视。。
定义一个泛型类KafkaSender<T>T 就是你需要发送的消息 对象,序列化使用阿里的 fastjson
消息发送后,可以在回调类里面处理自己的业务,ListenableFutureCallback 类有两个方法,分别是 onFailureon 和 onSuccess ,实际场景可以在这两个方法,处理自己的具体业务,这里不做实现。
/**
* 消息生产者
*
* @author Jarvis
* @date 2018/8/3
*/
@Component
public class KafkaSender<T> {
private Logger logger = LoggerFactory.getLogger(KafkaSender.class);
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
/**
* kafka 发送消息
*
* @param obj 消息对象
*/
public void send(T obj) {
String jsonObj = JSON.toJSONString(obj);
logger.info("------------ message = {}", jsonObj);
//发送消息
ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send("kafka.tut", jsonObj);
future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
@Override
public void onFailure(Throwable throwable) {
logger.info("Produce: The message failed to be sent:" + throwable.getMessage());
}
@Override
public void onSuccess(SendResult<String, Object> stringObjectSendResult) {
//TODO 业务处理
logger.info("Produce: The message was sent successfully:");
logger.info("Produce: _+_+_+_+_+_+_+ result: " + stringObjectSendResult.toString());
}
});
}
}
- 定义消息消费者
使用@KafkaListener注解监听 topics 消息,此处的topics必须和 send 函数中的 一致
@Header(KafkaHeaders.RECEIVED_TOPI 直接获取 topic
/**
* 监听kafka.tut 的 topic
*
* @param record
* @param topic topic
*/
@KafkaListener(id = "tut", topics = "kafka.tut")
public void listen(ConsumerRecord<?, ?> record, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
//判断是否NULL
Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) {
//获取消息
Object message = kafkaMessage.get();
logger.info("Receive: +++++++++++++++ Topic:" + topic);
logger.info("Receive: +++++++++++++++ Record:" + record);
logger.info("Receive: +++++++++++++++ Message:" + message);
}
}
- 配置文件 application.yml
spring:
application:
name: kafka-tutorial
kafka:
# 指定kafka 代理地址,可以多个
bootstrap-servers: 192.168.10.100:9092
producer:
retries: 0
# 每次批量发送消息的数量
batch-size: 16384
# 缓存容量
buffer-memory: 33554432
# 指定消息key和消息体的编解码方式
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
consumer:
# 指定默认消费者group id
group-id: consumer-tutorial
auto-commit-interval: 100
auto-offset-reset: earliest
enable-auto-commit: true
# 指定消息key和消息体的编解码方式
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 指定listener 容器中的线程数,用于提高并发量
listener:
concurrency: 3
- 直接使用 @Autowired 对类 KafkaSender 自动装配,然后调用 send 方法发送消息即可,下面给出代码:
@Autowired
private KafkaSender<User> kafkaSender;
@Test
public void kafkaSend() throws InterruptedException {
//模拟发消息
for (int i = 0; i < 5; i++) {
User user = new User();
user.setId(System.currentTimeMillis());
user.setMsg(UUID.randomUUID().toString());
user.setSendTime(new Date());
kafkaSender.send(message);
Thread.sleep(3000);
}
}
控制台可以看到执行成功:

在服务器执行 bin/kafka-topics.sh --list --zookeeper localhost:2181 可以看到topic

Kafka如何保证数据的不丢失
1.生产者数据的不丢失
- 新版本的producer采用异步发送机制。KafkaProducer.send(ProducerRecord)方法仅仅是把这条消息放入一个缓存中(即RecordAccumulator,本质上使用了队列来缓存记录),同时后台的IO线程会不断扫描该缓存区,将满足条件的消息封装到某个batch中然后发送出去。显然,这个过程中就有一个数据丢失的窗口:若IO线程发送之前client端挂掉了,累积在accumulator中的数据的确有可能会丢失。 kafka的ack机制:在kafka发送数据的时候,每次发送消息都会有一个确认反馈机制,确保消息正常的能够被收到。
- 如果是同步模式:ack机制能够保证数据的不丢失,如果ack设置为0,风险很大,一般不建议设置为0
producer.type=sync
request.required.acks=1 - 如果是异步模式:通过buffer来进行控制数据的发送,有两个值来进行控制,时间阈值与消息的数量阈值,如果buffer满了数据还没有发送出去,如果设置的是立即清理模式,风险很大,一定要设置为阻塞模式
producer.type=async
request.required.acks=1
queue.buffering.max.ms=5000
queue.buffering.max.messages=10000
queue.enqueue.timeout.ms = -1
batch.num.messages=200 - 结论:producer有丢数据的可能,但是可以通过配置保证消息的不丢失
2.消费者数据的不丢失 - 如果在消息处理完成前就提交了offset,那么就有可能造成数据的丢失。由于Kafka consumer默认是自动提交位移的,所以在后台提交位移前一定要保证消息被正常处理了,因此不建议采用很重的处理逻辑,如果处理耗时很长,则建议把逻辑放到另一个线程中去做。为了避免数据丢失,现给出两点建议:
enable.auto.commit=false 关闭自动提交位移
在消息被完整处理之后再手动提交位移 - 如果使用了storm,要开启storm的ackfail机制;
- 如果没有使用storm,确认数据被完成处理之后,再更新offset值。低级API中需要手动控制offset值。通过offset commit 来保证数据的不丢失,kafka自己记录了每次消费的offset数值,下次继续消费的时候,接着上次的offset进行消费即可。
源码 github:https://github.com/jarvisqi/java-tutorial/tree/master/kafka-tutorial
参考:
- http://kafka.apache.org/quickstart
- https://docs.spring.io/spring-kafka/reference/htmlsingle/#kafka
- https://blog.csdn.net/tzs_1041218129/article/details/78988439
Spring Boot2.0 整合 Kafka的更多相关文章
- 手把手教你Spring Boot2.x整合kafka
首先得自己搭建一个kafka,搭建教程请自行百度,本人是使用docker搭建了一个单机版的zookeeper+kafka作为演示,文末会有完整代码包提供给大家下载参考 废话不多说,教程开始 一.老规矩 ...
- 基于Redis的消息队列使用:spring boot2.0整合redis
一 . 引入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="ht ...
- 【spring boot】整合LCN,启动spring boot2.0.3 启动报错:Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
spring boot 2.0.3启动报错: Error starting ApplicationContext. To display the conditions report re-run yo ...
- Spring Boot2.0之整合事物管理
首先Spring 事务分类 1.声明事务 原理:基于编程事务的 2.编程事务 指定范围 扫包去解决 3.事务原理:AOP技术 通过环绕通知进行了拦截 使用Spring 事务注意事项: 不要tr ...
- spring boot 2.0(一)权威发布spring boot2.0
Spring Boot2.0.0.RELEASE正式发布,在发布Spring Boot2.0的时候还出现一个小插曲,将Spring Boot2.0同步到Maven仓库的时候出现了错误,然后Spring ...
- Spring Boot2.0 设置拦截器
所有功能完成 配置登录认证 配置拦截器 在spring boot2.0 之后 通过继承这个WebMvcConfigurer类 就可以完成拦截 新建包com.example.interceptor; 创 ...
- Spring Boot2.0 静态资源被拦截问题
在Spring Boot2.0+的版本中,只要用户自定义了拦截器,则静态资源会被拦截.但是在spring1.0+的版本中,是不会拦截静态资源的. 因此,在使用Spring Boot2.0+时,配置拦截 ...
- Spring Boot2.0使用Spring Security
一.Spring Secutity简介 Spring 是一个非常流行和成功的 Java 应用开发框架.Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性 ...
- spring boot2.0(一 ) 基础环境搭建
1.基础配置 开发环境:window jdk版本:1.8(spring boot2.0最低要求1.8) 开发工具:eclipse 构建方式:maven3 2.POM配置文件 <project x ...
随机推荐
- Android 7.0 新特性
Android7.0提供新功能以提升性能.生产效率和安全性. 关于Android N的性能改进,Android N建立了先进的图形处理Vulkan系统,能少的减少对CPU的占用.与此同时,Androi ...
- 对display主要属性的探究,以及vertical-aligin
display 首先要简单说明一下display的主要3个主要属性,分别为block,inline-block,inline,这里只提及主要,关于其他的inherit,none等可以自行了解 inli ...
- LeetCode题解之Clone Graph
1.题目描述 2.问题分析 要遍历图,然后标记没有被复制的节点. 3.代码 class Solution { private: unordered_map<Node*, Node*> m; ...
- myeclipse10 blue版激活码
http://blog.itpub.net/27042095/viewspace-1164998/
- SQL SERVER 查询表的各字段长度
SELECT a.name,b.name,c.DATA_TYPE,b.max_length FROM sys.tables a join sys.columns b on b.object_id = ...
- 关于Box Anemometer的安装配置遇到的几个坑
Box Anemometer是一个非常不错的MySQL慢查询可视化工具平台,具体就不多详述了,官网是https://github.com/box/Anemometer 最近动自己动手搭了一个,具体搭建 ...
- css点滴3—5种方式实现圆环
使用css实现圆环,最简单的方式就是使用嵌套标签,设置border-radius就可以实现,但是这个是最简单的方式,这篇文章我们介绍5种方式实现圆环. 1.两个标签嵌套 html代码: <div ...
- 【夯实PHP基础】PHPUnit -- PHP测试框架
本文地址 分享提纲: 1.概述 2.安装 3.编写第一个测试用例 4.PHPUnit高级 5.参考 1.概述 1)[测试框架] 它是一款轻量级的PHP测试框架,是一个xUnit的体系结构的单元测试框架 ...
- 《Java大学教程》—读后总结
1.坚持就是胜利. 中间启动了许多次,但又因为各种原因被停.就连闭关学习期间,也多次想放弃,总觉得太简单,最后还是选择了这本书而放弃了其他书,原因是马上要还书了,"书是非借不能读!" ...
- HDFS的dfs.replication不同验证
对于上传文件到hdfs上时,当时hadoop的副本系数是几,这个文件的块数副本数就会有几份,无论以后你怎么更改系统副本系统,这个文件的副本数都不会改变,也就说上传到分布式系统上的文件副本数由当时的系统 ...