2019独角兽企业重金招聘Python工程师标准>>>

概览

本文主要介绍如何使用RabbitMQ消息代理来实现分布式系统之间的通信,从而促进微服务的松耦合。

RabbitMQ,也被称为开源消息代理,它支持多种消息协议,并且可以部署在分布式系统上。它轻量级,便于部署应用程序。它主要充当一个队列,其中输入的消息可以首先被操作。RabbitMQ可以在许多操作系统和云环境中运行,并为大多数流行语言提供了广泛的开发工具。它是生产者-消费者模式,生产者发出信息,消费者消费信息。RabbitMQ的主要特点如下:

异步消息

分布式部署

管理和监控

企业和云计算

安装

对于RabbitMQ,首先需要在系统中安装ErLang,因为RabbitMQ是用ErLang语言编写的。安装Erlang之后,你可以通过下面的介绍从它的官网下载最新版本的 RabbitMQ 。

在微服务中使用RabbitMQ

在您的微服务体系结构中,RabbitMQ是实现消息队列的最简单的免费的可用选项之一。这些队列模式有助于解耦各个微服务之间的通信来增加应用程序的弹性。我们可以将这些队列用于各种目的,比如核心微服务之间的交互、微服务的解耦、实现故障转移机制,以及通过消息代理发送电子邮件通知。

无论在哪里,只要有两个或两个以上的核心模块需要相互通信,我们就不应该进行直接的HTTP调用,因为它们会使核心层产生紧耦合,并且当每个核心模块有更多实例时将很难管理。而且每当服务宕机时,HTTP调用模式就会失败,因为在服务重启之后,我们将无法跟踪旧的HTTP请求调用。这就产生了对RabbitMQ的需求。

在微服务中设置RabbitMQ

在微服务架构中,为了演示,我们将使用一个可以通过任何核心微服务发送电子邮件通知的示例模式。在这种模式下,我们将有一个可以存在任何核心微服务的生产者,它将生成电子邮件内容并将其发送到队列。然后,这个电子邮件内容由总是在等待队列中新消息的消费者来处理。

请注意,由于正在使用Spring Boot构建微服务,因此我们将为Spring提供配置。

1)生产者:这一层负责生成电子邮件内容,并将此内容发送给RabbitMQ中的消息代理。

a)在properties文件中,我们需要配置队列名和交换类型,以及安装RabbitMQ服务器的主机和端口。

queue.name=messagequeue

fanout.exchange=messagequeue-exchange

spring.rabbitmq.host: localhost

spring.rabbitmq.port: 5672

spring.rabbitmq.username: guest

spring.rabbitmq.password: guest

b)我们需要创建一个配置类,它将使用队列名和交换类型将队列绑定到微服务模块。

@Configuration

public class RabbitConfiguration {

@Value("${fanout.exchange}")

private String fanoutExchange;

@Value("${queue.name}")

private String queueName;

@Bean

Queue queue() {

return new Queue(queueName, true);

}

@Bean

FanoutExchange exchange() {

return new FanoutExchange(fanoutExchange);

}

@Bean

Binding binding(Queue queue, FanoutExchange exchange) {

return BindingBuilder.bind(queue).to(exchange);

}

}

c)最后,我们需要一个工具类,它将使用Spring框架提供的RabbitTemplate将实际的电子邮件内容发送到队列中。

@Component

public class QueueProducer {

protected Logger logger = LoggerFactory.getLogger(getClass());

@Value("${fanout.exchange}")

private String fanoutExchange;

private final RabbitTemplate rabbitTemplate;

@Autowired

public QueueProducer(RabbitTemplate rabbitTemplate) {

super();

this.rabbitTemplate = rabbitTemplate;

}

public void produce(NotificationRequestDTO notificationDTO) throws Exception {

logger.info("Storing notification...");

rabbitTemplate.setExchange(fanoutExchange);

rabbitTemplate.convertAndSend(new ObjectMapper().writeValueAsString(notificationDTO));

logger.info("Notification stored in queue sucessfully");

}

}

d)然后,您可以在模块的任何地方调用这个produce方法。

