JMS:Java消息服务(即Java Message Service),Java平台上有关面向MOM的技术规范。目的是通过提供标准的产生、发送、接收和处理消息的API简化企业应用的开发,类似JDBC和数据库通信方式的抽象。
ActiveMQ:ActiveME是基于JMS的开源的消息中间件。提供标准的、面向消息的、能够跨多种语言和系统的应用集成消息中间件。
消息:服务之间进行传送的数据单位。可以很简单,比如字符串;也可以是对象等。
JMS中的相关角色
Broker:消息服务器,作为server提供消息核心服务。
Provider/MessageProvider:消息生产者是由会话创建的一个对象,用于把消息发送到一个目的地。
Consumer/MessageConsumer:消息消费者是由会话创建的一个对象,它用于接收发送到目的地的消息。
同步消费:调用消费者的receive方法从目的地中显式提取消息。receive方法可以一直阻塞到消息到达。
异步消费:为消费者注册一个消息监听器,以定义在消息到达时所采取的动作。
PTP:Point To Point,点对点通信消息模型。
生产者将消息发送到queue中,消费者从queue中获取并消费消息。消息被消费之后,queue不能在有存储,所以消费者不会消费到已经被消费的消息。Queue支持多个消费者,但对于一个消息,只会有一个消费者。如果消费者不存在,消息将一致保存,直到被消费。
Pub/Sub:Publish/Subscribe,发布订阅消息模型
生产者将消息发布的topic,同时有多个消费者订阅来消费该消息。不同于PTP的方式,发不到topic的消息会被所有的订阅者消费。默认情况下,当生产者发布消息当时候,只有在线的订阅者会消费到消息,不在线的订阅者将不会消费到该消息。
Queue:队列,目标类型之一,和PTP结合
Topic:主题,目标类型之一,和Pub/Sub结合
Queue/Topic都是 Destination 的子接口.
ConnectionFactory:连接工厂是客户用来创建连接的对象,例如ActiveMQ提供的ActiveMQConnectionFactory。
Connnection:JMS Connection封装了客户与JMS提供者之间的一个虚拟的连接。
Destination:消息目的地,由Session创建。是客户用来指定它生产的消息的目标和它消费的消息的来源的对象。
Session:JMS Session是生产和消费消息的一个单线程上下文(在这个上下文中,一组发送和接收被组合到了一个原子操作中)。会话用于创建消息生产者(producer)、消息消费者(consumer)和消息(message)等。
消息中间件的场景
异步通信:消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
缓冲:消息队列通过一个缓冲层来帮助任务最高效率的执行,该缓冲有助于控制和优化数据流经过系统的速度。以调节系统响应时间。
解耦:降低服务间的强依赖程度,针对异构系统进行适配。通过消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,当应用发生变化时,可独立的扩展或者修改。
冗余:消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。
扩展性:消息队列解耦了处理过程,可以在不修改代码的情况下进行分布式扩容。
可恢复性:消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
过载保护:访问量剧增的情况下,消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
HelloActiveMQ
Producer
public class MyProducer {
public static void main(String[] args) {
Connection connection = null;
ActiveMQConnectionFactory connectionFactory = null;
try {
//1.获取连接工厂,这里默认不设定用户密码,为了安全可以在activemq.xml中配置指定的用户、密码才能访问ActiveMQ。
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD,
"tcp://localhost:61616"//tcp协议,ActiveMQ支持多种协议,开启了不通的端口
);
//2.获取一个ActiveMQ的连接
connection = connectionFactory.createConnection();
//3.获取session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//false,表示事务不开启
//4.找目的地,获取destination,消费端,也会从这个目的地取消息。要么是queue,要么是topic
Queue queue = session.createQueue("myQueue");
//5.消息创建者
MessageProducer producer = session.createProducer(queue);
//6.创建消息
for (int i = 0; i < 10; i++) {
TextMessage textMessage = session.createTextMessage("hi :" + i);
//7.向目的地写入消息
producer.send(textMessage);
}
} catch (JMSException e) {
e.printStackTrace();
} finally {
//8.关闭连接
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
Messages Enqueued:表示生产了多少条消息
Messages Dequeued:表示消费了多少条消息
Number Of Consumers:表示在该队列上还有多少消费者在等待接受消息
Number Of Pending Messages:表示还有多少条消息没有被消费,实际上是表示消息的积压程度
Consumer
public class MyConsumer {
public static void main(String[] args) {
Connection connection = null;
ActiveMQConnectionFactory connectionFactory = null;
try {
//1.获取连接工厂
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD,
"tcp://localhost:61616"
);
//2.获取一个ActiveMQ的连接
connection = connectionFactory.createConnection();
connection.start();
//3.获取session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.找目的地,消费端,从这个目的地取消息
Destination queue = session.createQueue("myQueue");
//5.消费者
MessageConsumer consumer = session.createConsumer(queue);
for (int i = 0; i < 10; i++) {
TextMessage textMessage = (TextMessage) consumer.receive();
System.out.println("Receive:" + textMessage.getText());
}
} catch (JMSException e) {
e.printStackTrace();
} finally {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
消息可靠性机制
消息是否被成功消费,需要有一种确认机制,就是消息确认机制。**ACK(Acknowledgement)**即确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。
ACK_MODE
JMS规定Client可以使用的ACK_MODE有四种:
- AUTO_ACKNOWLEDGE = 1:自动确认。当客户成功的从receive方法返回的时候,或者从MessageListener.onMessage方法成功返回的时候,会话自动确认客户收到的消息。
- CLIENT_ACKNOWLEDGE = 2:客户端手动确认。客户通过消息的acknowledge方法确认消息。(在这种模式中,确认是在会话层上进行:确认一个被消费的消息将自动确认所有已被会话消费的消息。)
- DUPS_OK_ACKNOWLEDGE = 3:自动批量确认.该选择只是会话迟钝的确认消息的提交。可能会导致一些重复的消息。
- SESSION_TRANSACTED = 0:事务提交并确认。所有的事务性会话,不管如何设置ack模式,都是按照以下原则:同一事务内部,在执行commit之前接收到的消息,都是没有ack的,放在pendingAck里面。在进行session.commit的时候会把pendingAck里面的消息全部一次确认,视为手动批量确认。事务会话要求效率高,因此都是批量进行ack的,没有别的方式。
ACK_TYPE
ACK_MODE确定了用何种方式进行消息确认。ACK_TYPE表示确认指令的类型。不同的ACK_TYPE将传递着消息的状态,broker可以根据不同的ACK_TYPE对消息进行不同的操作。JMS API中并没有定义ACT_TYPE,因为它通常是一种内部机制,并不会面向开发者。
DELIVERED_ACK_TYPE = 0 消息"已接收",但尚未处理结束
STANDARD_ACK_TYPE = 2 “标准"类型,通常表示为消息"处理成功”,broker端可以删除消息了
POSION_ACK_TYPE = 1 消息"错误",通常表示"抛弃"此消息,比如消息重发多次后,都无法正确处理时,消息将会被删除或者DLQ(死信队列)
REDELIVERED_ACK_TYPE = 3 消息需"重发",比如consumer处理消息时抛出了异常,broker稍后会重新发送此消息
INDIVIDUAL_ACK_TYPE = 4 表示只确认"单条消息",无论在任何ACK_MODE下
UNMATCHED_ACK_TYPE = 5 BROKER间转发消息时,接收端"拒绝"消息
消息优先级
消息优先级只是一个理论上的概念,并不能绝对保证优先级高的消息一定被消费者优先消费!也就是说ActiveMQ并不能保证消费的顺序性!
默认(JMSPriority == 4)
高(JMSPriority> 4 && <= 9)
低(JMSPriority> 0 && <4)