文章目录提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
- 一、跨项目,跨服务之间的通信方式
- 1.无论是跨项目通信,还是跨服务通信,cloud中通信方式基本就是两种:
- 2.关于银行跨行转账:
- 3.我们发邮件,发短信,发站内信时最好使用异步编程
- 4.如何实现异步编程?
- 二、消息队列MQ
- 1.消息队列的四个使用场景
- 三.课程上线消息推送
- 四.单独搭建一个消息推送服务;
- 第一步:依赖
- 第二步:启动类
- 第三步:bootstrap.yml
- 第四步:在消息服务中,新建一个配置类声明交换机,队列,绑定关系
- 第五步:在消息服务中新建一个dto类
- 第六步:在消息服务中新建一个MsgController
- 第七步:在消息服务中搭建一个hrm-msg-feign模块
- 第八步:新建一个MsgProducerClentFallback类,实现。。。FallBack接口,泛型是
- 五.其他服务调用消息服务:
- 六.准备一个消费者模块,从MQ中拉取消息消费
- 5.注意:
- 总结
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
一、跨项目,跨服务之间的通信方式 1.无论是跨项目通信,还是跨服务通信,cloud中通信方式基本就是两种:
1)不同项目中:A项目直接给B项目发送Http请求或RPC请求,同一个项目中,A服务直接给B服务发送Http请求或RPC请求;(OpenFeign,Ribbon就是使用这种方式)
以下图为例子:A项目发送Http请求或者RPC请求,直接访问项目B,这种直接访问的方式具有强一致性:就是说A服务必须要等到B服务返回结果才能继续往下执行;
所以这种就不太好;
2)项目A,项目B之间通过MQ进行通信,MQ是天然具有异步性的,A项目通过MQ发送消息给到B项目,B项目从MQ拉取项目然后进行消费;
这样的好处就是:A项目往MQ推送消息后就可以不用管了,就可以继续做其他事情;
总结:当跨项目进行通信时,我们建议使用MQ;当跨服务进行通信时,使用OpenFeign就可以了;
比如工商银行与中国银行之间的跨行转账,这两家银行的系统绝对是两个不同的项目,所以它们一定是使用MQ进行通信的;
为什么它们不是用Http请求直接通信的?因为如果是使用Http请求,会存在强一致性问题,工商银行发起跨行转账后,必须等到中国银行返回了消息结果给工商银行,工商银行这边的跨行转账业务才算完成成功,但是中国银行肯定会优先完成自己的业务,所以这种情况,工商银行就会等很久,显然不合适;所以银行跨行转账才使用MQ操作;
但是使用MQ通信会存在消息排队的问题;所以当天跨行转账的人数很多时,跨行到账的时间可能会有较久的延迟;但是银行会保证24小时之内能到账,那银行到底是如何保证的?
银行会根据跨行转账的业务繁忙程度动态的增加消费者,平时业务不这么忙的时候,消费者就开少一点,一忙起来,消费者就躲开,增强处理请求的能力,所以它们能保证24小时内完成跨行转账;
项目二中发邮件,发短信,发站内信存在一个问题,前端平台客户点击发送邮件后,如果不采用异步编程,假如后台发送邮件的逻辑处理变慢,那么就会导致前端的邮件发送界面一直转圈;体验很不好;
使用异步编程的好处是:用户点击发送邮件后,只要一点,就不用再等待后台返回结果给前端了;用户就可以继续再干其他的事,比如继续发送下一封邮件等;
1.使用MQ,MQ天然就是异步的。2.单独开一个线程,多线程当然是异步的。
其中使用多线程时,我们可以考虑线程池,比我们手动开启线程方便的多;
总体来说:只要项目中需要处理异步、消峰、解耦、通信的地方都可以使用消息队列:
1)不同项目或者服务之间发生通信时,可以使用MQ来传递消息;
场景:异步下单中,秒杀服务需要将下订单所需的数据作为消息内容传递给订单服务;页面静态化功能中,后端生成静态页面上传到OSS后,将地址作为消息推送到消息前端项目服务器部署的Java项目(消费者);
2)异步:生产者发送消息后,无需等待消费者处理完毕消息;
场景;微服务电商平台里面秒杀活动中,秒杀服务中通过分布式锁技术扣减库存,然后推送消息到订单服务;
3)消峰:消息队列可以配置最多允许多少个消息在队列中排队;
场景:规定同一时间内不能有太多请求(假设1000个)进入到消费者项目接口;假设此时瞬间来了1万个消息,其余9000个消息先进入死信队列,然后配合一个定时任务,每隔一段时间从死信队列里面拿出前面的N个消息补充到正常队列中;
4)解耦:应用程序之间进行通信是松耦合的,应用程序之间无需通过HTTP或者RPC请求进行调用;
场景:跨行转账、支付宝微信提现;
1.架构设计
@Configuration
public class MQ {
//交换机
private static final String EXCHANGE_HRM_MSG_TOPIC = "exchange_hrm_msg_topic";
//短信队列
private static final String QUEUE_HRM_MSG_SMS = "queue_hrm_msg_sms";
//邮件队列
private static final String QUEUE_HRM_MSG_EMAIL = "queue_hrm_msg_email";
//站内信队列
private static final String QUEUE_HRM_MSG_SYSTEM_MESSAGE = "queue_hrm_msg_system_message";
@Bean
public Exchange exchange(){
return ExchangeBuilder.topicExchange(EXCHANGE_HRM_MSG_TOPIC)
.durable(true)
.build();
}
@Bean(QUEUE_HRM_MSG_SMS)
public Queue queueSms(){
return QueueBuilder.durable(QUEUE_HRM_MSG_SMS).build();
}
@Bean(QUEUE_HRM_MSG_EMAIL)
public Queue queueEmail(){
return QueueBuilder.durable(QUEUE_HRM_MSG_EMAIL).build();
}
@Bean(QUEUE_HRM_MSG_SYSTEM_MESSAGE)
public Queue queueSystemMessage(){
return QueueBuilder.durable(QUEUE_HRM_MSG_SYSTEM_MESSAGE).build();
}
@Bean
public Binding bindingSms(Exchange exchange, @Qualifier(QUEUE_HRM_MSG_SMS)Queue queue){
return BindingBuilder
.bind(queue)
.to(exchange)
.with("sms.#")
.noargs();
}
@Bean
public Binding bindingEmail(Exchange exchange, @Qualifier(QUEUE_HRM_MSG_EMAIL)Queue queue){
return BindingBuilder
.bind(queue)
.to(exchange)
.with("email.#")
.noargs();
}
@Bean
public Binding bindingSystemMessage(Exchange exchange, @Qualifier(QUEUE_HRM_MSG_SYSTEM_MESSAGE)Queue queue){
return BindingBuilder
.bind(queue)
.to(exchange)
.with("system.message.#")
.noargs();
}
}
第五步:在消息服务中新建一个dto类
这个Msg类
新建一个接口push,这个接口的作用是让消息服务能推送消息到MQ中;
其他服务在调用消息服务时push接口时,需要传递Msg对象过来;
把msg作为消息推送到mq中;
其他服务要调用消息服务时,就可以调用hrm-msg-feign模块
注意:下图中的MsgProducerClientFallback后面有.class,截图只截少了一部分;
MsgController类上的@RequestMapping是@RequestMapping(“/msgProducer”),push接口的@RequestMapping是(“/push”);所以MsgProducerClent接口中,可以在@FeignClient注解中加path = “/msgProducer” ,也可以直接加在MsgProducerClent接口的push方法上面的@PostMapping中,就像上图这样;
其他服务要调用消息服务时,首先要创建一个Msg对象;
以发送短信为例:
msg要设置接收方的电话,还要设置routingkey,以便找到具体哪个路由;
1.配置yaml
2.配置bootstrap.yaml
3.准备pom
①jackson-databind这个依赖是用来序列化Msg对象的;
②导入hrm-msg-common依赖,是因为消息传输对象Msg类是写在hrm-msg-common模块的;
③导入starter-amqp依赖是因为消费者要从MQ拉取消息,所以要starter-amqp依赖
4.消费者模块中新建一个监听类
消费者收到消息后的业务处理逻辑都写在监听类中
@RabbitListener注解表示这是一个RabbitMq的监听类,要在@RabbitListener里面指定当前类具体监听的哪一个队列,要指定队列名称;
形参里的Msg是消息推送服务往MQ推送的消息,推送的什么,Msg msg这里就填什么;后面两个参数Message message,Channel channel 不变;
然后通过message.getMessageProperties()可以获得mq的所有属性参数,然后.getDeliveryTag()就可以获得deiveryTag对象;注意multiple基本都会设置为false;
5.消息序列化
往MQ传输消息的时候,需要将消息序列化:
消息序列化的两种方式:JDK序列化和JSON序列化,我们采用JSON序列化的方式,因为它更优秀;
首先:
在调用消息服务的课程服务中,新建一个配置类,自定义一个RabbitTemplate的@Bean,用来覆盖掉starter-amqp依赖中自带的RabbitTemplate;代码写法如下:
其次:
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。



