ActiveMq(二)

1.签收

ActiveMq(二)_第1张图片

public interface Session extends Runnable {
    
    int AUTO_ACKNOWLEDGE = 1;   // 自动签收
    int CLIENT_ACKNOWLEDGE = 2;  // 客户端确认签收
    int DUPS_OK_ACKNOWLEDGE = 3; // 自动批量进行签收
    int SESSION_TRANSACTED = 0;  // 事务提交就签收
    
}

注意:事务会话中,如果一个事务提交成功,这个时候就签收!事务混滚,消息就会被再次传送。

没有事务的情况下,如果是 客户端确认签收,那则需要手动签收。

一般用自动 手动

message.acknowledge(); // 消息确认签收

2.Broker

Broker:将 ActvieMQ … 以代码的形式内嵌到我们程序中。保证随时可以启动进行使用。
官网地址:http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection



    com.fasterxml.jackson.core
    jackson-databind
    2.11.0

代码

public class EmbedBroker {
    public static void main(String[] args) throws Exception {
        // 1.创建服务
        BrokerService broker = new BrokerService();

        // 2、配置连接地址
        // jmx是java的一个新框架
        // 允许将我们所有的资源(软件和硬件)封装一个Java对象,直接暴露在服务中即可使用
        broker.setUseJmx(true);
        broker.addConnector("tcp://localhost:61616");

        // 3、启动
        broker.start();
    }
}

3.整合SpringBoot

1.导入依赖


    org.springframework.boot
    spring-boot-starter-activemq


    org.springframework.boot
    spring-boot-starter-web

2.配置yaml

server:
  port: 9000
spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616
    user: admin
    password: admin
  jms:
    pub-sub-domain: false # false 队列,  true 主题

myqueue: coding-queue

比较

server.port=9090
spring.activemq.broker-url=tcp://127.0.0.1:61616
# 在考虑结束之前等待的时间
#spring.activemq.close-timeout=15s
# 默认代理URL是否应该在内存中。如果指定了显式代理,则忽略此值。
spring.activemq.in-memory=true 
# 是否在回滚回滚消息之前停止消息传递。这意味着当启用此命令时,消息顺序不会被保留。
spring.activemq.non-blocking-redelivery=false
# 等待消息发送响应的时间。设置为0等待永远。
spring.activemq.send-timeout=0
#默认情况下activemq提供的是queue模式,若要使用topic模式需要配置下面配置
spring.jms.pub-sub-domain=true
#账号
spring.activemq.user=admin
# 密码
spring.activemq.password=admin
# 是否信任所有包
#spring.activemq.packages.trust-all=
# 要信任的特定包的逗号分隔列表(当不信任所有包时)
#spring.activemq.packages.trusted=
# 当连接请求和池满时是否阻塞。设置false会抛“JMSException异常”。
#spring.activemq.pool.block-if-full=true
# 如果池仍然满,则在抛出异常前阻塞时间。
#spring.activemq.pool.block-if-full-timeout=-1ms
# 是否在启动时创建连接。可以在启动时用于加热池。
#spring.activemq.pool.create-connection-on-startup=true
# 是否用Pooledconnectionfactory代替普通的ConnectionFactory。
#spring.activemq.pool.enabled=false
# 连接过期超时。
#spring.activemq.pool.expiry-timeout=0ms
# 连接空闲超时
#spring.activemq.pool.idle-timeout=30s
# 连接池最大连接数
#spring.activemq.pool.max-connections=1
# 每个连接的有效会话的最大数目。
#spring.activemq.pool.maximum-active-session-per-connection=500
# 当有"JMSException"时尝试重新连接
#spring.activemq.pool.reconnect-on-exception=true
# 在空闲连接清除线程之间运行的时间。当为负数时,没有空闲连接驱逐线程运行。
#spring.activemq.pool.time-between-expiration-check=-1ms
# 是否只使用一个MessageProducer
#spring.activemq.pool.use-anonymous-producers=true

3.配置Bean

import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;

// 注意导包,util java中的队列
// JMS 下的队列
import javax.jms.Queue;

@Configuration
@EnableJms // 声明对 JMS 注解支持
public class ActiveMQConfig {

