首页 > 其他分享 >JMS规范及相关实现

JMS规范及相关实现

时间:2023-11-08 16:07:29浏览次数:26  
标签:publisher JMS 规范 PERSISTENT session 消息 相关 message


JMS是一种应用于异步消息传递的标准API,作为Java平台的一部分,JMS可以允许不同应用、不同模块之间实现可靠、异步数据通信。


在JMS中,支持两种消息模型,点对点(Point-to-point)和发布-订阅(Publish and subscribe),这两种模式分别对应于JMS中的两种消息目标(Message Destination):队列及主题。

在点对点模型中,每个消息都有一个发送者和一个接收者,消息中介(broker)收到发送者的消息,会将消息放入队列中,而接收者请求并接收队列中的一条消息后,这条消息就会从队列中删除。消息队列中的每条消息只能投递给一个接收者,但并不意味着只能使用一个接收者从队列中取消息,根据业务需要,可以使用多个接收者同时从队列中请求消息,分担处理压力。但是需要注意的是,单个接收者收到的消息是按照发送顺序的,多个接收者因为多线程的关系,并不能保证收到的消息一定是原序的。

在发布-订阅模式中,消息会发送给一个主题,但是与点对点模式不同的是消息不再只被投递给一个接收者,而是所有此主题的订阅者都会收到该消息。


JMS消息类型

在JMS1.1规范中,定义了五种消息类型,分别为:
1.StreamMessage :消息体是 Java 流,写入和读出都是顺序的
2.MapMessage :消息体包含 key-value 对, key 为 String , value 为基本类型,可以通过迭代器访问
3.TextMessage :消息体是 String
4.ObjectMessage :消息体是可序列化的 Java 对象
5.BytesMessage :消息体是字节数组


可以通过 message.clearBody() 来清除消息体;但在消费端,消息体是只读的,针对消息的写操作都会抛出 MessageNotWritableException 异常



JMS消息头


所有消息的消息头都具体相同的字段,用于 JMS Client 以及 JMS Provider 对它们进行区别以及进行消息路由


1.JMSDestination


消息发送的目的地(队列或主题);创建消息时可以设置 JMSDestination ,但是在发送完成时其值会更新为发送方所指定的 JMSDestination ,也就是说发送前该字段会被忽略;当消息被消费时,该字段的值与在它被发送时被设置的值是相同的


以下所有示例均基于ActiveMQ


Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建2个目的地
Destination destination = session.createQueue("JMS.DEMO");
Destination destination2 = session.createQueue("JMS.DEMO2");

// 创建生产者
MessageProducer publisher = session.createProducer(destination);

// 设置传输模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 创建消息
TextMessage message = session.createTextMessage("Test Message");
// 设置消息的目的地为destination2
message.setJMSDestination(destination2);

// 发送消息
publisher.send(message);

System.out.println(message.getJMSDestination());


代码中,通过 message.setJMSDestination(destination2); 设置了 message 的 JMSDestination 消息头属性值,我们再看看其输出结果

queue://JMS.DEMO




通过这个例子可以看出,虽然在发送前设置了消息的目的地,但是发送后消息的目的地被重置了


2.JMSDeliveryMode


指明消息的传输模式,有两种:


DeliveryMode.PERSISTENT :保证消息仅传一次, JMS Provider 服务停止后消息不会丢失;


DeliveryMode.NON_PERSISTENT :消息最多传一次,消息会因 JMS Provider 停止后丢失;


同 JMSDestination 一样,在发送前设置的会被忽略



看下面的例子

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地
Destination destination = session.createQueue("JMS.DEMO");

// 创建生产者
MessageProducer publisher = session.createProducer(destination);

// 设置传输模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
// 发送PERSISTENT消息
publisher.send(session.createTextMessage("PERSISTENT MESSAGE"));

// 设置传输模式
publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 发送PERSISTENT消息
publisher.send(session.createTextMessage("NON_PERSISTENT MESSAGE"));


例子中分别发送了一条 PERSISTENT 的消息和一条 NON_PERSISTENT 的消息;当 Active MQ 重启后,启动消费端,收到的消息如下

PERSISTENT MESSAGE




该例子说明,在 JMS Provider 重启后, NON_PERSISTENT 消息丢失了,而 PERSISTENT 消息能正常被消费者消费


3.JMSMessageID


由 JMS Provider 指定的消息的唯一标识符;同上面的字段一样,在发送前设置的会被忽略,在发送完成时,由 JMS Provider 重置该字段

