Rabbitmq的初步使用

随着微服务概念发展,大应用逐步拆分为小应用,提高开发效率,专门的人做专门的事情,逐渐的流行起来。

在微服务上实现通信的方式大部分是采用rpc方式,也有升级版本的grpc。

还有另外一种实现就是使用mq来进行解耦。

今天初识mq,快速入门先,准备一个环境实现案例,该文涉及以下内容:

  • 安装rabbitmq
  • mq能解决的问题
  • 实战演练

安装

rabbitmq的安装我们采用docker的方式,docker方便我们快速的实现rabbitmq的安装,不需要再对安装mq进行头疼。

docker 的两种方式

docker方式

//拉取mq镜像
docker pull rabbitmq
//启动mq
docker run -d --name rabbitmq3.7.7 -p 5672:5672 -p 15672:15672 -v `pwd`/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost  -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin df80af9ca0c9

说明:

  1. -d 后台运行容器;
  2. --name 指定容器名;
  3. -p 指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号);
  4. -v 映射目录或文件;
  5. --hostname 主机名(RabbitMQ的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名);
  6. -e 指定环境变量;(RABBITMQDEFAULTVHOST:默认虚拟机名;RABBITMQDEFAULTUSER:默认的用户名;RABBITMQDEFAULTPASS:默认用户名的密码)

docker-compose 方式

version

下载的rabbitmq内置管理界面,ip:15672 用户名与密码是我们在启动是写入的。

mq能解决什么?

通俗的来说,主要使用MQ来解决以下三个问题。

异步消息

在业务中,经常会遇到同时发送邮件,短信或者其他通知内容服务。业务初期,采用同步或者异步处理方式都需要等发送完毕后再返回给客户端。中间有一定的延迟

业务增长后,此方式系统性能就会造成很大的浪费。采用消息队列,将这几个服务进行解耦,只需将消息内容发送到消息队列中,降低用户的等待时间,体验效果比原先好很多。

应用间解耦

同一个服务中可能需要其他服务的配合才能完成一项业务操作.还是拿常见的购物案例来说明。

在京东下单支付后,消息要通知到商家,邮件通知用户已经购买某商品。

如果这两种操作都采用同步执行,用户等待时间会变长。

采用mq方式之后,订单系统将消息持久化到mq上,返回给用户下单成功。

  • 商家接收到用户的下单信息,进行处理,如果有库存管理那么需要进行库存处理。
  • 邮件通知用户,告知用户下单成功。

mq保证消息的可靠投递,不会导致消息丢失,保证消息的高可靠性。如果库存出现失败也不会导致用户下单失败的情况,可以重新进行投递。

流量削峰

流量削峰,一般是同一时间涌进来很多请求,后台处理不过来。那么需要采用削峰方式来处理。

简单来说是通过一个队列承接瞬时过来流量洪峰,在消费端平滑的将消息推送出去,如果消费者消费不及时可以将消息内容持久化在队列中,消息不存在丢失。

  1. 消费端不及时进行消费,还可以动态的扩增消费者数量,提高消费速度。
  2. 设定相关的阀值,多余的消息直接丢弃,告知用户秒杀失败等业务消息内容。

实战案例

本文是按照Java语言进行,使用Spring boot搭建,包管理工具Gradle。

导入rabbitmq jar包

 compile("org.springframework.boot:spring-boot-starter-amqp:1.5.10.RELEASE")

配置mq

yaml 文件配置

spring:rabbitmq:host: 192.168.110.5port: 5672username: gutstpassword: guest

准备好模板类,供后面直接使用

package com.infervision.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author: fruiqi* @date: 19-2-18 下午2:42* @version:1.0 rabbit配置**/
@Configuration
public class RabbitConfig {
/*** 日志**/private static final Logger logger = LoggerFactory.getLogger(RabbitConfig.class);@Value("${spring.rabbitmq.username}")String userName;@Value("${spring.rabbitmq.password}")String userPassword;@Value("${spring.rabbitmq.host}")String host;@Value("${spring.rabbitmq.port}")Integer port;
/*** 注入** @param* @return com.rabbitmq.client.Connection* @author fruiqi* @date 19-1-22 下午5:41**/@Beanpublic ConnectionFactory getConnection() throws Exception {CachingConnectionFactory factory = new CachingConnectionFactory();factory.setUsername(userName);factory.setPassword(userPassword);factory.setHost(host);factory.setPort(port);return factory;}/*** 创建制定的 监听容器** @param queueName  监听的队列名字* @param listenerChannel 设置是否将监听的频道 公开给已注册的* @param PrefetchCount  告诉代理一次请求多少条消息过来* @param ConcurrentConsumers  制定创建多少个并发的消费者数量* @param acknowledgeMode  消息确认模式* @param listener 监听器* @return org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer**/public SimpleMessageListenerContainer setSimpleMessageListenerContainer(String queueName, boolean listenerChannel,int PrefetchCount, int ConcurrentConsumers,AcknowledgeMode acknowledgeMode,ChannelAwareMessageListener listener) throws Exception {SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(getConnection());container.setQueueNames(queueName);container.setExposeListenerChannel(listenerChannel);container.setPrefetchCount(PrefetchCount);container.setConcurrentConsumers(ConcurrentConsumers);container.setAcknowledgeMode(acknowledgeMode);container.setMessageListener(listener);return container;}
}package com.infervision.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author: fruiqi* @date: 19-2-18 下午2:51* @version:1.0**/
@Component
public class MsgSender {private static final Logger logger = LoggerFactory.getLogger(MsgSender.class);@Autowiredprivate RabbitTemplate rabbitTemplate;/*** @param exchange 交换机名称* @param routingKey 路由名称* @param message 消息内容* @return void* @description //TODO 发送消息到消息队列中**/public void sendMsg(String exchange, String routingKey, Object message) {try {rabbitTemplate.convertAndSend(exchange,routingKey,message);}catch (Exception e){logger.error("[ERROR] send statistic message error ",e);}}}

