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

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 用户名与密码是我们在启动是写入的。

739c35ebecc6cc686c34148f7f06729d.png

mq能解决什么?

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

异步消息

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

0f10817f8a808879665fd11e4351073d.png

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

36a503018d4227d9633f88e991cd31db.png

应用间解耦

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

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

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

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

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

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

流量削峰

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

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

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

8611fa2a30504c3586c846f81e350483.png

实战案例

本文是按照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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538750.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Angular v6 正式发布

Angular 6 正式发布 Angular 6 已经正式发布了!这个主要版本并不关注于底层的框架,更多地关注于工具链,以及使 Angular 在未来更容易快速推进。 作为发布的一部分,我们同步了主要的框架包 (angular/core, angular/common, angula…

py 字典添加多个value_# Python 3 # Python 3字典Dictionary(1)

Python3 字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,格式如下所示:d {key1 : value1, key2 : value2 }键必须是唯…

饶军:Apache Kafka的过去,现在,和未来

欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 本文首发在云社区,未经许可,不得转载。大家好,我大概简单的介绍一下,我叫饶军,我是硅谷的初创公司Confluent的联合创始人之一,我们公司…

Android手机avi转换为mp4手机,如何把avi转换为mp4

AVI是目前比较常见的一种音视频交错格式,这种格式的文件在多种地方是可以看到的,大多在游戏录制、光盘文件中可以见到此类文件。其画质不错,适合在电脑上观看,但是现在我们使用较多的是手机、iPad等设备。如果我们想要在这些设备上…

伪代码书写规范_C++代码书写规范(推荐新手程序员)

代码就是程序员的面子,无论是在工作中在电脑上写程序代码还是在面试时在纸上写演示代码我们都希望写出整洁,优雅的代码。特别在工作中当我们碰到需要维护别人的代码,或者是多人参与一个项目大家一起写代码的时候,如果碰到一些丑陋…

Java基础17:Java IO流总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a724888/article/details/80201802 这位大侠,这是我的公众号:程序员江湖。 分享程序员面试与技术的那些事。 干货满满,关注就送。 本文介…

html语言闪烁特效代码,css3 文字闪烁特效代码

今天给大家分享几个文字闪烁特效代码,纯css3代码实现,对于新手小伙伴值得拿来学习一下。文字闪烁特效一通过改变透明度来实现文字的渐变闪烁,代码如下:文字闪烁:闪烁效果.main{color: #666;margin-top: 50px;}/* 定义k…

2021年山西副高考试成绩查询,中国卫生人才网2021年山西卫生资格考试成绩查询...

2021年山西卫生资格考试成绩查询 由中国卫生人才网考试快讯提供,以及提供2021国家卫生资格成绩查询考试信息。更多关于2021年山西卫生资格考试成绩查询 ,卫生资格考试,2021卫生资格考试,卫生资格成绩快讯的内容,请关注国家卫生资格考试网!!20…

团队项目作业1-团队展示与选题

团队展示: 队名:summer 团队项目描述:基于java 、web的四则运算网站的开发,有三种角色:老师、家长、学生。老师在网站上发布四则运算作业,可以设置题目数量,数值范围、以及完成作业限定的时间。…

SP2-0734: 未知的命令开头 imp scott/... - 忽略了剩余的行。

原文地址:http://blog.csdn.net/yangwenxue_admin/article/details/47667943 Oracle数据导入报错:SP2-0734: 未知的命令开头 "imp scott/..." - 忽略了剩余的行。 原因:进入sqlplus里是不能执行imp的(sqlplus不认识imp)&#xff0c…

impdp导入dmp文件

impdp命令在cmd下直接用,不必登录oracle。只能导入expdp导出的dmp文件。 expdp导出的时候,需要创建 DIRECTORY 导出什么表空间,导入也要什么表空间。 导出什么用户,导入也要什么用户。 如果没有要新建。 从杭州服务器expdp导出…

高中技校学计算机,我没考上高中,英语数学极差,想上技校学计算机专业,玩代码的那种,有前途吗?...

我没考上高中,英语数学极差,想上技校学计算机专业,玩代码的那种,有前途吗?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!我没考上…

html中函数传递多个值,JavaScript 实战开发经验!函数多参数传参技巧

HTML5学堂-码匠:掌握JavaScript代码的你,一定编写封装过函数,为了提升函数的控制性,必不可少的就是参数,必选可选的一大堆参数罗列出来,函数调用貌似变得麻烦起来~~~Tips:必选参数指的是必须要传…

软件工程学习笔记(考试版)

软 件 工 程 笔 记 第一章 一个软件产品必须由一个完整的配置组成,软件配置主要包括:程序,数据及相关文档。程序是能够完成预定功能和性能的可执行的指令序列;数据是使程序能够适当的处理信息的数据结构;文档是开发使…

印象笔记编辑pdf_笔记软件使用体验(至2020.03)

几年的时间,从OneNote到为知笔记,再到印象笔记,再回到为知笔记和OneNote,用下来感觉各有优势,也有不爽的地方。 早年间OneNote的同步很有问题,一次同步冲突导致失去了几乎所有笔记本。心灰意冷之下就离开了…

C#获取当前程序运行路径的方法集合

2019独角兽企业重金招聘Python工程师标准>>> // 获取当前进程的完整路径,包含文件名(进程名) Console.WriteLine(GetType().Assembly.Location "\tGetType().Assembly.Location"); // 获取新的 Process 组件并将其与当前活动的进程关联的主模…

Hive thrift服务--beeline使用

hive提供了thrift服务,只要客户端符合thrift标准就可以与它对接。 这样可以以在一台服务器上启动一个hive,其他用户通过thrift访问hive。 hive自带了一个thrift的客户端-------bin/beeline 启动方式: 1、hadoop的core-site.xml增加配置 &l…

vfp控制excel使用sort_使用Python根据索引合并Excel表

有两张不同大小的excel表表1:字典的选项值,2118行表2:字典名称,405行表1和表2有共同的列.现在需要根据共同的列,以表1为底,将表2的值对应添加到表1的每一行。下面是代码:1.加载相关的库import n…

Redis详解(三)

一、Redis集群介绍 Clustering:redis 3.0之后进入生产环境分布式数据库,通过分片机制来进行数据分布,clustering 内的每个节点,仅有数据库的一部分数据;去中心化的集群:redis集群中的每一个节点,都可以作为集群的接入节…