“老生”畅谈 - ActiveMQ

1 篇文章 0 订阅

1、四大 MQ 介绍

       在介绍 ActiveMQ 之前,我想先把当下存在且有一定认可度的四大 MQ 简单做下说明。为了便于整体观看和比对,我列了如下表格:

名称单机吞吐量Topic 数量对吞吐量的影响时效性可用性可靠性优势
ActiveMQ万级ms高,基于主从架构实现高可用性有较低概率丢失数据
RabbitMQ万级um高,基于主从架构实现高可用性有较低概率丢失数据延迟极低
RocketMQ十万级ms非常高,分布式架构经过参数优化配置,消息可以做到 0 丢失可支持大量 Topic
Kafka十万级ms非常高,分布式架构经过参数优化配置,消息可以做到 0 丢失吞吐量

       其中,RabbitMQRocketMQ 是目前中小型公司用的比较多的。RabbitMQ 是用 erlang 语言开发的,RocketMQ 是用的 Java。如果你是做 Java 开发的,最好选用 RocketMQ,可控制性高。
       Kafka 那当然是大数据必选。至于今天要介绍的 ActiveMQ ,用起来比较简单,但是社区已经不怎么活跃,疲态日显。别问我为啥还在用,我只能告诉你:人在公司,身不由己。

2、JMS

       JMS(Java Messaging Service)是 Java 平台上有关面向消息中间件的技术规范,就像你可以用 JDBC 去连接 MySql、Oracle 等数据库一样,你可以用 JMS 来连接不同厂商的 MQ 产品。

2.1 JMS 的消息格式

  • TextMessage:一个字符串对象
  • MapMessage:一套名称 - 值对
  • ObjectMessage:一个序列化的 Java 对象
  • BytesMessage:一个字节的数据流
  • StreamMessage:Java 原始值的数据流

2.2 JMS 的消息传递类型

  1. P2P(Point - to - Point):
           点对点的,即一个生产者和一个消费者一一对应。一个生成者产生一个消息只能被一个消费者消费,消费完,消息就没有了。如下图:
    P2P

  2. P / S(Publish / Subscribe):
           发布 / 订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。发布即接收,没有消费者就自动结束,不会存在服务器里。如下图:
    P2S

3、安装配置

3.1 安装

  1. 下载地址:https://activemq.apache.org/components/classic/download/
  2. 按平台下载:
    download
  3. 下载完后解压;
  4. 进入 bin 目录,window 选择对应的 32 或 64 位文件夹后,直接双击“activemq.bat”即可完成启动,liunx 下执行“./activemq start”完成启动。然后打开浏览器输入地址:http://localhost:8161/ 进入 index 页,即表示成功,默认账号密码均为 admin
    index

3.2 修改管理界面密码

  1. 进入 conf 目录下;
  2. 打开 jetty-realm.properties 文件;
  3. 找到 admin: admin, admin,格式为 - 用户名 : 密码, [角色名, …]
  4. 想改成什么密码修改即可修改即可。

3.3 修改消息传送密码

  1. 进入 conf 目录下;
  2. 打开 credentials.properties 文件;
  3. activemq.username 为用户名,activemq.password 为密码,按照自己的意愿修改;
  4. 打开 activemq.xml 文件,在 上面添加如下配置:
<!-- 添加访问 ActiveMQ 的账号密码 -->
<plugins>
	<simpleAuthenticationPlugin>
		<users>
			<authenticationUser username="${activemq.username}" password="${activemq.password}" groups="users,admins"/>
		</users>
	</simpleAuthenticationPlugin>
</plugins>
  1. 还有一种 jssa 的方式,复杂一点,不过可以精确到消息的读写权限控制,感兴趣的话,可以搜一搜,这里就不介绍了。

4、代码示例

4.1 P2P

Producer:

import javax.jms.*;