实例链接mq

在使用rabbitmq 有的时候需要自己客户端创建queue,但有的时候并不是自己创建,在rabbitmq页面上进行创建queue,其他消费者直接引用。

客户端创建mq

//初始化队列,如果队列已存在,则不作任何处理 如果有权限控制如下操作并不能实现@Beanpublic Queue dicomQueue() {return new Queue(getMacPreStr(DICOM_QUEUE_NAME));}//初始化交换机@Beanpublic Exchange topicExchange() {return ExchangeBuilder.topicExchange((DEFAULT_TOPIC_EXCHANGE).durable(true).build();}// 将队列与交换机按照路由规则进行绑定@BeanBinding bindingExchangeDicomQueue(Queue dicomQueue, TopicExchange topicExchange) {return BindingBuilder.bind(dicomQueue).to(topicExchange).with(DICOM_QUEUE_ROUTING_KEY);}

使用

队列的使用:一个是发送,属于生产者;一个是监听,属于消费者.

生产者实现

在mq配置模板类中,专门实现了一个发送类,发送文件内容,直接调用发送接口即可。

@AutowiredRabbitService rabbitService;/*** 练习 发送数据到 mq中* 1. 发送的数据会到 mq中* 2. 我们配置的 listener 是用来消费消息的* 3. 客户端配置 可以参考 RabbitClientConfig* @param name 名字编号* @param vo   实体内容* @return: com.infervision.model.NameVo*/@ApiOperation(value = "增加name信息", notes = "实体信息")@PostMapping(value = "/{name}")@ApiImplicitParam(paramType = "query", name = "name", value = "用户名字", required = true, dataType = "string")public NameVo addNameVo(@RequestParam String name, @RequestBody NameVo vo) {rabbitService.sendMessage(DEFAULT_TOPIC_TEST_EXCHANGE, LABEL_FIEL_XML_QUEUE_ROUTING_KEY, JSON.toJSONString(vo));return vo;}@Service
public class RabbitServiceImpl implements RabbitService {@AutowiredMsgSender msgSender;/*** 尝试发送 message 到mq中* @param message* @return: void*/@Overridepublic void sendMessage(String exchange, String routingKey,String message) {msgSender.sendMsg(exchange, routingKey, message);}
}

消费者实现

消费者实现有两种方式,一种通过注解的方式监听,一种是实现ChannelAwareMessageListener类来实现消费。

注解实现监听

//在方法上进行注入。配置工厂帮助提高单个消费者一次性消费的消息数量,设置多少个消费者,用来提高程序的性能
@RabbitListener(queues = "dicom.queue",containerFactory = "multipleConsumerContainerFactory")public void processDicomMessage(Message message, Channel channel) {logger.info(message);}// 工厂可以在配置模板类中中配置好。
@Bean("multipleConsumerContainerFactory")public SimpleRabbitListenerContainerFactory multipleConsumerContainerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();factory.setPrefetchCount(50);factory.setConcurrentConsumers(10);factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);configurer.configure(factory, connectionFactory);return factory;}

实现接口方式

