Java简单实现MQ架构和思路01
实现一个 MQ(消息队列)架构可以涉及到很多方面,包括消息的生产和消费、消息的存储和传输、消息的格式和协议等等。下面是一个简单的 MQ 架构的实现示例,仅供参考:
定义消息格式和协议:我们可以定义一个简单的消息格式,比如 JSON 格式,包含消息的 ID、内容、发送时间等信息。同时,我们可以定义一个简单的协议,比如 TCP 协议,用来传输消息。
实现消息的存储:我们可以使用数据库或者文件系统等方式来存储消息。对于消息队列来说,可以考虑使用类似于链表的数据结构来存储消息,每个节点包含一个消息和指向下一个节点的指针。
实现消息的生产和消费:我们可以使用多线程来实现消息的生产和消费。具体地,我们可以定义一个生产者线程和多个消费者线程,生产者线程负责从外部系统中获取消息并存储到消息队列中,消费者线程负责从消息队列中获取消息并进行处理。
实现消息的传输:我们可以使用 TCP 协议来传输消息。具体地,我们可以定义一个服务器程序,负责监听指定的端口号,并接受客户端的连接请求。一旦连接建立,服务器程序就可以和客户端进行数据传输。
综上所述,一个简单的 MQ 架构的实现可以包含以上几个部分。实际上,MQ 的实现还涉及到很多其他方面,比如消息的确认和重试、消息的过期和删除、消息的优先级和分区等等。因此,在实际项目中,需要根据具体的需求和场景来进行设计和实现。
以下是一个简单的 Java 消息队列示例代码,使用了多线程和 TCP 协议:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
public class MessageQueue {
private LinkedList<Message> queue = new LinkedList<Message>();
public synchronized void putMessage(Message message) {
queue.add(message);
notifyAll();
}
public synchronized Message getMessage() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
return queue.removeFirst();
}
public static void main(String[] args) {
MessageQueue queue = new MessageQueue();
Producer producer = new Producer(queue);
Consumer consumer1 = new Consumer(queue);
Consumer consumer2 = new Consumer(queue);
producer.start();
consumer1.start();
consumer2.start();
}
}
class Message implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String content;
public Message(String id, String content) {
this.id = id;
this.content = content;
}
public String getId() {
return id;
}
public String getContent() {
return content;
}
}
class Producer extends Thread {
private MessageQueue queue;
public Producer(MessageQueue queue) {
this.queue = queue;
}
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(9999);
while (true) {
Socket socket = serverSocket.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message message = (Message) ois.readObject();
queue.putMessage(message);
ois.close();
socket.close();
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Consumer extends Thread {
private MessageQueue queue;
public Consumer(MessageQueue queue) {
this.queue = queue;
}
public void run() {
try {
while (true) {
Message message = queue.getMessage();
System.out.println("Consumer " + getId() + " got message: " + message.getContent());
Socket socket = new Socket("localhost", 9998);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message);
oos.close();
socket.close();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
在这个示例中,我们定义了一个简单的消息队列,使用了一个链表来存储消息。然后,我们定义了一个生产者线程和两个消费者线程,生产者线程负责从外部系统中获取消息并存储到消息队列中,消费者线程负责从消息队列中获取消息并进行处理。我们使用 TCP 协议来传输消息,生产者线程监听端口号 9999,消费者线程通过连接 localhost 的 9998 端口来发送消息。在实际应用中,需要根据具体需求进行修改和扩展。
并在此代码基础上增加 协议类和注释
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
// 消息队列类
public class MessageQueue {
private LinkedList<Message> queue = new LinkedList<Message>();
// 往队列中添加消息
public synchronized void putMessage(Message message) {
queue.add(message);
notifyAll();
}
// 从队列中取出消息
public synchronized Message getMessage() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
return queue.removeFirst();
}
// 主函数
public static void main(String[] args) {
MessageQueue queue = new MessageQueue();
Producer producer = new Producer(queue);
Consumer consumer1 = new Consumer(queue);
Consumer consumer2 = new Consumer(queue);
producer.start();
consumer1.start();
consumer2.start();
}
}
// 消息类
class Message implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String type; // 消息类型,例如:ORDER, PAYMENT, SHIPMENT, 等等
private String content; // 消息内容
private String sender; // 消息发送者
private String receiver; // 消息接收者
// 构造方法
public Message(String type, String content, String sender, String receiver) {
super();
this.type = type;
this.content = content;
this.sender = sender;
this.receiver = receiver;
}
// 返回消息类型
public String getType() {
return type;
}
// 返回消息内容
public String getContent() {
return content;
}
// 返回消息发送者
public String getSender() {
return sender;
}
// 返回消息接收者
public String getReceiver() {
return receiver;
}
}
// 编解码协议类
class Protocol {
public static final String HEADER = "MESSAGE"; // 消息头
public static final String DELIMITER = ":"; // 分隔符
// 将消息编码为字符串
public static String encode(Message message) {
return HEADER + DELIMITER + message.getType() + DELIMITER + message.getContent() + DELIMITER
+ message.getSender() + DELIMITER + message.getReceiver();
}
// 将字符串解码为消息
public static Message decode(String messageString) {
String[] parts = messageString.split(DELIMITER);
return new Message(parts[1], parts[2], parts[3], parts[4]);
}
}
// 生产者线程类
class Producer extends Thread {
private MessageQueue queue;
private ServerSocket serverSocket;
// 构造方法
public Producer(MessageQueue queue) {
this.queue = queue;
}
// 启动线程
public void run() {
try {
serverSocket = new ServerSocket(9999); // 监听端口号9999
while (true) {
Socket socket = serverSocket.accept(); // 接收连接
ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); // 创建输入流
String messageString = (String) in.readObject(); // 读取消息字符串
Message message = Protocol.decode(messageString); // 解码消息
queue.putMessage(message); // 添加消息到队列
in.close(); // 关闭输入流
socket.close(); // 关闭连接
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
// 消费者线程类
class Consumer extends Thread {
private MessageQueue queue;
// 构造方法
public Consumer(MessageQueue queue) {
this.queue = queue;
}
// 启动线程
public void run() {
while (true) {
try {
Message message = queue.getMessage(); // 从队列中取出消息
System.out.println("Received message: " + message.getContent()); // 输出消息内容
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
以下是在上面代码基础上增加消息确认和重试功能:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
// 消息队列类
public class MessageQueue {
private LinkedList<Message> queue = new LinkedList<Message>();
// 往队列中添加消息
public synchronized void putMessage(Message message) {
queue.add(message);
notifyAll();
}
// 从队列中取出消息
public synchronized Message getMessage() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
return queue.removeFirst();
}
// 主函数
public static void main(String[] args) {
MessageQueue queue = new MessageQueue();
Producer producer = new Producer(queue);
Consumer consumer1 = new Consumer(queue);
Consumer consumer2 = new Consumer(queue);
producer.start();
consumer1.start();
consumer2.start();
}
}
// 消息类
class Message implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String type; // 消息类型,例如:ORDER, PAYMENT, SHIPMENT, 等等
private String content; // 消息内容
private String sender; // 消息发送者
private String receiver; // 消息接收者
private boolean confirmed; // 消息是否已确认
private int retryCount; // 消息重试次数
// 构造方法
public Message(String type, String content, String sender, String receiver) {
super();
this.type = type;
this.content = content;
this.sender = sender;
this.receiver = receiver;
confirmed = false;
retryCount = 0;
}
// 返回消息类型
public String getType() {
return type;
}
// 返回消息内容
public String getContent() {
return content;
}
// 返回消息发送者
public String getSender() {
return sender;
}
// 返回消息接收者
public String getReceiver() {
return receiver;
}
// 返回消息是否已确认
public boolean isConfirmed() {
return confirmed;
}
// 设置消息已确认
public void setConfirmed() {
confirmed = true;
}
// 返回消息重试次数
public int getRetryCount() {
return retryCount;
}
// 增加消息重试次数
public void incrementRetryCount() {
retryCount++;
}
}
// 编解码协议类
class Protocol {
public static final String HEADER = "MESSAGE"; // 消息头
public static final String DELIMITER = ":"; // 分隔符
// 将消息编码为字符串
public static String encode(Message message) {
return HEADER + DELIMITER + message.getType() + DELIMITER + message.getContent() + DELIMITER
+ message.getSender() + DELIMITER + message.getReceiver() + DELIMITER + message.isConfirmed()
+ DELIMITER + message.getRetryCount();
}
// 将字符串解码为消息
public static Message decode(String messageString) {
String[] parts = messageString.split(DELIMITER);
Message message = new Message(parts[1], parts[2], parts[3], parts[4]);
message.setConfirmed(Boolean.parseBoolean(parts[5]));
message.incrementRetryCount();
return message;
}
}
// 生产者线程类
class Producer extends Thread {
private MessageQueue queue;
private ServerSocket serverSocket;
// 构造方法
public Producer(MessageQueue queue) {
this.queue = queue;
}
// 启动线程
public void run() {
try {
serverSocket = new ServerSocket(9999); // 监听端口号9999
while (true) {
Socket socket = serverSocket.accept(); // 接收连接
ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); // 创建输入流
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); // 创建输出流
String messageString = (String) in.readObject(); // 读取消息字符串
Message message = Protocol.decode(messageString); // 解码为消息对象
if (!message.isConfirmed()) { // 如果消息未确认
queue.putMessage(message); // 添加到队列中
}
out.writeObject("ACK"); // 发送确认消息
out.flush();
in.close();
out.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace
}
}
}
Java简单实现MQ架构和思路01的更多相关文章
- 为什么要用消息队列 及 自己如何设计一个mq架构
1. 解耦:如左图, 系统a因为业务需求需要调用系统b,后续因为业务需求可能需要改代码调用系统c,甚至还要考虑被调用的系统挂了访问超时的问题.耦合性太高! 如右图, 系统a产生一条数据发送到消息队列里 ...
- 手把手教你用redis实现一个简单的mq消息队列(java)
众所周知,消息队列是应用系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ActiveMQ,RabbitMQ,Zero ...
- 整理下.net分布式系统架构的思路
最近看到有部分招聘信息,要求应聘者说一下分布式系统架构的思路.今天早晨正好有些时间,我也把我们实际在.net方面网站架构的演化路线整理一下,只是我自己的一些想法,欢迎大家批评指正. 首先说明的是.ne ...
- 高吞吐高并发Java NIO服务的架构(NIO架构及应用之一)
高吞吐高并发Java NIO服务的架构(NIO架构及应用之一) http://maoyidao.iteye.com/blog/1149015 Java NIO成功的应用在了各种分布式.即时通信和中 ...
- Java生鲜电商平台-Java后端生成Token架构与设计详解
Java生鲜电商平台-Java后端生成Token架构与设计详解 目的:Java开源生鲜电商平台-Java后端生成Token目的是为了用于校验客户端,防止重复提交. 技术选型:用开源的JWT架构. 1. ...
- java简单数据类型转化
java简单数据类型,有低级到高级为:(byte,short,char)→int→long→float→double (boolean不参与运算转化) 转化可以分为 低级到高级的自动转化 高级到低级的 ...
- 00:Java简单了解
浅谈Java之概述 Java是SUN(Stanford University Network),斯坦福大学网络公司)1995年推出的一门高级编程语言.Java是一种面向Internet的编程语言.随着 ...
- java简单学生成绩管理系统
题目要求: 一. 数据结构要求:(5 分) 1.定义 ScoreInformation 类,其中包括七个私有变量(stunumber, name, mathematicsscore, englishi ...
- MVC架构模式分析与设计(一)---简单的mvc架构
首先 我要感谢慕课网的老师提供视频资料 http://www.imooc.com/learn/69 下面我来进行笔记 我们制作一个简单的mvc架构 制作第一个控制器 testController.cl ...
- java简单词法分析器(源码下载)
java简单词法分析器 : http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%8D%E6%B3%95%E5%88%8 ...
随机推荐
- OpenHarmony Meetup 深圳站招募令
OpenHarmony Meetup城市巡回深圳站火热来袭!! 日期:2023年10月15日14:00 地点:深圳市福田区上步路中路1003号 深圳市科学馆 与OpenHarmony技术大咖近距离 ...
- 深入了解 Python MongoDB 查询:find 和 find_one 方法完全解析
在 MongoDB 中,我们使用 find() 和 find_one() 方法来在集合中查找数据,就像在MySQL数据库中使用 SELECT 语句来在表中查找数据一样 查找单个文档 要从MongoDB ...
- Visual Studio 2022插件的安装及使用 - 编程手把手系列文章
这次开始写手把手编程系列文章,刚写到C#的Dll程序集类库的博文,就发现需要先介绍Visual Studio 2022的插件的安装及使用,因为在后面编码的时候会用到这些个插件,所以有必要先对这个内容进 ...
- 支持API 9的Sample已上新,速来拿走
原文:https://mp.weixin.qq.com/s/sPDG5sG5F_gTp0cE1VV3gQ,点击链接查看更多技术内容. 今年的华为开发者大会上我们发布了HarmonyOS 3.1 D ...
- 抓包整理————ip 协议二[十三]
前言 介绍一下什么是nat协议和napt协议,和简单带一下LVS. 正文 什么是nat(Network Address Translation) 协议呢? 比如现在你家分配了一个ip,但是你家有10个 ...
- 重新点亮shell————管道和重定向[二]
前言 简单介绍一下管道和重定向. 正文 管道和信号一样,是进程通信的方式之一 管道符是"|",将前一个命令执行的结果传递给后面的命令. 比如说: ls -l | more 就是第一 ...
- 《Effective C#》系列之(零)——概要
把全书的内容讲述完整可能需要很长时间,我可以先回答主要目录和核心的内容.如果您有任何特定问题或需要更详细的解释,请告诉我. <Effective C#>一书共包含50条C#编程建议,以下是 ...
- 【数学】主成分分析(PCA)的详细深度推导过程
Based on Deep Learning (2017, MIT) book. 本文基于Deep Learning (2017, MIT),推导过程补全了所涉及的知识及书中推导过程中跳跃和省略的部分 ...
- Docker部署Node应用简单实践
简介: 本文将从零至一,介绍如何在云服务器上通过 Docker 容器运行一个简单的Node应用. 前言 本文将从零至一,介绍如何在云服务器上通过 Docker 容器运行一个简单的Node应用.本文假设 ...
- Java单元测试技巧之PowerMock
简介: 高德的技术大佬向老师在谈论方法论时说到:"复杂的问题要简单化,简单的问题要深入化." 这句话让我感触颇深,这何尝不是一套编写代码的方法--把一个复杂逻辑拆分为许多简单逻辑, ...