    @Value("${myqueue}")
    private String myqueue;

    @Bean
    public Queue queue(){
        return new ActiveMQQueue(myqueue);
    }

}

4.业务 生产者

@Component
public class QueueProduce {

    // springboot  xxxTemplate
    @Autowired
    private JmsMessagingTemplate template;

    @Autowired
    private Queue queue;

    public void produceMsg(){
        template.convertAndSend(queue,"produceMsg");
    }

}
@RestController
public class ActiveMQController {

    @Autowired
    private QueueProduce queueProduce;

    @RequestMapping("/queue/send")
    public void queue_send(){
        queueProduce.produceMsg();
        System.out.println(" 消息发送成功");
    }


}

ActiveMq(二)_第2张图片5.定时发送

@Component
public class QueueProduce {
    @Autowired
    private JmsMessagingTemplate template;

    @Autowired
    private Queue queue;
    @Scheduled(fixedDelay = 3000)
    public void produceMsg(){
        template.convertAndSend(queue,"produceMsg");
        System.out.println("定时发送消息");
    }
}
@EnableScheduling
@SpringBootApplication
public class ActivemqApplication {

    public static void main(String[] args) {
        SpringApplication.run(ActivemqApplication.class, args);
    }

}

ActiveMq(二)_第3张图片
6.消息消费者

@Configuration
public class QueueConsumer {
    // 通过监听注解实现消息接收。
    // 具体消费  目的地:(队列还是主题)  接收到的消息
    @JmsListener(destination = "${myqueue}")
    public void receive(TextMessage textMessage) throws JMSException {
        System.out.println(textMessage.getText());
    }
}

ActiveMq(二)_第4张图片
主题生成者
ActiveMq(二)_第5张图片

@Bean
public Topic topic(){
    return new ActiveMQTopic(mytopic);
}

与队列一样 把 queue 换 topic

@Component
public class TopicProduce {
    @Autowired
    private JmsMessagingTemplate template;

    // 先启动消费者。。
    @Autowired
    private Topic topic;

    @Scheduled(fixedDelay = 3000)
    public void produceMsgScheduled(){
        template.convertAndSend(topic,"produceMsgTopic");
        System.out.println("系统正在定时发送消息.....");
    }

}

@Configuration
public class TopicConsumer {

    // 具体消费  目的地:(队列还是主题)  接收到的消息
    @JmsListener(destination= "${mytopic}")
    public void receive(TextMessage textMessage) throws JMSException {
        // 接收消息
        System.out.println(textMessage.getText());
    }

}

4.ActiveMQ传输协议

配置:conf/activemq.xml 就是一个 Spring的配置
在这里插入图片描述tcp
网络传输必须序列化,消息通过一个叫wire protocol 来序列化成字节流
wire protocol默认openwire
参数配置参考文档(一般不动)
http://activemq.apache.org/tcp-transport-reference

nio
端口需自定义


    
      

升级版
auto+nio
其他协议不太常用 用的话需更改代码

5.可持久化

kahaDB
像redisaof日志存储 5.4默认
KahaDB特性:

1、日志的方式存储的信息

2、B-Tree 索引,快速更新

3、可以快速恢复数据
ActiveMq(二)_第6张图片
db.data 保存数据的,B-tree 所用。

db.redo 恢复消息的。自动启动然后备份

lock 锁,表示 kahadb的读写权限。

jdbc mysql
比较慢


        
        
        
        
   



      
   


  
          
        
          
          
          
            
 

引入三个jar 到 activemq 安装的lib 目录下
在这里插入图片描述
http://activemq.apache.org/persistence
LevelDB

6.集群

官网地址:http://activemq.apache.org/masterslave
ActiveMq(二)_第7张图片
zookeeper集群
这篇博客linux:https://www.cnblogs.com/yangzhenlong/p/8270835.html
win上集群
1.复制3分zookeeper
在这里插入图片描述
2.复制zoo_sample.cfg一份更改成zoo.cfg
ActiveMq(二)_第8张图片
3.在每个apache-zookeeper-9001下建data目录
data建myid
在这里插入图片描述
内容对应9001对应1 , 9002对应2
在这里插入图片描述
4.配置zoo.cfg
分别更改端口和dataDir路径 其他不变
ActiveMq(二)_第9张图片5.可以写个脚本 一键启动
ActiveMq(二)_第10张图片
ActiveMq(二)_第11张图片