public class QueueProducer {
    public static void main(String[] args) throws JMSException {
        // 1. 创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
        // 2. 获取连接
        Connection connection = connectionFactory.createConnection();
        // 3. 启动连接
        connection.start();
        /* 4. 获取 session:
         * Session.AUTO_ACKNOWLEDGE = 1,自动确认
         * CLIENT_ACKNOWLEDGE = 2,客户端手动确认
         * DUPS_OK_ACKNOWLEDGE = 3,自动批量确认
         * SESSION_TRANSACTED = 0,事务提交并确认
         */
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 5. 创建队列对象
        Queue queue = session.createQueue("test-queue");
        // 6. 创建消息生产者
        MessageProducer producer = session.createProducer(queue);
        // 7. 创建消息
        TextMessage textMessage = session.createTextMessage("Hello, world!");
        // 8. 发送消息
        producer.send(textMessage);
        // 9. 关闭资源
        producer.close();
        session.close();
        connection.close();
    }
}

Consumer:

import javax.jms.*;
import java.io.IOException;

public class QueueConsumer {
    public static void main(String[] args) throws JMSException, IOException {
        // 1. 创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
        // 2. 获取连接
        Connection connection = connectionFactory.createConnection();
        // 3. 启动连接
        connection.start();
        // 4. 获取 session
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 5. 创建队列对象
        Queue queue = session.createQueue("test-queue");
        // 6. 创建消息消费者
        MessageConsumer consumer = session.createConsumer(queue);
        // 7. 监听消息
        consumer.setMessageListener(message -> {
            TextMessage textMessage = (TextMessage) message;
            try {
                System.out.println("接收到消息:" + textMessage.getText());
            } catch (JMSException e) {
                System.out.println("接收消息异常:" + e.getMessage());
            }
        });
        // 8. 等待键盘输入,防止程序退出
        System.in.read();
        // 9. 关闭资源
        consumer.close();
        session.close();
        connection.close();
    }
}

运行示例:

  1. 先运行 Producer,然后在 ActiveMQ 界面会出先一个 Queue:
    Queue
  2. 再运行 Consumer,控制台会输出: 接收到消息:Hello, world!,且不会退出;
  3. 多次运行 Producer,观察 Consumer 会一直输出。

4.2 P/S

同时创建 2 个消费者,分别修改生产者和消费者创建队列对象创建主题对象

// 5. 创建主题对象
Topic topic = session.createTopic("test-topic");

运行示例:

  1. 要先运行 2 个 Consumer;
  2. 再运行 Producer;
  3. 观察两个 Consumer 控制台会分别输出:Topic1:接收到消息:Hello, world!, Topic2:接收到消息:Hello, world!,且不会退出;
  4. 多次运行 Producer,观察 Consumer 会一直输出;
  5. ActiveMQ 管理界面如下:
    Topic

5、整合到 SpringBoot

  1. 添加 pom 依赖:
<!-- activemq -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
  1. 添加配置信息:
# activemq 基础配置
spring.activemq.broker-url=tcp://127.0.0.1:61616
# 生产环境设置密码
spring.activemq.user=[根据实际情况填写]
spring.activemq.password=[根据实际情况填写]
spring.activemq.pool.enabled=false
  1. 编写生产者工具类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

import javax.jms.Destination;

@Component
public class ActivemqUtil {

    private final JmsMessagingTemplate jmsTemplate;

    @Autowired
    public ActivemqUtil(JmsMessagingTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    /**
     * 发送消息
     *
     * @param destination Queue or Topic
     * @param message     消息内容
     */
    public void sendMessage(Destination destination, final String message) {
        jmsTemplate.convertAndSend(destination, message);
    }

}
  1. 添加消费者类:
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;

@Service
public class Consumer {

    @JmsListener(destination = "test-queue")
    public void receiveQueue(String message) {
        System.out.println("receiveQueue: " + message);
    }

}
  1. 修改启动类:
import com.sohu.usstock.common.utils.ActivemqUtil;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.Resource;
import javax.jms.Destination;

@SpringBootApplication
public class UsstockApplication implements CommandLineRunner {

    @Resource
    private ActivemqUtil activemqUtil;

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

    @Override
    public void run(String... args) {
        Destination queue = new ActiveMQQueue("test-queue");
        // Destination topic = new ActiveMQTopic("test-topic");
        activemqUtil.sendMessage(queue, "Hello, world!");
    }
    
}
  1. 运行后查看结果,即可。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值