4.JMSReplyTo


发送端在发送消息时,可以指定该属性(为一个 JMSDestination ),表示期望收到客户端的响应;是否响应由消费端决定



如下面的例子:


发送端: 


Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地
Destination destination = session.createQueue("JMS.DEMO");
Destination destination2 = session.createQueue("JMS.DEMO3");

// 创建生产者
MessageProducer publisher = session.createProducer(destination);

// 设置传输模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 创建消息
TextMessage message = session.createTextMessage("Test Message");
message.setJMSReplyTo(destination2);
// 发送消息
publisher.send(message);



接收端(可以根据情况决定是否需要回复)

public void onMessage(Message message) {
    try {
        System.out.println("Receive message: " + message);
        if (message.getJMSReplyTo() != null) {
            session.createProducer(message.getJMSReplyTo()).send(session.createTextMessage("This is a reply to"
                                                                                           + message.getJMSReplyTo()));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}



5.JMSRedelivered



当消费者收到带有 JMSRedelivered 的消息头时,表明该消息在过去传输过但没有被确认


JMS Provider 必须对该字段进行设置,当为 true 时即告知消费者该消息是重传的,消费者需要自行处理重复的消息



6.JMSExpiration


消息的过期时间,其值为当前时间加上存活时间(毫秒);当存活时间设置为 0 时,该字段的值也被设置为 0 ,表示永不过期;


消费端在一般情况下都不会接收到过期的消息,但 JMS Provider 并不保证这一点;



下面的例子说明了如何设置消息的过期时间


Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地
Destination destination = session.createQueue("JMS.DEMO");

// 创建生产者
MessageProducer publisher = session.createProducer(destination);

// 设置传输模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 创建消息
TextMessage message = session.createTextMessage("Test Message");
// 发送消息
publisher.setTimeToLive(5000);
publisher.send(message);



7.JMSPriority


消息的优先级, 0 代表最低优先级, 9 代表最高优先级;一般 0~4 为普通优先级, 5~9 为加快优先级


JMS 规范里并没有要求 JMS Provider 严格按这个优先级来实现,但是尽可能实现加快优先级消息的传输在普通消息的前面


同 JMSDestination 一样,该字段在发送前被忽略,在发送完成时重置




消息属性



除了前面提到的消息头以外, JMS 消息还提供了对“属性值对”的支持,以对消息头进行扩展;消息属性主要用于消息选择器 (message selector 详见下文 ) 



1.属性名


属性名必须服务消息选择器的命名规则



2.属性值


可以是基本类型及其对象类型以及 Map 、 List 和 String



下面的例子中,消息带 HashMap 的属性


Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地
Destination destination = session.createQueue("JMS.DEMO");

// 创建生产者
MessageProducer publisher = session.createProducer(destination);

// 设置传输模式
publisher.setDeliveryMode(DeliveryMode.PERSISTENT);

// 创建消息
TextMessage message = session.createTextMessage("Test Message");
// 发送消息
message.setObjectProperty("myProp", new HashMap() {

    {
        this.put("key1", "value1");
        this.put("key2", "value2");
    }
});
publisher.send(message);



3.清除属性

JMS 不能清除单个属性,但可以通过 Message.clearProperties() 方法清除所有消息属性



JMS实现(Provider implementations)



要使用JMS,必须要有相应的实现来管理session以及队列,从Java EE1.4开始,所有的Java EE应用服务器必须包含一个JMS实现。


以下是一些JMS实现:


    Apache ActiveMQ


    Apache Qpid, using AMQP


    BEA Weblogic (part of the Fusion Middleware suite) and Oracle AQ from Oracle


    EMS from TIBCO


    FFMQ, GNU LGPL licensed


    JBoss Messaging and HornetQ from JBoss


    JORAM, from the OW2 Consortium


    Open Message Queue, from Sun Microsystems


    OpenJMS, from The OpenJMS Group


    RabbitMQ, using AMQP


    Solace JMS from Solace Systems


    SonicMQ from Progress Software


    StormMQ, using AMQP


    SwiftMQ


    Tervela


    Ultra Messaging from 29 West (acquired by Informatica)


    webMethods from Software AG


    WebSphere Application Server from IBM, which provides an inbuilt default messaging provider known as the Service Integration Bus (SIBus), or which can connect to WebSphere MQ as a JMS provider [5]


    WebSphere MQ (formerly MQSeries) from IBM



Ref from:


1.http://en.wikipedia.org/wiki/Java_Message_Service


2.Spring in Action


3.http://goldendoc.iteye.com/blog/1155647




标签:publisher,JMS,规范,PERSISTENT,session,消息,相关,message
From: https://blog.51cto.com/u_809530/8255864

相关文章

  • 相关性系数及其python实现 (转)
    转自: https://www.cnblogs.com/sddai/p/10332573.html参考文献:1.python皮尔森相关系数 https://www.cnblogs.com/lxnz/p/7098954.html2.统计学之三大相关性系数(pearson、spearman、kendall) http://blog.sina.com.cn/s/blog_69e75efd0102wmd2.html 1.personcorrelatio......
  • C#C++,opencv的dll中detach相关:关于调用dll后程序退出后进程仍然驻留系统列表的问题
    我在c#中调用C++的dll,内部使用了线程并detach使其独立于主线程UI运行。但后来发现程序关闭后,任务列表中的进场依然存在,即app并未实际正常退出。这个问题有很多人碰到和争论,但都没有给出明确的答案。这里提供一个理论解释和绝佳的调试排除方法:根本原因:程序退出之前,系统(或程序员......
  • SQL Server 2005 数据库对象命名规范 Database Naming Conventions(Guidelines)
    使用SQLServer2005命名数据库对象时可以参照微软的示例数据库AdventureWorks。其次可以参照以下内容:DatabaseNamingConventionsVersion1.1LastRevisedMay13,2004byJasonMaussThemaingoalofadoptinganamingconventionfordatabaseobjectsissothatyouand......
  • R语言Copula模型分析股票市场板块相关性结构|附代码数据
    原文链接:http://tecdat.cn/?p=25804 原文出处:拓端数据部落公众号  最近我们被客户要求撰写关于Copula的研究报告,包括一些图形和统计输出。这篇文章是关于copulas和重尾的。在全球金融危机之前,许多投资者是多元化的。看看下面这张熟悉的图:黑线是近似正态的。红线代表Cau......
  • ​​Android平台GB28181历史视音频文件回放规范解读及技术实现
     技术背景在实现GB28181历史视音频文件回放之前,我们已完成了历史视音频文件检索和下载,历史视音频回放,在GB28181平台非常重要,比如执法记录仪等前端设备,默认录像数据存储在前端设备侧,如果需要上传到平台统一保存,除了到工作站拷贝外,还可以通过GB28181的历史视音频文件下载到指挥中心......
  • 统计独立性和统计相关性
    在随机信号分析中,不相关、正交、统计独立等是非常重要的,这里进一步讨论各自的严格概念和相互关系。当两个随机过程保持统计独立时,它们必然是不相关的,但反过来则不一定成立,即不相关的两个随机过程不一定能保持统计独立,唯有在高斯随机过程中才是例外。这就是说,从统计角度看,保持统计独......
  • 代码规范(阿里)
    一、代码规范:接口中分方法和属性,不加修饰符号如:publc,正确为:voidf()long或Long,统一用Long类型处理常量按功能分类归类if/for/while/switch/do等保留字与括号之间都必须加空格注释的双斜线与注释内容之间有且仅有一个空格当字符数超过120个时,换行规则:第二行相对第一行缩进4个空格......
  • 云服务器相关操作
    当涉及到云服务器的操作时,以下是一些常见的任务和操作:创建云服务器实例:选择云服务提供商(如AWS、Azure、GoogleCloud等),登录到其控制台,按照相关文档和界面指引创建云服务器实例。您需要选择实例类型、操作系统、存储选项和网络配置等。远程连接到云服务器:一旦创建了云服务器......
  • 秒杀相关的问题
    1、高并发场景,要避免请求操作数据库。用定时任务将数据定时更新到Redis中,请求直接查询Redis。2、更新秒杀商品的库存时,可以通过where库存>0来做一个乐观锁的效果。MySQL的InnoDB引擎在更新行的时候会加行锁。updateseckill_productsetstock_count=stock_count-......
  • GBrowse配置相关资料
    GBrowse配置相关资料(形状、颜色、配置、gff3)http://gmod.org/wiki/Glyphs_and_Glyph_Optionshttp://gmod.org/wiki/GBrowse_Configuration/Glyphshttp://gmod.org/wiki/GBrowse_Configuration/Feature_frequency_histograms(2010)http://boyun.sh.cn/bio/?p=1817(2011 GBrowse之......