赞
踩
同步通讯:比如微信视频,同一时间只能跟一个人视频,其他人想跟你视频的话,得等你这个视频结束之后才可以
异步通信:比如微信发消息,发了一个人后,别人可能还没回你,但你还可以给其他人发
微服务间基于Feign的调用就属于同步方法,存在一些问题。
1.耦合度高
2.性能下降
3.资源浪费
4.级联失败
同步调用的优点:
同步调用的问题:
异步调用常见实现就是事件驱动模式
优势一:服务解耦
优势二:性能提升,吞吐量提高
优势三:服务没有强依赖,不担心级联失败问题
优势四:流量削峰
异步通信的优点
异步通信的缺点:
MQ,中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。
RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
---|---|---|---|---|
公司/社区 | Rabiit | Apache | 阿里 | Apache |
开发语言 | Erlang | Java | Java | Scala&Java |
协议支持 | AMQP,XMPP,SMTP,STOMP | OpenWrite,STOMP,REST,XMPP,AMQP | 自定义协议 | 自定义协议 |
可用性 | 高 | 一般 | 高 | 高 |
单机吞吐量 | 一般 | 差 | 高 | 非常高 |
消息延迟区 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
消息可靠性 | 高 | 一般 | 高 | 一般 |
kafka适用于海量数据的传输,但对数据安全要求不高的,比如说日志数据
中小型企业推荐使用 RabbitMQ
如果是大型企业,需要做更深度的定制,推荐使用RocketMQ
RabbitMQ是基于Erlang语言开发的开源消息通信中间件,官网地址:http://www.rabbitmq.com/
在Centos7虚拟机中使用Docker来安装
方式一:在线拉取
docker pull rabbitmq:3-management
方式一:从本地加载
从资料中提供的镜相包上传到虚拟机后,使用命令加载镜像即可:
docker load -i mq.tar
执行下面的命令来运行MQ容器
docker run \
-e RABBITMQ_DEFAULT_USR=luxifa \ #设置环境变量
-e RABBITMQ_DEFAULT_PASSWORD=1234 \ #设置环境变量
--name mq \ #起名
--hostname mql \ #配置主机名,不配也没关系,如果将来做集群部署的话,就得配
--p 15672:15672 \ # 开放了两个端口 15672是rabbitmq 管理平台的端口
--p 5672:5672 \ # 做消息通信的端口
-d \ # 后台运行
rabbitmq:3-management # 镜像的名称
把命令在控制台运行,容器即可创建完成
通过 docker ps 查看一下
在浏览器输入:http://机器IP:15672 即可进入RabblitMQ的管理界面
界面中:
Overview:总览,主要就是节点的一些详细信息,因为现在是单节点运行,没有集群,所以节点中只有一个
Connections:连接,将来,无论是消息的发布者还是消息的消费者,都要跟mq建立连接
Channels:通道,建立连接以后一定要建立通道,生产者或消费者才能基于channels完成消息的发送或接收,可以认为channe是mq中消息发送也好,接收也好等等各种操作的一个对象,将来每一个连上的人都应该创建一个或多个channel
Exchanges:交换机
Queues:队列,用来做消息存储的
Admin:管理,在这个界面中可以管理当前的用户信息
发布者会将消息发送到exchange,exchange负责路由,把消息投递到queue,queue负责暂存消息,消费者从queue中获取消息,处理消息
RabbitMQ中的几个概念:
MQ的官方文档中(http://rabbitmq.com/getstarted.html)给出了5个MQ的Demo示例,对应了几种不同的用放大:
这两种都是基于消息队列来完成的,没有经过交换机
发布订阅(Publish、Subscribe),又根据交换机类型不同分为三种:
官方的HelloWorld是基于最基础的消息队列模型来实现的,只包括三个角色:
实现步骤:
PublisherTest.java
public class PublisherTest { @Test public void testSendMessage() throws IOException, TimeoutException { // 1.建立连接 ConnectionFactory factory = new ConnectionFactory(); // 1.1设置连接参数 分别是:主机名、端口号、vhost、用户名、密码 factory.setHost("192.168.150.101"); factory.setPort(5672); factory.setVirtualHost("/"); factory.setUsername("luxifa"); factory.setPassword("123456"); // 1.2建立连接 Connection connection = factory.newConnection(); // 2.创建通道Channel Channel channel = connection.createChannel(); // 3.创建队列 String queueName = "simple.queue"; channel.queueDeclare(queueName,durable:false,exclusive:false,qutoDelete:false,arguments:null); // 4.发送消息 String message = "hello rabbitmq!"; channel.basicPublish(exchange:"",queueName,props:null,message.getBytes()); System.out.println("发送消息成功:【" + message + "】"); //5.关闭通道和连接 channel.close(); connection.close(); } }
ConsumerTest.java
public class ConsumerTest{ @Test public static void main(Strign[] args) throws IOException,TimeoutException { // 1.建立连接 ConnectionFactory factory = new ConnectionFactory(); // 1.1设置连接参数 分别是:主机名、端口号、vhost、用户名、密码 factory.setHost("192.168.150.101"); factory.setPort(5672); factory.setVirtualHost("/"); factory.setUsername("luxifa"); factory.setPassword("123456"); // 1.2建立连接 Connection connection = factory.newConnection(); // 2.创建通道Channel Channel channel = connection.createChannel(); // 3.创建队列 String queueName = "simple.queue"; channel.queueDeclare(queueName,durable:false,exclusive:false,qutoDelete:false,arguments:null); // 4.订阅消息 channel.basicConsume(queueName,autoAck:true,new DefaultConsumer(channel) { @Ovrride public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body) throws IOException { // 5.处理消息 String message = new String(body); System.out.println("接收到消息:【" + message + "】"); } }); System.out.println("等待接收消息......"); } }
基本消息队列的消息发送流程:
1.建议connection
2.创建channel
3.利用channer声明队列
4.利用channel向队列发送消息
基本消息队列的消息接收流程:
1.建议connection
2.创建channel
3.利用channer声明队列
4.定义consumer的消费行为handleDelevery()
5.利用channel将消费者与队列绑定
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。