MQ集群

node-1 61616 8161

node-2 61617 8162

node-3 61618 8163

1.复制3分mq

2、保证 brokername 相同,默认是localhost,集群的前提就是 borkerName一致。

3.修改activemq.xml文件及端口

hostname=“broker-ms1” 不同
hostname中的值需要在系统的hosts文件中配置,如果不想配置就直接写当前机器的IP
直接127.0.0.1启动时会报
C:\Windows\System32\drivers\etc
Unexpected session error: java.io.IOException: java.nio.channels.UnresolvedAddressException


    


在这里插入图片描述
以节点2为例


    
    


  
  
      

修改jetty.xml启动端口


    
     

4.一键启动
ActiveMq(二)_第12张图片
ActiveMq(二)_第13张图片

问题
1.引入消息队列如何保证其高可用
持久化 事务 签收 集群
2.异步投递Async Sends
有俩种同步 开启同步 在没开启事务去持久化

useAsyncSend=true开启异步客户端要容忍消息丢失的可能
开启异步3种
1.在路径 “tcp://127.0.0.1:61616?jms.useAsyncSend=true"
2.ActiveMQConnectionFactory对象.setUseAsyncSend(true)
3.ActiveMQConnection对象.setUseAsyncSend(true)

确保成功异步回调
message.setJMSMessageID(UUID.randomUUID.toString+"…")
在消息头设置标识 回调成功失败 返回
activeMQMessageProducer.send(message,new AsyncCallback()…)

3.延时投递和定时投递
ActiveMq(二)_第14张图片

public class TestMQ {
    //地址
    public static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";
    public static void main(String[] args) throws JMSException {
        //2.创建连接工厂
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //3. 获得连接
        Connection connection = factory.createConnection();

        connection.start();
        // 4、创建会话
        // 参数:事务、签收  AUTO_ACKNOWLEDGE : 自动确认
        Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
        //5.模式 队列 主题

        Queue queue = session.createQueue("queue11");
        //6.发送消息(生产者)
        MessageProducer producer = session.createProducer(queue);
        // 7、发送具体的消息到队列, 创建的消息类型是什么就些什么
        // 简单文本(TextMessage)、可序列化的对象 (ObjectMessage)、属性集合 (MapMessage)、字节流 (BytesMessage)、原始值流 (StreamMessage),还有无有效负载的消息 (Message)。
        for (int i = 1; i <3 ; i++) {
            TextMessage message= session.createTextMessage("消息"+i);
            long time = 60 * 1000;// 延时1min
		    long period = 10 * 1000;// 每个10s
		    int repeat = 6;// 6次
		    message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);
		    message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, period);
		    message.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, repeat);
            //8.发送消息
            producer.send(textMessage);
        }
        //9.关闭流
        producer.close();
        session.close();
        connection.close();
        System.out.println("发送完毕");
    }

4.分发策略

5.activemq消费重试机制
什么情况引起消息重发
用事务且在session中调用rollback()
用事务调用commit()之前关闭 或者 没有commit()
在CLIENT_ACKNOWLEDGE的传递模式下 在session中调用了recover
client acknowledge
间隔:1
次数: 6
重发6次后 消息端会给MQ发送一个“poison ack” 告诉broker别发了 broker就把消息放到DLQ(死信队列)
官网的重发 http://activemq.apache.org/redelivery-policy

6.死信队列
默认不会把非持久的死消息发送到死信队列

 
            
              
                
                  
                    
                  
                 
                // “>”表示对所有队列生效,如果需要设置指定队列,则直接写队 列名称 

             
                   
                 //queuePrefix:设置死信队列前缀 
                     
                     //是否丢弃过期消息
                     
                    
                
              
            
        

7.如何保证消息不被重复消费呢?幂等性问题谈谈
用redis 把成功的一k v存入 消费前查询k是否有 来判断是否重复
如何保证消息的可靠传输?如果消息丢了怎么办
ActiveMq(二)_第15张图片

你可能感兴趣的:(acitveMq,java)