{

queueProducer.produce(notificationDTO);

}

2) 消费者:这一层负责使用FIFO方法从RabbitMQ消息代理中消费消息,然后执行与电子邮件相关的操作。

a)在这个properties文件中,我们需要配置队列名和交换类型,以及安装RabbitMQ服务器的主机和端口。

queue.name=messagequeue

fanout.exchange=messagequeue-exchange

spring.rabbitmq.host: localhost

spring.rabbitmq.port: 5672

spring.rabbitmq.username: guest

spring.rabbitmq.password: guest

b)我们需要创建一个配置类,它将使用队列名和交换类型将队列绑定到微服务模块。此外,在消费者的RabbitMQ配置中,我们需要创建一个充当消费者的MessageListenerAdapter bean,它始终侦听从队列中传入的消息。这个MessageListenerAdapter将有一个带有消费者工具类和defaultListenerMethod的有参构造函数,在这里我们可以指定与电子邮件相关的操作。

@Configuration

public class RabbitConfiguration {

private static final String LISTENER_METHOD = "receiveMessage";

@Value("${queue.name}")

private String queueName;

@Value("${fanout.exchange}")

private String fanoutExchange;

@Bean

Queue queue() {

return new Queue(queueName, true);

}

@Bean

FanoutExchange exchange() {

return new FanoutExchange(fanoutExchange);

}

@Bean

Binding binding(Queue queue, FanoutExchange exchange) {

return BindingBuilder.bind(queue).to(exchange);

}

@Bean

SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,

MessageListenerAdapter listenerAdapter) {

SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();

container.setConnectionFactory(connectionFactory);

container.setQueueNames(queueName);

container.setMessageListener(listenerAdapter);

return container;

}

@Bean

MessageListenerAdapter listenerAdapter(QueueConsumer consumer) {

return new MessageListenerAdapter(consumer, LISTENER_METHOD);

}

}

c)然后,需要创建具有特定消息侦听器方法的 QueueConsumer类,在该类中我们可以进行实际发送电子邮件的操作。

@Component

public class QueueConsumer {

@Autowired

MailServiceImpl mailServiceImpl;

protected Logger logger = LoggerFactory.getLogger(getClass());

public void receiveMessage(String message) {

logger.info("Received (String) " + message);

processMessage(message);

}

public void receiveMessage(byte[] message) {

String strMessage = new String(message);

logger.info("Received (No String) " + strMessage);

processMessage(strMessage);

}

private void processMessage(String message) {

try {

MailDTO mailDTO = new ObjectMapper().readValue(message, MailDTO.class);

ValidationUtil.validateMailDTO(mailDTO);

mailServiceImpl.sendMail(mailDTO, null);

} catch (JsonParseException e) {

logger.warn("Bad JSON in message: " + message);

} catch (JsonMappingException e) {

logger.warn("cannot map JSON to NotificationRequest: " + message);

} catch (Exception e) {

logger.error(e.getMessage());

}

}

}

总结

通过使用RabbitMQ,您可以避免服务之间直接的HTTP调用,并消除核心微服务的紧密耦合。这将帮助您在更高级别上实现微服务的可伸缩性,并在微服务之间添加故障转移机制。

转载于:https://my.oschina.net/u/3959468/blog/2223395

