最近的项目中用到了mq,之前自己一直在码农一样的照葫芦画瓢。最近几天研究了下,把自己所有看下来的文档和了解总结一下。

一. 认识JMS

1.概述

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

简短来说,JMS是一种与厂商无关的 API,用来访问消息收发系统消息。它类似于JDBC(Java Database Connectivity),提供了应用程序之间异步通信的功能。

JMS1.0是jsr 194里规定的规范(关于jsr规范,请点击)。目前最新的规范是JSR 343,JMS2.0。

好了,说了这么多,其实只是在说,JMS只是sun公司为了统一厂商的接口规范,而定义出的一组api接口。

2. JMS体系结构

描述如下:

  • JMS提供者(JMS的实现者,比如activemq jbossmq等)
  • JMS客户(使用提供者发送消息的程序或对象,例如在12306中,负责发送一条购票消息到处理队列中,用来解决购票高峰问题,那么,发送消息到队列的程序和从队列获取消息的程序都叫做客户)
  • JMS生产者,JMS消费者(生产者及负责创建并发送消息的客户,消费者是负责接收并处理消息的客户)
  • JMS消息(在JMS客户之间传递数据的对象)
  • JMS队列(一个容纳那些被发送的等待阅读的消息的区域)
  • JMS主题(一种支持发送消息给多个订阅者的机制)

3. JMS对象模型

  • 连接工厂(connectionfactory)客户端使用JNDI查找连接工厂,然后利用连接工厂创建一个JMS连接。
  • JMS连接 表示JMS客户端和服务器端之间的一个活动的连接,是由客户端通过调用连接工厂的方法建立的。
  • JMS会话 session 标识JMS客户端和服务端的会话状态。会话建立在JMS连接上,标识客户与服务器之间的一个会话进程。
  • JMS目的 Destinatio 又称为消息队列,是实际的消息源
  • 生产者和消费者
  • 消息类型,分为队列类型(优先先进先出)以及订阅类型

二. ActiveMQ

1. ActiveMQ的安装

  1. 从官网下载安装包,http://activemq.apache.org/download.html
  2. 赋予运行权限 chmod +x,windows可以忽略此步
  3. 运行 ./active start | stop

启动后,activeMQ会占用两个端口,一个是负责接收发送消息的tcp端口:61616,一个是基于web负责用户界面化管理的端口:8161。这两个端口可以在conf下面的xml中找到。http服务器使用了jettry。
这里有个问题是启动mq后,很长时间管理界面才可以显示出来。

2. 用Java访问ActiveMQ

先附上Bean代码:

public class MqBean implements Serializable{
private Integer age;
private String name;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

2.1 队列消息的发送:

public static void main(String[] args) {
ConnectionFactory connectionFactory;
Connection connection;
Session session;
Destination destination;
MessageProducer producer;
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
try {
connection = connectionFactory.createConnection();
connection.start();
//第一个参数是是否是事务型消息,设置为true,第二个参数无效
//第二个参数是
//Session.AUTO_ACKNOWLEDGE为自动确认,客户端发送和接收消息不需要做额外的工作。异常也会确认消息,应该是在执行之前确认的
//Session.CLIENT_ACKNOWLEDGE为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会删除消息。可以在失败的
//时候不确认消息,不确认的话不会移出队列,一直存在,下次启动继续接受。接收消息的连接不断开,其他的消费者也不会接受(正常情况下队列模式不存在其他消费者)
//DUPS_OK_ACKNOWLEDGE允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。在需要考虑资源使用时,这种模式非常有效。
//待测试
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
destination = session.createQueue("test-queue");
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//优先级不能影响先进先出。。。那这个用处究竟是什么呢呢呢呢
MqBean bean = new MqBean();
bean.setAge(13);
for(int i=0;i<100;i++){
bean.setName("小黄"+i);
producer.send(session.createObjectMessage(bean));
}
producer.close();
System.out.println("呵呵");
} catch (JMSException e) {
e.printStackTrace();
}
}

注:在上面的代码中,确认模式有三种,里面的DUPS_OK_ACKNOWLEDGE和AUTO_ACKNOWLEDGE一直没明白有什么区别。因为无法测试。不过大概也明白了一些。其实主要是MQ处理消息的流程决定的:

  1. 消息从生成方客户端传送到消息服务器。
  2. 消息服务器读取消息。
  3. 消息被放置到持久性存储器当中(出于可靠性的考虑)。
  4. 消息服务器确认收到消息(出于可靠性的考虑)。
  5. 消息服务器确定消息的路由。
  6. 消息服务器写出消息。
  7. 消息从消息服务器传送到使用方客户端。
  8. 使用方客户端确认收到消息(出于可靠性的考虑)。
  9. 消息服务器处理客户端确认(出于可靠性的考虑)。
  10. 消息服务器确定已经处理客户端确认。

这些步骤是连续的,所以任何步骤都可能成为消息从生成方客户端到使用方客户端的传送过程的瓶颈。这些步骤中的大多数都取决于消息传送系统的物理特征:网络带宽、计算机处理速度和消息服务器体系结构等等。但是,有一些步骤还取决于消息传送应用程序的特征和该应用程序要求的可靠性级别。
其实就是基于可靠性还是性能的选择.

2.2 队列消息的接收:

public static void main(String[] args) {
ConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection = null;
// Session: 一个发送或接收消息的线程
Session session;
// Destination :消息的目的地;消息发送给谁.
Destination destination;
// 消费者,消息接收者
MessageConsumer consumer;
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
try {
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
//这个最好还是有事务
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue("test-queue");
consumer = session.createConsumer(destination);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
try {
MqBean bean = (MqBean) ((ObjectMessage)message).getObject();
System.out.println(bean);
if (null != message) {
System.out.println("收到消息" + bean.getName());
}
} catch (Exception e) {
// TODO: handle exception
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}

注:对于队列来说,比较简单的优化策略,应该就是队列分载了。由于每个消费者都是单线程的,所以可以设置多个消费者来提高速度。
大家可以复制个消费者自己测试下,在消费者中添加sleep测试下效果。

2.3 订阅消息的发送

public static void main(String[] args) {
ConnectionFactory connectionFactory;
Connection connection;
Session session;
Destination destination;
MessageProducer producer;
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
try {
connection = connectionFactory.createConnection();
connection.start(); session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
destination = session.createTopic("test-topic");
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//优先级不能影响先进先出。。。那这个用处究竟是什么呢呢呢呢
MqBean bean = new MqBean();
bean.setAge(13);
for(int i=0;i<100;i++){
Thread.sleep(1000);
bean.setName("小黄"+i);
producer.send(session.createObjectMessage(bean));
}
producer.close();
System.out.println("呵呵");
} catch (Exception e) {
e.printStackTrace();
}
}

2.4 订阅消息的接收

public static void main(String[] args) {
ConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection = null;
// Session: 一个发送或接收消息的线程
Session session;
// Destination :消息的目的地;消息发送给谁.
Destination destination;
// 消费者,消息接收者
MessageConsumer consumer;
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.3.159:61616");
try {
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
//这个最好还是有事务
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue("test-queue");
consumer = session.createConsumer(destination);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
try {
MqBean bean = (MqBean) ((ObjectMessage)message).getObject();
System.out.println(bean);
if (null != message) {
System.out.println("收到消息" + bean.getName());
}
} catch (Exception e) {
// TODO: handle exception
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}

以上的消息发送后,如果没有接收到,可以登录自己的MQ管理页面:http://192.168.3.159:8161/admin/ ,默认帐号密码都是admin,查看队列中的消息

Number Of Pending Messages 等待消费的消息 这个是当前未出队列的数量。可以理解为总接收数-总出队列数
Messages Enqueued 进入队列的消息 进入队列的总数量,包括出队列的。 这个数量只增不减
Messages Dequeued 出了队列的消息 可以理解为是消费这消费掉的数量

JMS(Java消息服务)与消息队列ActiveMQ基本使用(一)的更多相关文章

  1. SpringBoot系列八:SpringBoot整合消息服务(SpringBoot 整合 ActiveMQ、SpringBoot 整合 RabbitMQ、SpringBoot 整合 Kafka)

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 整合消息服务 2.具体内容 对于异步消息组件在实际的应用之中会有两类: · JMS:代表作就是 ...

  2. JEESZ-kafka消息服务平台实现

    JEESZ的消息服务平台已经抛弃了之前的ActiveMQ,改用高吞吐量比较大的Kafka分布式消息中间件方案:JEESZ-kafka消息平台使用spring+kafka的集成方案,详情如下:1. 使用 ...

  3. MQ消息队列(2)—— Java消息服务接口(JMS)

    一.理解JMS   1.什么是JMS?         JMS即Java消息服务(Java Message Service)应用程序接口,API是一个消息服务的标准或者说是规范,允许应用程序组件基于J ...

  4. Java消息队列ActiveMQ (一)--JMS基本概念

    摘要:The Java Message Service (JMS) API is a messaging standard that allows application components bas ...

  5. ActiveMQ学习总结(5)——Java消息服务JMS详解

    JMS: Java消息服务(Java Message Service) JMS是用于访问企业消息系统的开发商中立的API.企业消息系统可以协助应用软件通过网络进行消息交互. JMS的编程过程很简单,概 ...

  6. Java消息队列--ActiveMq 实战

    1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...

  7. JMS(Java消息服务)入门教程

    什么是Java消息服务 Java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建.发送.读取消息等,用于支持JAVA应用程序开发.在J2EE中 ...

  8. JMS(java消息服务)整合Spring项目案例

    转载自云栖社区 摘要: Sprng-jms消息服务小项目 所需的包: spring的基础包 spring-jms-xx包 spring-message–xx包 commons-collection-x ...

  9. Java消息队列--ActiveMq 初体验

    1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...

随机推荐

  1. open file /var/mobile/Media/DCIM 相册中获取到的视频地址使用 报错 视频文件不存在

    从相册中获取到的视频地址 例如  file:///var/mobile/Media/DCIM/100APPLE/IMG_9876.MOV 后面再使用的时候报错 视频文件不存在  那是因为在ios10. ...

  2. Python之MySQL基础

    一.存储引擎 1.1  什么是存储引擎 MySQL中的数据通过不同的技术存储再文件或者内存中,每种技术有不同的存储机制,索引技巧,锁定水平,并且提供不同的能力,而实现这些技术的我们就称之为存储引擎 1 ...

  3. Apache 80端口被占用

    前段时间停止了Apache,结果在打开的时候发现无法打开,80端口被占用,于是win+r 运行cmd 输入netstat -ano 可以看到80端口被PID4占用,于是打开任务管理器-进程-查看,选择 ...

  4. 下拉框、下拉控件之Select2。自动补全的使用

    参考链接: 参考一:https://blog.csdn.net/weixin_36146275/article/details/79336158 参考二:https://www.cnblogs.com ...

  5. 函数式编程 - 函数缓存Memoization

    函数式编程风格中有一个"纯函数"的概念,纯函数是一种无副作用的函数,除此之外纯函数还有一个显著的特点:对于同样的输入参数,总是返回同样的结果.在平时的开发过程中,我们也应该尽量把无 ...

  6. RabbitMQ一个简单可靠的方案(.Net Core实现)

    前言 最近需要使用到消息队列相关技术,于是重新接触RabbitMQ.其中遇到了不少可靠性方面的问题,归纳了一下,大概有以下几种: 1. 临时异常,如数据库网络闪断.http请求临时失效等: 2. 时序 ...

  7. .Net Core小技巧 - Swagger适配虚拟目录及二级目录

    前言 随着前后端分离模式与微服务架构的出现,Web API变得越来越重要及普遍.而后出现的网关技术,使开发者更倾向于使用二级/多级目录来暴露Web API,一是暴露的端口更少,方便管理:二是在网关中可 ...

  8. pojo,javabean与entitybean

    pojo:朴实无华的实体类 javabean:遵守某些规范的可重用的实体类 entitybean:与数据库中的数据记录对应的类 这个链接说的很明白!https://blog.csdn.net/chen ...

  9. 实现ssr服务端渲染

    前言 前段时间寻思做个个人网站,然后就立马行动了.  个人网站如何实现选择什么技术方案,自己可以自由决定.  刚好之前有大致想过服务端渲染,加载速度快,还有 SEO 挺适合个人网站的.  所以就自己造 ...

  10. 蓝桥杯刷题,第四界省赛B组

    题头,本内容的题目和部分内容均来自博客:https://blog.csdn.net/ryo_218/article/details/79704030 ,在此感谢. 1. 题目标题:高斯日记大数学家高斯 ...