手写MQ入门介绍了消息队列的基本概念、应用场景以及实现过程。文章详细讲解了开发环境搭建、数据结构与算法基础、网络编程和并发模型等准备工作,并通过具体示例演示了消息队列的实现和优化方法。此外,还提供了实战案例,展示了手写MQ在实际项目中的应用。
消息队列简介 什么是消息队列消息队列是一种异步通信技术,主要用于在分布式系统中实现组件之间的解耦。消息队列允许生产者将消息发送到队列中,然后消费者从队列中读取消息进行处理。这种机制提供了松耦合的架构,使得不同服务之间可以独立运行,不受彼此的影响。
消息队列可以理解为中间件,它提供了一种标准的消息传递机制,用于在分布式系统中实现异步通信。消息队列可以保证生产者和消费者之间的解耦和异步处理,使得系统更加灵活和稳定。例如,生产者可以将消息发送到队列中,然后立即返回响应,而消费者可以在适当的时间从队列中读取消息并进行处理。这种方式减轻了生产者和消费者之间的直接依赖关系,提高了系统的可维护性和扩展性。
消息队列的作用和应用场景消息队列在现代软件开发中扮演着重要角色,它可以用于多种场景以提高系统性能和稳定性。以下是一些常见的应用场景:
-
异步处理:当一个应用程序需要异步处理某个任务时,可以将任务放入消息队列,然后直接返回响应给客户端。后台的服务可以异步从消息队列中读取消息并处理。
-
解耦架构:不同服务之间通过消息队列进行通信可以做到解耦,使得服务间的交互更加灵活。当服务A需要调用服务B时,它可以将请求放入消息队列,服务B可以在适当的时间从队列中读取消息并处理。这种方式减少了服务之间的直接依赖,提高了系统的可维护性和扩展性。
-
流量削峰:在高并发场景下,消息队列可以帮助系统削峰填谷,通过缓冲机制来平滑流量的峰值,保证系统在高负载下仍然能够保持稳定。
-
系统解耦:通过消息队列,可以将系统模块之间解耦,使得各模块可以独立开发、部署和扩展。当某个模块需要升级或者维护时,不会影响到其他模块的运行。
- 数据同步:消息队列可以用于数据同步,比如从一个系统同步数据到另一个系统。生产者可以将数据发送到消息队列,消费者从队列中读取数据并将其写入目标系统。
消息队列是一个涵盖广泛的技术领域,不同的实现和框架适用于不同的需求和场景。以下是几种常见的消息队列系统:
-
RabbitMQ:RabbitMQ 是一个开源的消息代理实现,具有高级的消息路由功能。它支持多种消息协议,包括AMQP (高级消息队列协议)。RabbitMQ 支持多种消息传递模式,如发布/订阅、点对点、请求/响应等。它还支持持久化消息和事务等高级特性。
-
Kafka:Apache Kafka 是一个分布式流处理平台,它可以用于构建实时数据管道和流应用。Kafka 通过分布式日志的方式来处理和存储消息,具有高吞吐量和持久化存储的能力。Kafka 还支持水平扩展,可以轻松地扩展到多个节点。
-
RocketMQ:RocketMQ 是阿里巴巴开源的一个分布式消息中间件,它提供了高吞吐量、低延迟的消息传递服务。RocketMQ 支持多种消息模式,如发布/订阅、顺序消息、事务消息等。它还具有丰富的消息过滤和路由功能,支持多种集群模式的部署。
-
ActiveMQ:ActiveMQ 是一个开源的、功能丰富的消息代理,支持多种消息协议,如AMQP、STOMP、OpenWire等。它提供了多种消息传递模式,如点对点、发布/订阅等,并且支持多种消息传递模式。ActiveMQ 还支持持久化消息和事务等特性。
-
RabbitMQ与Kafka的对比:RabbitMQ 和 Kafka 都是流行的开源消息队列系统,但它们的设计目标和应用场景有所不同。RabbitMQ 的设计目标是提供一个可靠的分布式消息传递系统,它支持多种消息传递模式,如发布/订阅、点对点等。Kafka 的设计目标是提供一个高吞吐量、低延迟的消息传递系统,它通过分布式日志的方式来处理和存储消息。Kafka 还支持水平扩展,可以轻松地扩展到多个节点。RabbitMQ 适用于需要高可靠性和灵活性的场景,如实时消息传递和工作流处理。Kafka 适用于需要高吞吐量和持久化存储的场景,如实时数据管道和流应用。
-
RocketMQ与ActiveMQ的对比:RocketMQ 和 ActiveMQ 都是流行的开源消息队列系统,但它们的设计目标和应用场景有所不同。RocketMQ 的设计目标是提供一个高吞吐量、低延迟的消息传递系统,适用于需要高吞吐量和持久化存储的场景,如实时数据处理和在线事务处理。RocketMQ 还支持多种消息传递模式,如发布/订阅、顺序消息、事务消息等。ActiveMQ 的设计目标是提供一个功能丰富的消息传递系统,它可以支持多种消息协议,如AMQP、STOMP、OpenWire等。ActiveMQ 还支持多种消息传递模式,如点对点、发布/订阅等,并且支持持久化消息和事务等特性。RocketMQ 适用于需要高吞吐量和持久化存储的场景,如实时数据处理和在线事务处理。ActiveMQ 适用于需要多种消息协议和功能丰富的场景,如实时消息传递和工作流处理。
- 其他消息队列:除了上述几种常见的消息队列系统外,还有其他一些消息队列系统,如ZeroMQ、NSQ、Apache Pulsar等。这些消息队列系统各有特点和优势,适用于不同的应用场景。ZeroMQ 是一个高性能的消息库,它可以用于构建异步和分布式通信系统。NSQ 是一个分布式消息队列系统,它可以用于构建实时数据管道和流应用。Apache Pulsar 是一个分布式消息流系统,它可以用于构建实时数据管道和流应用。这些消息队列系统各有特点和优势,适用于不同的应用场景。
在消息队列(Message Queue)系统中,生产者(Producer)和消费者(Consumer)是两个重要概念。生产者负责生成消息并将其发送到队列,而消费者则负责从队列中读取消息并进行处理。生产者和消费者之间通过消息队列进行交互,实现了松耦合的架构。
-
生产者:生产者是指创建和发送消息到队列中的服务或应用程序。在生产者中,首先需要创建一个消息,这个消息可以包含数据和元数据。然后,生产者将消息发送到消息队列。生产者可以是任何能够生成消息的服务或应用程序,如一个Web应用、一个API、一个脚本等。
-
消费者:消费者是指从队列中读取消息并进行处理的服务或应用程序。在消费者中,首先需要从消息队列中读取消息。然后,消费者将解析消息并执行相应的处理逻辑。消费者可以是任何能够处理消息的服务或应用程序,如一个后台任务、一个微服务、一个脚本等。
- 生产者和消费者之间的交互:生产者和消费者之间的交互通过消息队列进行,实现了松耦合的架构。生产者和消费者之间不需要知道对方的存在,也不需要直接进行交互。生产者只需要将消息发送到队列中,消费者只需要从队列中读取消息即可。
消息队列系统通常支持两种主要类型的消息传递模式:点对点(Point-to-Point)和发布/订阅(Publish/Subscribe)。
-
点对点(Point-to-Point)模式:是指消息只被一个消费者接收和处理。在这种模式下,生产者发送的消息只会被一个消费者接收。当一个消息被一个消费者接收后,该消息即被移出队列。点对点模式适用于需要精确消息传递的场景,如请求/响应、命令/响应等。在点对点模式下,消息的传递是确定的,即每个消息只会被一个消费者接收。这种方式适用于需要精确消息传递的场景,如请求/响应、命令/响应等。
- 发布/订阅(Publish/Subscribe)模式:是指消息可以被多个消费者接收和处理。在这种模式下,生产者发送的消息会被多个消费者接收。当一个消息被多个消费者接收后,该消息不会被移出队列,而是会被多个消费者各自处理。发布/订阅模式适用于需要广播消息的场景,如日志、事件等。在发布/订阅模式下,消息的传递是广播式的,即每个消息会被多个消费者接收。这种方式适用于需要广播消息的场景,如日志、事件等。
消息队列支持多种消息传递模式,包括同步和异步传递。
-
同步传递:同步传递是指消息发送者(生产者)在发送消息后,会等待消息被接收者(消费者)接收并处理后才继续执行。这种方式适用于需要确认消息已被接收和处理的场景,如请求/响应模式。在同步传递模式下,生产者在发送消息后,会等待消费者接收并处理消息。
- 异步传递:异步传递是指消息发送者(生产者)在发送消息后,不会等待消息被接收者(消费者)接收和处理,而是继续执行其他任务。这种方式适用于不需要等待消息被接收和处理的场景,如日志、事件等。在异步传递模式下,生产者在发送消息后,不会等待消费者接收并处理消息,而是继续执行其他任务。
在开发消息队列之前,需要搭建好开发环境。首先选择合适的编程语言和开发工具,这将直接影响到后续开发的效率和效果。在选择编程语言时,需要考虑语言的生态系统、社区支持、开发效率等因素。常用的编程语言包括Java、Python、Go等,这些语言都有丰富的消息队列库和框架支持。
-
编程语言选择:选择编程语言时,需要考虑以下几个因素:
- 生态系统:选择一个有丰富生态系统和工具支持的语言可以大大提高开发效率。
- 社区支持:选择社区活跃、有大量开发者支持的语言可以更容易地解决问题。
- 性能要求:不同的应用场景可能对性能有不同的要求,选择合适的语言可以更好地满足需求。
- 开发经验:选择自己熟悉的语言可以更快地上手开发。
-
IDE配置:选择合适的集成开发环境(IDE),并进行必要的配置。常用的IDE包括Eclipse、IntelliJ IDEA、PyCharm、Visual Studio等,这些IDE都有丰富的插件和工具支持。
- 开发工具:选择合适的开发工具,如代码编辑器、Git版本控制工具、调试工具等。常用的开发工具包括Visual Studio Code、Sublime Text、Git、Postman等。
以下是一个简单的示例,演示如何在Eclipse中配置Java开发环境:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
在Eclipse中创建一个新的Java项目,并添加以上代码。然后运行程序,确保开发环境已经正确配置。
数据结构与算法基础消息队列的核心是数据结构,正确设计数据结构可以提高消息队列的性能和可靠性。消息队列一般使用队列、链表、树等数据结构来实现。例如,可以使用链表来实现消息队列,链表可以高效地插入和删除元素,适用于消息队列的插入和删除操作。同时,需要掌握一些基本的算法理论,如排序、查找、图算法等,这些算法可以应用于消息队列的优化和扩展。
以下是一个简单的链表示例:
public class Node {
public int value;
public Node next;
public Node(int value) {
this.value = value;
this.next = null;
}
}
public class LinkedList {
public Node head;
public LinkedList() {
this.head = null;
}
public void add(int value) {
if (this.head == null) {
this.head = new Node(value);
} else {
Node current = this.head;
while (current.next != null) {
current = current.next;
}
current.next = new Node(value);
}
}
public void delete(int value) {
if (this.head == null) {
return;
}
if (this.head.value == value) {
this.head = this.head.next;
return;
}
Node current = this.head;
while (current.next != null) {
if (current.next.value == value) {
current.next = current.next.next;
return;
}
current = current.next;
}
}
}
网络编程和并发模型简介
消息队列通常涉及到网络编程和并发模型。网络编程是实现不同服务之间通信的关键技术,可以使用Socket编程、HTTP等协议来实现。并发模型则是实现消息队列的高性能和高可用性的关键。常用的消息队列并发模型包括线程池、进程池、协程等。线程池可以复用线程资源,提高系统的性能;进程池可以实现进程间的隔离,提高系统的稳定性;协程可以实现轻量级的并发,提高系统的效率。
以下是一个简单的Socket编程示例:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = null;
while (true) {
socket = serverSocket.accept();
new Thread(new ServerThread(socket)).start();
}
}
}
public class ServerThread implements Runnable {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Received: " + inputLine);
out.println("Echo: " + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
手写消息队列实现
在设计消息队列时,首先需要定义消息队列的数据结构。消息队列可以使用链表、数组、队列等数据结构实现。链表可以灵活地插入和删除元素,适用于消息队列的插入和删除操作。数组可以快速地访问元素,适用于需要随机访问的消息队列。队列可以高效地插入和删除元素,适用于消息队列的插入和删除操作。在选择数据结构时,需要考虑队列的长度、插入和删除操作的频率等因素。
以下是一个简单的链表实现消息队列的示例:
public class LinkedListQueue {
private Node head;
private Node tail;
private class Node {
private int value;
private Node next;
public Node(int value) {
this.value = value;
this.next = null;
}
}
public LinkedListQueue() {
this.head = null;
this.tail = null;
}
public void add(int value) {
Node newNode = new Node(value);
if (this.head == null) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
this.tail = newNode;
}
}
public int poll() {
if (this.head == null) {
return -1;
}
int value = this.head.value;
this.head = this.head.next;
if (this.head == null) {
this.tail = null;
}
return value;
}
}
在实现消息队列时,还需要考虑线程安全问题。线程安全是指在一个多线程环境中,多个线程可以安全地访问和修改数据而不会导致数据不一致或程序崩溃。对于消息队列,需要确保在多线程环境下,插入和删除操作不会导致数据不一致或程序崩溃。可以使用锁、信号量、原子变量等机制来实现线程安全。
以下是一个简单的线程安全消息队列的示例:
import java.util.concurrent.locks.*;
public class ThreadSafeQueue {
private LinkedListQueue queue;
private ReentrantLock lock;
private Condition notEmpty;
private Condition notFull;
public ThreadSafeQueue(int capacity) {
this.queue = new LinkedListQueue();
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
this.notFull = lock.newCondition();
}
public void add(int value) {
lock.lock();
try {
while (queue.size() >= capacity) {
notFull.await();
}
queue.add(value);
notEmpty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public int poll() {
lock.lock();
try {
while (queue.size() == 0) {
notEmpty.await();
}
int value = queue.poll();
notFull.signal();
return value;
} catch (InterruptedException e) {
e.printStackTrace();
return -1;
} finally {
lock.unlock();
}
}
}
手写MQ的优化和扩展
在实现消息队列后,还需要考虑如何优化和扩展消息队列。性能优化策略包括减少锁的使用、使用高效的算法和数据结构、优化I/O操作等。例如,可以使用无锁的数据结构来减少锁的使用,使用高效的数据结构来减少内存占用和访问时间。高可用与容错设计包括使用冗余节点、心跳检测、数据备份等。例如,可以使用多个节点来实现冗余,使用心跳检测来检测节点的存活状态,使用数据备份来防止数据丢失。消息持久化与可靠传递包括使用持久化存储、使用消息确认机制等。例如,可以将消息存储到磁盘上,使用消息确认机制来确保消息被正确接收和处理。
以下是一个简单的性能优化示例:
import java.util.concurrent.atomic.*;
public class AtomicQueue {
private Node head;
private Node tail;
private AtomicInteger size;
private class Node {
private int value;
private Node next;
public Node(int value) {
this.value = value;
this.next = null;
}
}
public AtomicQueue() {
this.head = null;
this.tail = null;
this.size = new AtomicInteger(0);
}
public void add(int value) {
Node newNode = new Node(value);
while (true) {
Node prevTail = this.tail;
Node next = prevTail.next;
if (prevTail == this.tail) {
if (next != null) {
this.tail = next;
} else {
newNode.next = next;
if (compareAndSetTail(prevTail, newNode)) {
this.size.incrementAndGet();
return;
}
}
}
}
}
private boolean compareAndSetTail(Node expected, Node update) {
return this.tail.compareAndSet(expected, update);
}
public int poll() {
while (true) {
Node prevHead = this.head;
Node next = prevHead.next;
if (prevHead == this.head) {
if (next == null) {
return -1;
} else {
int value = next.value;
if (compareAndSetHead(next)) {
this.size.decrementAndGet();
return value;
}
}
}
}
}
private boolean compareAndSetHead(Node update) {
return this.head.compareAndSet(this.head, update);
}
}
高可用与容错设计
在设计高可用和容错性时,可以使用冗余节点、心跳检测、数据备份等技术。例如,可以使用多个消息队列节点确保高可用性,使用心跳检测来监测节点状态,使用数据备份来防止数据丢失。以下是一个简单的高可用和容错设计示例:
import java.util.*;
public class HighAvailabilityQueue {
private Map<String, ThreadSafeQueue> queues;
private String primaryQueue;
private List<String> secondaryQueues;
public HighAvailabilityQueue(String primaryQueueName, List<String> secondaryQueueNames) {
this.primaryQueue = primaryQueueName;
this.secondaryQueues = secondaryQueueNames;
this.queues = new HashMap<>();
for (String queueName : secondaryQueueNames) {
this.queues.put(queueName, new ThreadSafeQueue(10));
}
this.queues.put(primaryQueue, new ThreadSafeQueue(10));
}
public void add(int value) {
ThreadSafeQueue primaryQueue = this.queues.get(primaryQueue);
if (primaryQueue != null) {
primaryQueue.add(value);
}
for (String secondaryQueueName : secondaryQueues) {
ThreadSafeQueue secondaryQueue = this.queues.get(secondaryQueueName);
if (secondaryQueue != null) {
secondaryQueue.add(value);
}
}
}
public int poll() {
ThreadSafeQueue primaryQueue = this.queues.get(primaryQueue);
if (primaryQueue != null) {
int value = primaryQueue.poll();
if (value != -1) {
return value;
}
}
for (String secondaryQueueName : secondaryQueues) {
ThreadSafeQueue secondaryQueue = this.queues.get(secondaryQueueName);
if (secondaryQueue != null) {
int value = secondaryQueue.poll();
if (value != -1) {
return value;
}
}
}
return -1;
}
}
消息持久化与可靠传递
确保消息的持久化和可靠传递可以通过使用持久化存储和消息确认机制来实现。持久化存储可以确保消息在系统崩溃或重启后仍然存在,消息确认机制可以确保消息被正确接收和处理。以下是一个简单的持久化存储和消息确认机制示例:
import java.util.*;
public class PersistentQueue {
private ThreadSafeQueue queue;
private Map<Integer, Boolean> confirmations;
public PersistentQueue(int capacity) {
this.queue = new ThreadSafeQueue(capacity);
this.confirmations = new HashMap<>();
}
public void add(int value) {
queue.add(value);
}
public int poll() {
int value = queue.poll();
if (value != -1) {
confirmations.put(value, false);
}
return value;
}
public void confirm(int value) {
confirmations.put(value, true);
}
public void rollback(int value) {
confirmations.put(value, false);
}
}
实战案例:手写MQ在项目中的应用
简单项目需求分析
假设有一个电商平台需要实现订单系统和支付系统之间的解耦,订单系统负责生成订单并将其发送到队列,支付系统负责从队列中读取消息并进行支付处理。在这种场景下,可以使用消息队列来实现订单系统和支付系统之间的异步通信。
-
订单系统:订单系统负责生成订单并将其发送到队列。订单系统可以将订单信息作为消息发送到队列,然后返回响应给客户端。订单系统可以使用发布/订阅模式来发送消息,将订单信息发送到指定的Topic。
- 支付系统:支付系统负责从队列中读取消息并进行支付处理。支付系统可以订阅指定的Topic,从队列中读取消息并进行支付处理。支付系统可以使用点对点模式来接收消息,确保每个订单只被一个支付系统处理。
在设计消息队列时,需要考虑以下几个方面:
-
队列类型:选择合适的队列类型,如发布/订阅模式或点对点模式。在本例中,可以选择发布/订阅模式来实现订单系统和支付系统之间的异步通信。
- 消息格式:设计合理的消息格式,包括消息头和消息体。消息头可以包含消息类型、消息时间戳等信息,消息体可以包含订单信息、支付信息等数据。以下是一个简单的消息格式示例:
{
"type": "order",
"timestamp": "2023-03-01T10:00:00Z",
"data": {
"orderId": "123456",
"userId": "654321",
"amount": 100.00
}
}
- 消息传递方式:选择合适的消息传递方式,如同步或异步传递。在本例中,可以选择异步传递方式,确保订单系统和支付系统之间的解耦。订单系统可以将订单信息发送到队列,支付系统可以异步从队列中读取消息并进行支付处理。
以下是一个简单的消息队列实现示例:
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
public class OrderProducer {
public static void main(String[] args) {
KafkaProducer<String, String> producer = new KafkaProducer<>(configureProps());
String topic = "order";
String orderJson = "{ \"type\": \"order\", \"timestamp\": \"2023-03-01T10:00:00Z\", \"data\": { \"orderId\": \"123456\", \"userId\": \"654321\", \"amount\": 100.00 } }";
ProducerRecord<String, String> record = new ProducerRecord<>(topic, orderJson);
producer.send(record);
producer.close();
}
private static Properties configureProps() {
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
return props;
}
}
public class PaymentConsumer {
public static void main(String[] args) {
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(configureProps());
String topic = "order";
consumer.subscribe(Arrays.asList(topic));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records) {
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
// Process the order
}
}
}
private static Properties configureProps() {
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "payment");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
return props;
}
}
项目测试与调试
在实现消息队列后,需要进行测试和调试,确保消息队列能够正常工作。可以通过编写单元测试和集成测试,对消息队列进行测试和调试。以下是一个简单的单元测试示例:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class OrderProducerTest {
@Test
public void testOrderProducer() {
OrderProducer producer = new OrderProducer();
String orderJson = "{ \"type\": \"order\", \"timestamp\": \"2023-03-01T10:00:00Z\", \"data\": { \"orderId\": \"123456\", \"userId\": \"654321\", \"amount\": 100.00 } }";
producer.send(orderJson);
// Test the producer
}
}
``
在调试过程中,需要关注以下几点:
1. **消息格式**:确保消息格式正确,包括消息头和消息体。消息头可以包含消息类型、消息时间戳等信息,消息体可以包含订单信息、支付信息等数据。
2. **消息传递**:确保消息能够正确传递,包括发送和接收。生产者需要将消息发送到队列,消费者需要从队列中读取消息。
3. **消息处理**:确保消息能够正确处理,包括解析和处理。消费者需要解析消息并执行相应的处理逻辑。
4. **错误处理**:确保错误能够正确处理,包括异常和错误。生产者和消费者需要能够处理各种异常和错误,例如网络错误、数据错误等。
5. **性能和稳定性**:确保消息队列能够稳定工作,包括高并发和高可用。生产者和消费者需要能够处理高并发和高可用,例如同时发送和接收多个消息。
在调试过程中,可以使用日志和监控工具来帮助调试。日志可以帮助记录消息队列的运行日志,监控工具可以帮助监控消息队列的运行状态。以下是一个简单的日志示例:
```java
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
public class PaymentConsumer {
public static void main(String[] args) {
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(configureProps());
String topic = "order";
consumer.subscribe(Arrays.asList(topic));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records) {
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
// Process the order
try {
// Process the order
} catch (Exception e) {
e.printStackTrace();
// Log the error
}
}
}
}
}
共同学习,写下你的评论
评论加载中...
作者其他优质文章