探索解析微服务下的RabbitMQ相关推荐

  1. Nepxion Discovery【探索】微服务企业级解决方案

    Nepxion Discovery[探索]微服务企业级解决方案 Nepxion Discovery[探索]使用指南,基于Spring Cloud Greenwich版.Finchley版和Hoxton ...

  2. 微服务下的APM全链路监控

    https://opentalk.upyun.com/333.html 2017 年 10 月 29 日,又拍云 Open Talk 联合 Spring Cloud 中国社区成功举办了"进击 ...

  3. AspNetCore微服务下的网关-Kong(一)

    Kong是Mashape开源的高性能高可用API网关和API服务管理层.它基于OpenResty,进行API管理,并提供了插件实现API的AOP.Kong在Mashape 管理了超过15,000 个A ...

  4. 微服务下使用GraphQL构建BFF

    https://zhuanlan.zhihu.com/p/35108457 微服务架构,这个在几年前还算比较前卫的技术在如今遍地开花.得益于开源社区的支持,我们可以轻松地利用 Spring Cloud ...

  5. 微服务下蓝绿部署、红黑部署、AB测试、灰度发布、金丝雀发布、滚动发布的概念与区别...

    更多内容关注微信公众号:fullstack888 在有关微服务.DevOps.Cloud-native的迭代过程中,不可避免的需要"上线",上线就需要部署,需要部署就意味着有修改, ...

  6. 微服务下权限校验方案

    微服务权限校验方案 权限概述 鉴权和权限控制 权限问题描述 权限概述 任何一个系统都绕不开权限这两个字,一个良好的权限设计对一个系统起到了非常重要的作用,其实权限设计是个范围很大的问题,包括从数据库的 ...

  7. 如何保证微服务下的数据一致性?

    目录 1.传统应用的事务管理 1.1 本地事务 1.2 分布式事务 1.2.1 两阶段提交(2PC) 1.2.2 三阶段提交(3PC) 2.微服务下的事务管理 3.实现微服务下数据一致性的方式 3.1 ...

  8. 微服务下数据表之间的耦合关系

    微服务下数据表之间的耦合关系 1.问题产生 今天同事给我发了一个链接,问我这种做可视化建表的过程觉得怎么样?(如下图) 同事的意思主要是,在微服务架构下,新建单一数据表,然后表内数据需要引用其他数据表 ...

  9. 【智简联接,万物互联】华为云·云享专家董昕:Serverless和微服务下, IoT的变革蓄势待发

    摘要:Serverless.微服务,这些新技术和IoT有什么关系?纵观IoT行业的发展,云服务又扮演了什么角色? IoT并不是一个新名词.新技术,很长一段时间,它甚至给人一种"下工地&quo ...

  10. 微服务下的链路追踪(Sleuth+Zipkin)

    目录 Sleuth简介 相关术语 使用Sleuth 引入依赖 创建服务 product-service order-service 启动&测试 Zipkin 使用Zipkin 参考文章 Sle ...

最新文章

  1. 关于text段、data段和bss段
  2. 进制在c语言中的作用,C语言中的进制是什么意思?
  3. ifix从sqlserver里读数据_ifix连接SQL和读写EXCEL的方法
  4. Nginx反向代理负载均衡时,验证码不正确
  5. boost::polygon模块实现多边形点相关的测试程序
  6. puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  7. es对已有的索引给主键_ES中对索引的相关操作
  8. 软件中的1、同步调用;2、回调;3、异步调用
  9. 首都富版本更新说明文档
  10. spreadsheet js中创建下拉列表_JS 中创建自定义排序方法
  11. Jquery.ajax发送参数调用.Net Mvc子方法返回一个子页面嵌入当前页
  12. Spring Boot中级篇-集成Swagger2分组文档
  13. 否认气候变暖的人都是睁眼说瞎话
  14. 飞机大战——图文详解
  15. js中ajax提交表单提交表单提交,JS中ajax请求提交form表单
  16. 生鲜行业采购管理系统把控采购成本,实现精细化管理
  17. 逻辑运算符 异或是什么意思 异或运算
  18. 日志收集之--将Kafka数据导入elasticsearch
  19. 新建 FrameMaker API 时引用目录的设置
  20. Oracle ERP 库存管理(业务流程 核心流程) [转]

热门文章

  1. canvas与svg的区别
  2. 【题解】Luogu P2157 [SDOI2009]学校食堂
  3. IDEA+MAVEN+testNG(reportNG)
  4. Win10 安装 Linux 子系统
  5. 第三百四十五天 how can I 坚持
  6. Swift-函数学习
  7. 《玩转D语言系列》三、轻松大跃进,把它当C语言先用起来
  8. C++请不要问我string s=”a”+”b”分配了几次内存
  9. 顶点计划 顾家与工作问题讨论
  10. 重写了GVBASIC模拟器