一、消息的作用
异步、解耦、流量削峰、日志收集、事务最终一致性
1.1 异步
1.2 解耦
只关心通知,不关心处理
1.3 流量削峰
将短时间高并发的请求持久化,然后逐步处理,从而削平高峰期的并发流量
1.4 日志收集
利用消息队列产品在接收和持久化消息方面的高性能,引入快速接收日志消息,避免写入日志时的某些故障导致业务系统访问阻塞、请求延迟等
1.5 事务最终一致性
分布式事务的规范———XA。
XA定义了全局事务管理器和局部资源管理器之间的接口。XA接口是双向的系统接口,在事务管理器及一个或多个资源管理器之间形成通信桥梁。XA引入的事务管理器充当全局事务中的协调者的角色。事务管理器控制着全局事务,管理事务生命周期,并协调资源,资源管理器负责控制和管理实际资源
二、消息队列的功能特点
一个典型意义上的消息队列,至少需要包含消息的发送,接收,暂存功能
除了上述功能,实际消息队列还要能处理消息堆积、消息持久化、可靠投递、消息重复、严格有序、集群等问题
三、设计一个简单的消息队列
package com.wisely.spring_boot_starter_hello;
import java.util.concurrent.ArrayBlockingQueue;
/**
* 消息处理中心类
* @author Administrator
*
*/
public class Broker {
//队列存储消息的最大数量
private final static int MAX_SIZE = 3;
//保存消息数据的容器
private static ArrayBlockingQueue<String> messageQueue = new ArrayBlockingQueue<String>(MAX_SIZE);
//生产消息
public static void produce(String msg){
if(messageQueue.offer(msg)){//offer(E e) 方法是用来插入指定的元素到此优先级队列。
System.out.println("成功向消息处理中心投递消息:"+msg+",当前缓存的消息数量是:"+messageQueue.size());
}else{
System.out.println("消息处理中心内暂存的消息达到最大负荷,不能继续放入消息!");
}
System.out.println("=================");
}
//消费消息
public static String consume() {
String msg = messageQueue.poll();//返回队列中的首个元素
if(msg != null){
//消费条件满足情况,从消费容器中取出一条消息
System.out.println("已经消费消息:"+msg+",当前暂存的消息数量是:"+messageQueue.size());
}else{
System.out.println("消息处理中心内没有消息可供消费");
}
System.out.println("=================");
return msg;
}
}
package com.wisely.spring_boot_starter_hello;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import javafx.scene.layout.Border;
public class BrokerServer implements Runnable {
public static int SERVICE_PORT = 9999;
private final Socket socket ;
public BrokerServer(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader in;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
while(true){
String str = in.readLine();
if(str == null){
continue;
}
System.out.println("接收到原始数据:"+str);
if(str.equals("CONSUME")){//要消费一条消息
//从消息队列中消费一条数据
String message = Broker.consume();
out.println(message);
out.flush();
}else{
//其他情况都表示生产消息放到消息队列中
Broker.produce(str);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(SERVICE_PORT);
while(true){
BrokerServer brokerServer = new BrokerServer(server.accept());
new Thread(brokerServer).start();
}
}
}
package com.wisely.spring_boot_starter_hello;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端访问
* @author Administrator
*
*/
public class MqClient {
//生产消息
public static void produce(String message) throws Exception{
Socket socket = new Socket(InetAddress.getLocalHost(),BrokerServer.SERVICE_PORT);
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println(message);
out.flush();
}
//消费消息
public static String consume() throws Exception{
Socket socket = new Socket(InetAddress.getLocalHost(),BrokerServer.SERVICE_PORT);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
//先向消息队列发送CONSUME表示消费
out.println("CONSUME");
out.flush();
//再从消息队列获取一条消息
String message = in.readLine();
return message;
}
}
package com.wisely.spring_boot_starter_hello;
public class ProduceClient {
public static void main(String[] args) throws Exception {
MqClient client = new MqClient();
client.produce("hello world");
}
}
package com.wisely.spring_boot_starter_hello;
public class ConsumeClient {
public static void main(String[] args) throws Exception {
MqClient client = new MqClient();
String message = client.consume();
System.out.println("获取的消息为:"+message);
}
}