异步消息-kaffa
Kafka 是一个消息代理。Kafka topic 被复制到集群中的所有 broker 中,Kafka 集群由多个 broker 组成。集群中的每个节点充当一个或多个 topic 的 leader,负责该 topic 的数据并将其复制到集群中的其他节点。
一、在spring中设置kafka
在pom.xml引入依赖:
Kafka 没有 Spring Boot starter。
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
当Kafka 服务器之一运行在 kafka.springlearndemo.com 上,并监听 9092 端口是。
在application.yml
或application.properties
配置文件中配置spring.kafka.bootstrap-servers 属性
application.yml
可以这么配置:
spring:
kafka:
bootstrap-servers:
- kafka.springlearndemo.com:9092
如果有多个,spring.kafka.bootstrap-servers
属性接受一个列表,可以如下配置:
spring:
kafka:
bootstrap-servers:
- kafka.springlearndemo.com:9092
- kafka.springlearndemo.com:9093
- kafka.springlearndemo.com:9094
二、使用 KafkaTemplate 发送消息
主要方法:
ListenableFuture<SendResult<K, V>> send(String topic, V data);
ListenableFuture<SendResult<K, V>> send(String topic, K key, V data);
ListenableFuture<SendResult<K, V>> send(String topic, Integer partition, K key, V data);
ListenableFuture<SendResult<K, V>> send(String topic, Integer partition, Long timestamp, K key, V data);
ListenableFuture<SendResult<K, V>> send(ProducerRecord<K, V> record);
ListenableFuture<SendResult<K, V>> send(Message<?> message);
ListenableFuture<SendResult<K, V>> sendDefault(V data);
ListenableFuture<SendResult<K, V>> sendDefault(K key, V data);
ListenableFuture<SendResult<K, V>> sendDefault(Integer partition, K key, V data);
ListenableFuture<SendResult<K, V>> sendDefault(Integer partition, Long timestamp, K key, V data);
KafkaTemplate没有convertAndSend()方法,因为 KafkaTemplate 是用的泛型,同时能够在发送消息时直接处理域类型,所有的 send() 方法都在做 convertAndSend() 的工作。
使用 Kafka 发送消息时,可以指定参数:
发送消息的 topic(send() 方法必要的参数)
写入 topic 的分区(可选)
发送记录的键(可选)
时间戳(可选;默认为 System.currentTimeMillis())
payload(必须)
使用 KafkaTemplate 及其 send() 方法,如:
package test.springlearndemo.messaging;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
@Service
public class KafkaOrderMessagingService{
private KafkaTemplate<String, Order> kafkaTemplate;
@Autowired
public KafkaOrderMessagingService(KafkaTemplate<String, Order> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
// sendOrder方法1,消息发送
@Override
public void sendOrder(Order order) {
// 向名为springlearndemo.orders.topic 的主题发送 Order
kafkaTemplate.send("springlearndemo.orders.topic", order);
}
}
若在application.yml
或者application.properties
配置文件中,设置了默认主题。
application.yml
:
spring:
kafka:
template:
default-topic: springlearndemo.orders.topic
上面代码中sendOrder方法1可以简化如下:
@Override
public void sendOrder(Order order) {
kafkaTemplate.sendDefault(order);
}
三、Kafka 监听器
消费 Kafka 主题的消息的唯一方法是用消息监听器。
@KafkaListener
注解的方法。
package test.springlearndemo.messaging.kafka.listener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import test.springlearndemo.Order;
@Component
public class OrderListener {
// ...
// handle方法1。当消息到达名为 springlearndemo.orders.topic 的主题时应该调用它。
@KafkaListener(topics="springlearndemo.orders.topic")
public void handle(Order order) {
// ...
}
}
如果需要来自消息的其他元数据,它也可以接受一个 ConsumerRecord 或 Message 对象。
修改上面的handle方法1,如:
// handle方法2
@KafkaListener(topics="springlearndemo.orders.topic")
public void handle(Order order, ConsumerRecord<Order> record) {
log.info("接收到 partition {} , 时间 {}",
record.partition(), record.timestamp());
// todo...
}
也可以使用Message,如:
// handle方法3
@KafkaListener(topics="springlearndemo.orders.topic")
public void handle(Order order, Message<Order> message) {
MessageHeaders headers = message.getHeaders();
log.info("接收到 from partition {} ,时间 {}",
headers.get(KafkaHeaders.RECEIVED_PARTITION_ID)
headers.get(KafkaHeaders.RECEIVED_TIMESTAMP));
// todo...
}