在学习消息中间件的路上我 得到的知识全部介绍在下文 后期会慢慢补充 一起进步!
在互联网大流量的时代 单一的同步处理非常消耗时间 而且耦合度很高 为了解决这个问题消息中间件诞生 说到MQ就提一下消息中间件常用的协议
一.协议介绍
6.1 AMQP协议
AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。
优点:可靠、通用
6.2 MQTT协议
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。
优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统
6.3 STOMP协议
STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。
优点:命令模式(非topic\queue模式)
6.4 XMPP协议
XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。
优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大
6.5 其他基于TCP/IP自定义的协议
有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。
这里主要说一下RabbitMQ 他遵循的AMQP
消息中间件的好处是
1.交互系统之间没有直接的调用关系,只是通过消息传输,故系统侵入性不强,耦合度低。
2.例如原来的一套逻辑,完成支付可能涉及先修改订单状态、计算会员积分、通知物流配送,几个逻辑才能完成;通过MQ架构设计,就可将紧急重要(需要立刻响应)的业务放到该调用方法中,响应要求不高的使用消息队列,放到MQ队列中,供消费者处理。
3.通过消息作为整合,大数据的背景下,消息队列还与实时处理架构整合,为数据处理提供性能支持。主要做日志处理等
4.负载均衡,流量消封
java还提供一个叫jms的 没有具体了解过
*二.amqp
producer指生产者
broker是消息的服务
exchange交换机
queue消息队列
message消息体
consumer消费者
这两个部件的含义如下:
1 Exchange接收producers发送过来的消息,按照一定的规则转发到相应的Message Queues。
2 Message Queues再将消息转发到相应的Consumers。
下面介绍windows下面Rabbitmq安装 linux介意直接使用docker
首先需要下载 Erlang https://www.erlang.org/downloads
安装过后添加环境变量
再下载rabbitmq 解压安装
然后激活启动
然后访问localhost:15672
默认账号密码 guest guest
这样就安装完成了
rabbitmq有4种状态 fanout,direct,topic,header
最后一种不常用我也没试过
fanout 广播模式 就是绑定了交换机的全部队列都能收到消息
direct 一对一模式 严格按照绑定的名字发送给队列
topic 通配符模式 * 和#
header 头模式
1.第一种 fanout
public class ConnectionUtil {
private static final String RABBIT_HOST = "localhost";
private static final String RABBIT_USERNAME = "guest";
private static final String RABBIT_PASSWORD = "guest";
private static Connection connection = null;
public static Connection getConnection() {
if(connection == null) {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(RABBIT_HOST);
connectionFactory.setUsername(RABBIT_USERNAME);
connectionFactory.setPassword(RABBIT_PASSWORD);
try {
connection = connectionFactory.newConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
return connection;
}
}
生产者代码
public class producer {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//channel.queueDeclare("queue_test",true,false,false,null);
channel.exchangeDeclare("jhjfanout","fanout",true,true,null);
channel.basicPublish("jhjfanout","",null,"交换机发送的消息".getBytes());
channel.close();
connection.close();
}
}
消费者代码
第一个消费者
public class consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
final Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare("fanout1",true,false,false,null);
channel.queueBind("fanout1","jhjfanout","");
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("fanout1"+new String(body,"utf-8"));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume("fanout1",false,defaultConsumer);
}
}
第二个消费者
public class consumer2 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
final Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare("fanout",true,false,false,null);
channel.queueBind("fanout","jhjfanout","");
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("fanout"+new String(body,"utf-8"));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume("fanout",false,defaultConsumer);
}
}
二 ,direct
生产者
public class producer {
private static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if(connectionFactory==null){
connectionFactory=new ConnectionFactory();
connectionFactory.setPort(5672);
connectionFactory.setHost(“127.0.0.1”);
connectionFactory.setUsername(“user”);
connectionFactory.setPassword(“admin”);
}
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
//channel.queueDeclare(“test2”,true,false,false,null);
channel.exchangeDeclare(“jhj”,“direct”,true,true,null);
channel.basicPublish(“jhj”,“test”,null,“交换机发送的消息”.getBytes());
channel.close();
connection.close();
}
}
消费者1
public class consumer {
static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if(connectionFactory==null){
connectionFactory=new ConnectionFactory();
connectionFactory.setUsername(“user”);
connectionFactory.setPassword(“admin”);
connectionFactory.setHost(“localhost”);
connectionFactory.setPort(5672);
}
Connection connection = connectionFactory.newConnection();
final Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare(“test”,true,false,false,null);
channel.queueBind(“test”,“jhj”,“test”);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(“test”+new String(body,“utf-8”));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(“test”,false,defaultConsumer);
}
}
消费者2
public class consumer2 {
static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if(connectionFactory==null){
connectionFactory=new ConnectionFactory();
connectionFactory.setUsername(“user”);
connectionFactory.setPassword(“admin”);
connectionFactory.setHost(“localhost”);
connectionFactory.setPort(5672);
}
Connection connection = connectionFactory.newConnection();
final Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare(“test2”,true,false,false,null);
channel.queueBind(“test2”,“jhj”,“test2”);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(“test2”+new String(body,“utf-8”));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(“test2”,false,defaultConsumer);
}
}
三 topic
生产者
public class producer {
static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if(connectionFactory==null){
connectionFactory=new ConnectionFactory();
connectionFactory.setUsername(“user”);
connectionFactory.setPassword(“admin”);
connectionFactory.setHost(“localhost”);
connectionFactory.setPort(5672);
}
Connection connection = connectionFactory.newConnection();
final Channel channel = connection.createChannel();
channel.exchangeDeclare(“jhj2”,“topic”);
channel.basicPublish(“jhj2”,“ab.s.11”,false,false,null,“我是交换机筛选过来的”.getBytes());
channel.close();
connection.close();
}
}
消费者1
public class consumer {
static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if (connectionFactory == null) {
connectionFactory = new ConnectionFactory();
connectionFactory.setUsername("user");
connectionFactory.setPassword("admin");
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
}
Connection connection = connectionFactory.newConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare("toptest", true, false, false, null);
channel.queueBind("toptest", "jhj2", "ab.*");
channel.basicQos(1);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body, "utf-8"));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume("toptest",false,defaultConsumer);
}
}
消费者2
public class consumer2 {
static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if (connectionFactory == null) {
connectionFactory = new ConnectionFactory();
connectionFactory.setUsername("user");
connectionFactory.setPassword("admin");
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
}
Connection connection = connectionFactory.newConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare("toptest2", true, false, false, null);
channel.queueBind("toptest2", "jhj2", "ab.#");
channel.basicQos(1);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body, "utf-8"));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume("toptest2",false,defaultConsumer);
}
}
消费者3
public class consumer3 {
static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if (connectionFactory == null) {
connectionFactory = new ConnectionFactory();
connectionFactory.setUsername("user");
connectionFactory.setPassword("admin");
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
}
Connection connection = connectionFactory.newConnection();
final Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare("toptest3", true, false, false, null);
channel.queueBind("toptest3", "jhj2", "abc");
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body, "utf-8"));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume("toptest3",false,defaultConsumer);
}
}
四
channel.basicConsume(“toptest3”,false,defaultConsumer);如果监听队列第二个参数为false他的意识就是需要手动提交消费结构
然后需要添加
channel.basicAck(envelope.getDeliveryTag(),false);
这句话是公平分发 设处理的快谁就发的多 channel.basicQos(1);
五.rabbitmq确认机制
事务+Confirm
1.事物
public class producer {
private static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException {
if(connectionFactory==null){
connectionFactory=new ConnectionFactory();
connectionFactory.setPort(5672);
connectionFactory.setHost(“127.0.0.1”);
connectionFactory.setUsername(“user”);
connectionFactory.setPassword(“admin”);
}
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
//channel.queueDeclare(“test2”,true,false,false,null);
channel.exchangeDeclare(“jhj”,“direct”,true,true,null);
channel.txSelect();
try {
channel.basicPublish(“jhj”, “test”, null, “交换机发送的消息”.getBytes());
channel.txCommit();
}catch(Exception s){
channel.txRollback();
System.out.println("错误");
}finally {
channel.close();
connection.close();
}
}
}
2.confirm
第1种
普通confirm模式最简单,publish一条消息后,等待服务器端confirm,如果服务端返回false或者超时时间内未返回,客户端进行消息重传。
channel.confirmSelect();
channel.basicPublish(ConfirmConfig.exchangeName, ConfirmConfig.routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, ConfirmConfig.msg_10B.getBytes());
if(!channel.waitForConfirms()){
System.out.println(“send message failed.”);
}
第二种
批量
hannel.confirmSelect();
for(int i=0;i<batchCount;i++){
channel.basicPublish(ConfirmConfig.exchangeName, ConfirmConfig.routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, ConfirmConfig.msg_10B.getBytes());
}
if(!channel.waitForConfirms()){
System.out.println(“send message failed.”);
}
第三种
public class producer {
private static ConnectionFactory connectionFactory;
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
if(connectionFactory==null){
connectionFactory = new ConnectionFactory();
connectionFactory.setPort(5672);
connectionFactory.setHost(“localhost”);
connectionFactory.setUsername(“guest”);
connectionFactory.setPassword(“guest”);
}
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(“queue_test”,true,false,false,null);
channel.confirmSelect();
final SortedSet ts=new TreeSet();
channel.addConfirmListener(new ConfirmListener() {
public void handleAck(long l, boolean b) throws IOException {
if(b){
ts.headSet(l+1).clear();
System.out.println(“ack”+b+“long”+l);
}else {
ts.remove(l);
System.out.println(“ack” + b + “long” + l);
}
}
public void handleNack(long l, boolean b) throws IOException {
if(b){
ts.headSet(l+1).clear();
System.out.println("nack"+b+"long"+l);
}else {
ts.remove(l);
System.out.println("nack"+b+"long"+l);
}
}
});
for (int i = 0; i < 50; i++) {
channel.basicPublish("","queue_test",null,("我的第一次测试"+i).getBytes());
ts.add(channel.getNextPublishSeqNo());
System.out.println("---"+i);
Thread.sleep(100);
}
channel.close();
connection.close();
}
}