Java ActiveMQ 讲解(一)理解JMS 和 ActiveMQ基本使用(转)
转自:http://www.cnblogs.com/luochengqiuse/p/4678020.html?utm_source=tuicool&utm_medium=referral
最近的项目中用到了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的安装
- 从官网下载安装包,http://activemq.apache.org/download.html
- 赋予运行权限 chmod +x,windows可以忽略此步
- 运行 ./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处理消息的流程决定的:
- 消息从生成方客户端传送到消息服务器。
- 消息服务器读取消息。
- 消息被放置到持久性存储器当中(出于可靠性的考虑)。
- 消息服务器确认收到消息(出于可靠性的考虑)。
- 消息服务器确定消息的路由。
- 消息服务器写出消息。
- 消息从消息服务器传送到使用方客户端。
- 使用方客户端确认收到消息(出于可靠性的考虑)。
- 消息服务器处理客户端确认(出于可靠性的考虑)。
- 消息服务器确定已经处理客户端确认。
这些步骤是连续的,所以任何步骤都可能成为消息从生成方客户端到使用方客户端的传送过程的瓶颈。这些步骤中的大多数都取决于消息传送系统的物理特征:网络带宽、计算机处理速度和消息服务器体系结构等等。但是,有一些步骤还取决于消息传送应用程序的特征和该应用程序要求的可靠性级别。
其实就是基于可靠性还是性能的选择.
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 出了队列的消息 可以理解为是消费这消费掉的数量
Java ActiveMQ 讲解(一)理解JMS 和 ActiveMQ基本使用(转)的更多相关文章
- Java ActiveMQ 讲解(一)理解JMS 和 ActiveMQ基本使用
最近的项目中用到了mq,之前自己一直在码农一样的照葫芦画瓢.最近几天研究了下,把自己所有看下来的文档和了解总结一下. 一. 认识JMS 1.概述 对于JMS,百度百科,是这样介绍的:JMS即Java消 ...
- Java ActiveMQ 讲解(二)Spring ActiveMQ整合+注解消息监听
对于ActiveMQ消息的发送,原声的api操作繁琐,而且如果不进行二次封装,打开关闭会话以及各种创建操作也是够够的了.那么,Spring提供了一个很方便的去收发消息的框架,spring jms.整合 ...
- 理解面向消息中间件及JMS 以及 ActiveMQ例子
为了帮助你理解ActiveMQ的意义,了解企业消息传送背景和历史是很重要的.讨论完企业消息传送,你将可以通过一个小例子了解JMS及其使用.这章的目的是简要回顾企业消息传送及JMS规范.如果你已经熟悉这 ...
- JMS(Java消息服务)与消息队列ActiveMQ基本使用(一)
最近的项目中用到了mq,之前自己一直在码农一样的照葫芦画瓢.最近几天研究了下,把自己所有看下来的文档和了解总结一下. 一. 认识JMS 1.概述 对于JMS,百度百科,是这样介绍的:JMS即Java消 ...
- Simple guide to Java Message Service (JMS) using ActiveMQ
JMS let’s you send messages containing for example a String, array of bytes or a serializable Java o ...
- JMS and ActiveMQ first lesson(转)
JMS and ActiveMQ first lesson -- jms基础概念和应用场景 2011-6-18 PM 9:30 主讲:kimmking <kimmking@163.com> ...
- JMS服务器ActiveMQ的初体验并持久化消息到MySQL数据库中
JMS服务器ActiveMQ的初体验并持久化消息到MySQL数据库中 一.JMS的理解JMS(Java Message Service)是jcp组织02-03年定义了jsr914规范(http://j ...
- 深入浅出JMS(三)--ActiveMQ简单的HelloWorld实例
第一篇博文深入浅出JMS(一)–JMS基本概念,我们介绍了JMS的两种消息模型:点对点和发布订阅模型,以及消息被消费的两个方式:同步和异步,JMS编程模型的对象,最后说了JMS的优点. 第二篇博文深入 ...
- 【JMS】JMS之ActiveMQ的使用
这篇文章主要是简单介绍一下JMS和ActiveMQ,以及使用ActiveMQ来写两个demo. 1. JMS是啥 百度百科的解释: JMS即Java消息服务(Java Message Service) ...
随机推荐
- Java学习-017-EXCEL 文件读取实例源代码
众所周知,EXCEL 也是软件测试开发过程中,常用的数据文件导入导出时的类型文件之一,此文主要讲述如何通过 EXCEL 文件中 Sheet 的索引(index)或者 Sheet 名称获取文件中对应 S ...
- PHP加密解密字符串
项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理. 最常见的应用在用户登录以及一些AP ...
- 右键TXT文件-打开方式-选择默认程序提示 windows无法访问指定设备,路经或文件.您可能没有合适的权限访问这个项目
新建立一个.txt文本,把下面复制到.txt文本点保存,再把.txt文件格式修改为.reg格式, 双击导入注册表就OK了 Windows Registry Editor Version 5.00 [H ...
- C#读写BitMap及颜色相乘
C#读写BitMap及颜色相乘 private Bitmap ReadBitMapAndMultipy(Bitmap bitmap0) { int x1width = bitmap0.Width; i ...
- 【未解决】CImage::Save / Load 导致“线程 0xc224 已退出,返回值为 1 (0x1)”
不知道这个返回值意味着什么,反正只要用到Save/Load就会出现这个情况. 这个链接:http://forums.codeguru.com/showthread.php?354017-The-thr ...
- App上架审核指南翻译
App Store Review Guidelines APP审核指南:https://developer.apple.com/app-store/review/guidelines/ 本文是自主翻译 ...
- 磁盘io负载查看
转自:http://blog.csdn.net/i_am_jojo/article/details/7698458 为了方便各位和自己今后遇到此类问题能尽快解决,我这里将查看linux服务器硬盘IO访 ...
- mysql:on duplicate key update与replace into
在往表里面插入数据的时候,经常需要:a.先判断数据是否存在于库里面:b.不存在则插入:c.存在则更新 一.replace into 前提:数据库里面必须有主键或唯一索引,不然replace into ...
- Redis:安装
此篇文章并不介绍linux下安装方法.围绕windows安装而介绍 两种安装方式: 1)下载压缩包,解压后(运行起来有个窗口,关闭掉就不在运行),没有windows服务被注册:可以只用命令在cmd将其 ...
- struts 2.0部署
环境:linux centos 64位. 1)下载JDK6.0,具体文件名是:jdk-6u45-linux-x64.bin 安装:chmod 755 jdk*.bin ./jdk....bin 设置环 ...