spring整合kafka简单单元测试
kafka简介:
Kafka 是一种分布式的,基于发布 / 订阅的消息系统。主要设计目标如下:
- 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间复杂度的访问性能。
- 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒 100K 条以上消息的传输。
- 支持 Kafka Server 间的消息分区,及分布式消费,同时保证每个 Partition 内的消息顺序传输。
- 同时支持离线数据处理和实时数据处理。
- Scale out:支持在线水平扩展。
一:配置文件
1.1:pom.xml中加入kafka依赖
<!--kafka--> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.2.4.RELEASE</version> </dependency>
1.2:导入生产者的xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--参数配置 --> <bean id="producerProperties" class="java.util.HashMap"> <constructor-arg> <map> <!-- kafka服务地址,可能是集群 value="localhost:9092,localhost:9093,localhost:9094"--> <entry key="bootstrap.servers" value="ip地址:9092" /> <!--有可能导致broker接收到重复的消息 默认是0--> <entry key="retries" value="3" /> <!--acks=0, 表示生产者在成功写入消息之前不会等待任何来自服务器的响应--> <!--acks=1, 表示只要集群的leader分区副本接收到了消息,就会向生产者发送一个成功响应的ack--> <!--acks=all, 表示只要所有参与复制的1节点(ISR列表的副本)全部收到消息时,生产者才会接收到来自服务器的响应--> <entry key="ack" value="1" /> <!--producer可以用来缓存数据的内存大小,如果数据产生速度大于向broker发送的速度,producer会阻塞或者抛出异常--> <entry key="buffer.memory" value="33554432" /> <entry key="key.serializer" value="org.apache.kafka.common.serialization.StringSerializer" /> <entry key="value.serializer" value="org.apache.kafka.common.serialization.StringSerializer" /> </map> </constructor-arg> </bean> <!-- 创建kafkatemplate需要使用的producerfactory bean --> <bean id="producerFactory" class="org.springframework.kafka.core.DefaultKafkaProducerFactory"> <constructor-arg> <ref bean="producerProperties" /> </constructor-arg> </bean> <!-- 创建kafkatemplate bean,使用的时候,只需要注入这个bean,即可使用template的send消息方法 --> <bean id="kafkaTemplate" class="org.springframework.kafka.core.KafkaTemplate"> <constructor-arg ref="producerFactory" /> <!--设置对应topic test -是后台已经创建好的主题--> <property name="defaultTopic" value="test" /> </bean> </beans>
1.3:导入消费者xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--消息监听器--> <bean id="messageListenerContainer" class="org.springframework.kafka.listener.KafkaMessageListenerContainer" init-method="doStart"> <constructor-arg ref="consumerFactory" /> <constructor-arg ref="containerProperties" /> </bean> <!-- 记得修改主题 --> <bean id="containerProperties" class="org.springframework.kafka.listener.ContainerProperties"> <!-- 构造函数 就是 主题的参数值 --> <constructor-arg value="test" /> <!-- 自定义个消息监听器 --> <property name="messageListener" ref="myListnener" /> <!--手工确定--> <property name="ackMode" value="MANUAL"></property> </bean> <!-- -消息监听器 --> <bean id="myListnener" class="com.zcb.kafka.MyMessageListener"></bean> <!-- 创建consumerFactory bean --> <bean id="consumerFactory" class="org.springframework.kafka.core.DefaultKafkaConsumerFactory"> <constructor-arg> <ref bean="consumerProperties" /> </constructor-arg> </bean> <bean id="consumerProperties" class="java.util.HashMap"> <constructor-arg> <map> <!--Kafka服务地址 --> <entry key="bootstrap.servers" value="ip地址:9092" /> <!--Consumer的组ID,相同group.id的consumer属于同一个组。 --> <entry key="group.id" value="test-consumer-group" /> <!--如果此值设置为true,consumer会周期性的把当前消费的offset值保存到zookeeper。当consumer失败重启之后将会使用此值作为新开始消费的值。 --> <entry key="enable.auto.commit" value="false" /> <!--当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费--> <entry key="auto-offset-reset" value="earliest"></entry> <!--网络请求的socket超时时间。实际超时时间由max.fetch.wait + socket.timeout.ms 确定 --> <entry key="session.timeout.ms" value="15000" /> <entry key="key.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer" /> <entry key="value.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer" /> </map> </constructor-arg> </bean> </beans>
1.4:添加监听器实体类,以及用于启动消费者的实体类
//消费者监听器 public class MyMessageListener implements AcknowledgingMessageListener<String,String> { @Override public void onMessage(ConsumerRecord<String, String> data, Acknowledgment acknowledgment) { String key = data.key(); String value = data.value(); if(key.equals("request")){ String s = JSON.parseObject(value, String.class); System.out.println(s); //确定接收 acknowledgment.acknowledge(); } } }
//启动消费者 public class KafKaMain { public static void main(String[] args) { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring-kafka-consumer.xml"); } }
二:启动生产者消费者
2.1:测试类
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring-kafka-producer.xml") public class MyTest { @Autowired KafkaTemplate kafkaTemplate; @Test public void testKafka(){ kafkaTemplate.sendDefault("request", JSON.toJSONString("hello,Word!")); } }
2.2:效果
我有一杯酒,足以慰风尘。