消息队列

1、消息队列概念

消息队列(也称报文队列)是在消息的传输过程中保存消息的容器。

2、为什么要用消息队列
  • 三个最重要的应用场景
2.1、解耦
  • 传统模式

     传统形式下系统间的耦合行太强,一个系统直接调用其他的系统,如果再次加入
    新的系统,又需要重新修改代码,太过于麻烦。传统的解决方式是页面静态化,
    但缺点是不 能随时更新。
    
  • 中间件模式
    在这里插入图片描述
    中间件模式的优点:
                将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而使系统A不需要修改。

2.2、异步

传统模式的缺点:一些不必要的业务逻辑同步进行,耗费时间
中间件模式:将消息写入消息队列中,非必要的业务逻辑以异步的形式运行,加快响应速度。

2.3、削峰

传统模式的缺点:并发量大的时候,所有请求都是直接访问数据库,给数据库太大压力,造成数据库连接异常。
中间件模式的优点:系统A访问数据库,按照数据库能处理的并发量从消息队列中拉去消息。

3、CAP

CAP理论 是由 EricBrewer 教授 提出的,在设计和部署分布式应用的时候,存在三个核心的系统需求,这个三个需求之间存在一定的特殊关系。三个需求如下:

C: Consistency (一致性)
A: Availability (可用性)
P: Partition Tolerance (分区容错性)

CAP理论的核心是:一个分布式系统不可能同时很好的满足 一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。

因此,根据CAP原理,将NoSQL数据库分成满足CA原则、CP原则和AP原则 三大类:
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。 (传统数据库)
CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。 (Redis、MongoDB)
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。 (大多数网站架构的选择)

4、消息队列类型
  • ActiveMQ:不够灵活轻巧,对队列较多情况支持不好.
  • ZeroMQ:灵活快速,不支持持久化,需要大量编码来实现稳定可靠.
  • rocketMQ:性能好,高吞吐,高可用性,支持大规模分布式.
  • kafka:高吞吐,高性能,快速持久化,无消息确认,无消息遗漏,可能会有有重复消息,依赖于zookeeper,成本高.
  • rabbitMQ:稳定,可靠,数据一致,支持多协议,有消息确认,性能一般,基于erlang语言,二次开发困难.
5、JMS

       JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。

6、Demo案例
6.1 配置文件
application.properties


spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
# Whether the default destination type is topic.  
spring.jms.pub-sub-domain=true   //false:queue (默认)一对一用false,一对多 true

6.2 pom依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
6.3 一对一
service层

//发送消息
@Service
public class QueueServiceSender {
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    public void sendQueueMessage(String destination,String msg){
        jmsMessagingTemplate.convertAndSend(destination,msg);
        System.out.println("发送消息:"+msg);
    }

    public void sendQueueMessageMap(String destination, Map msg){
        jmsMessagingTemplate.convertAndSend(destination,msg);
        System.out.println("发送消息:"+msg);
    }
}

//接收消息
@Service
public class QueueServiceReceive {

    @JmsListener(destination = "mymsg")
    public void receive(String test) throws InterruptedException {
        Thread.sleep(30);
        System.out.println("收到消息:"+test);
    }
    @JmsListener(destination = "mymap")
    public void receiveMap(Map msg) throws InterruptedException {
        Thread.sleep(500);
        System.out.println("收到消息:"+msg);
    }

}

注:实际开发中给接收消息加休眠,防止还未提交打印完,就接收到了

6.4 一对多
service层
//发送消息
@Service
public class TopicServiceSender {
    @Autowired
    private JmsMessagingTemplate messagingTemplate;

    public void sendTopicMessageMap(String destination, Map msg){
        messagingTemplate.convertAndSend(new ActiveMQTopic(destination),msg);
        System.out.println("发送消息:"+msg);
    }

//接收消息
@Service
public class TopicServiceReceive {

    @JmsListener(destination = "mytopic")
    public void receiveMap(Map msg) throws InterruptedException {
        Thread.sleep(200);
        System.out.println("收到消息1:"+msg);
    }
    @JmsListener(destination = "mytopic")
    public void receiveMap2(Map msg) throws InterruptedException {
        Thread.sleep(200);
        System.out.println("收到消息2:"+msg);
    }


注:实际开发中给接收消息加休眠,防止还未提交打印完,就接收到了

6.5 测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootJmsApplicationTests {

    @Autowired
    private QueueServiceSender serviceSender;

    @Test
    public void t1() {
        serviceSender.sendQueueMessage("mymsg","hello jms");
    }

    @Test
    public void t2() {
        Map<String,Object> map=new HashMap<>();
        map.put("username","lucy");
        map.put("age",22);
        serviceSender.sendQueueMessageMap("mymap",map);
    }

    @Test
    public void t3() {
        Map<String,Object> map=new HashMap<>();
        map.put("username","lucy");
        map.put("age",22);
        serviceSender.sendQueueMessageMap("mytopic",map);
    }
}

6.6 测试效果图

启动cmd 进入 D:\Working software\apache-activemq-5.15.9-bin\activemq

spring.jms.pub-sub-domain=false
spring.jms.pub-sub-domain=false
spring.jms.pub-sub-domain=true
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值