/**

总结

以上内容就完成了rabbitmq 从搭建到使用全部的流程。当然里面还有更多的可以让我们去探讨,比如mq的队列模式,一个系统配置多个mq等等内容。敬请期待我们下一篇mq系列内容。

大家在系统中使用过mq吗?你们使用的mq是什么样的?可以在留言区我们一起探讨哦。

·END·

路虽远,行则必至

本文原发于 同名微信公众号「胖琪的升级之路」,回复「1024」你懂得,给个赞呗。

微信ID:YoungRUIQ

docker rabbitmq_一文看懂Rabbitmq,从安装到实战演练相关推荐

  1. 一文看懂Android APK安装的原理

    一文看懂Android APK安装的原理 前言 APK包的构成 安装APK 总结 前言 大家有没有想过一个应用的APK是怎么被安装到安卓手机上的,安装的本质是什么?我们知道,Windows应用程序的安 ...

  2. 一文看懂RabbitMQ

    RabbitMQ笔记 1.RabbitMQ是什么? 1.1.概念: ​ MQ(Message Queue)消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统 ...

  3. 一文看懂 AI 训练集、验证集、测试集(附:分割方法+交叉验证)

    2019-12-20 20:01:00 数据在人工智能技术里是非常重要的!本篇文章将详细给大家介绍3种数据集:训练集.验证集.测试集. 同时还会介绍如何更合理的讲数据划分为3种数据集.最后给大家介绍一 ...

  4. 一文看懂计算机视觉-CV(基本原理+2大挑战+8大任务+4个应用)

    2020-03-06 20:00:00 计算机视觉(Computer Vision)是人工智能领域的一个重要分支.它的目的是:看懂图片里的内容. 本文将介绍计算机视觉的基本概念.实现原理.8 个任务和 ...

  5. 一文看懂人脸识别(4个特点+4个实现步骤+5个难点+算法发展轨迹)

    2020-03-09 20:01:00 人脸识别是身份识别的一种方式,目的就是要判断图片和视频中人脸的身份时什么. 本文将详细介绍人脸识别的4个特点.4个步骤.5个难点及算法的发展轨迹. 什么是人脸识 ...

  6. 一文看懂卷积神经网络-CNN(基本原理+独特价值+实际应用)

    http://blog.itpub.net/29829936/viewspace-2648775/ 2019-06-25 21:31:18 卷积神经网络 – CNN 最擅长的就是图片的处理.它受到人类 ...

  7. 【深度学习理论】一文看懂卷积神经网络

    [深度学习理论]一文看懂卷积神经网络 https://mp.weixin.qq.com/s/wzpMtMFkVDDH6scVcAdhlA 选自Medium 作者: Pranjal Yadav 经机器之 ...

  8. python读取excelsheet-一文看懂用Python读取Excel数据

    原标题:一文看懂用Python读取Excel数据 导读:现有的Excel分为两种格式:xls(Excel 97-2003)和xlsx(Excel 2007及以上). Python处理Excel文件主要 ...

  9. ​【Python基础】一文看懂 Pandas 中的透视表

    作者:来源于读者投稿 出品:Python数据之道 一文看懂 Pandas 中的透视表 透视表在一种功能很强大的图表,用户可以从中读取到很多的信息.利用excel可以生成简单的透视表.本文中讲解的是如何 ...

最新文章

  1. LeetCode: 108. Convert Sorted Array to Binary Search Tree
  2. SAP EWM - 其他主数据 - 运输主数据-1
  3. 程序员编程如何入门、进阶?
  4. openvino人脸
  5. docker安装运行rancher脚本
  6. Android http Request / Response ContentType
  7. SpringMVC异常处理机制-异常处理两种方式
  8. matlab神经网络动量因子,bp神经网络的动量因子
  9. python3 selenium ie 拒绝连接报错_Python3+selenium配置常见报错解决方案
  10. Jquery 中 ajaxSubmit使用笔记
  11. 2021年中国房地产行业发展现状及2022年前景展望「图」
  12. 我国跨境电子商务的发展概念以及发展概况
  13. 浏览器安全检查5秒解决方案
  14. Luat 功能开发教程(十八) 阿里云
  15. STM32 Cube MX 之hal库软件模拟IIC 可直接移植使用
  16. 工业互联网与高端装备健康管理解决方案
  17. STM32硬件I2C与软件模拟I2C超详解
  18. Xilinx推荐使用ODDR原语输出高质量时钟
  19. 拿下今年最大笔潮玩市场融资,52TOYS投资价值几何?
  20. 科普之Linux应用程序与内核程序交互的几种方式。

热门文章

  1. android 绘画笔迹回放_随时记录分享书写笔迹,EverPEN高级版套装体验
  2. C/C++小游戏 ——贪吃蛇
  3. Floyd算法的理解
  4. android压缩图片质量,Android 图片质量压缩有关问题
  5. 从未在一起更让人遗憾_二十不惑强行悲伤结尾,我们本可以在一起,才最让人遗憾...
  6. matlab机械手ikine函数,关于Mtalab-robotics工具箱中的fkine和ikine两个函数的问题讨论!...
  7. Qt图形界面编程入门(4)
  8. mysql批量写入100万数据_Mysql数据库实践操作之————批量插入数据(100万级别的数据)-阿里云开发者社区...
  9. php养老院管理系统,XYCMS养老院建站系统 v3.8
  10. MySQL 之binlog日志说明及利用binlog日志恢复数据操作记录