JSR-343学习笔记(JMS)

来源:互联网 发布:淘宝店铺首页大图 编辑:程序博客网 时间:2024/06/05 16:52
  1. JMS两种模式, p2p, pub/sub

  2. Cosuming message from Topic

    1. Nondurable, unshared Subscription[JMSContext.createConsumer()]

    2. Durable Subscriptions

    3. Shared Subscriptions,可以实现负载均衡的目的

  3. Controlling Message Acknowledgment

    1. 成功消费了一条message体现在3点<1>client接收到消息<2>client处理了消息<3>消息被acknowledged

    2. 对于locally transacted session,当session提交时消息会被acknowledged,如果调用context.rollback(),消息会被重发(redeliver)

    3. 对于JTA transaction(JaveEE web 或者EJB),当事务提交时,消息会被acknowledged

    4. 对于 non-transacted session, 消息如何被acknowledged取决于调用createContext时传入的参数

      1. JMSContext.AUTO_ACKNOWLEDGE,在client调用receive方法返回(对于a中的3点,这个是个例外)或者MessageListener返回成功是,消息会被自动acknowledged

      2. JMSContext.CLIENT_ACKNOWLEDGE,手动调用Message的acknowledge方法,会对所有已消费的messages进行acknowledge,只能用在application client,不能用在web组件和EJB中

      3. JMSContext.DUPS_OK_ACKNOWLEDGE,出否可以接收重复的消息

  4. 对于未能及时进行acknowledge的处理情况

    1. 如果是从queue读

      1. provider会保留消息,等下次消费者访问queue会重发(redeliver)

    2. 如果是从topic读

      1. 如果是从建立的持续(durable)订阅关掉了JMSContext, Provider会保留消息

      2. 如果是从建立的非持续(non-durable)订阅关掉了JMSContext,Provider会丢弃掉这些消息

    3. 对于non-transacted session

      1. 如果是durable订阅,使用JMSContext.recover会重新接收自上次acknowledge之后的消息,但是顺序有可能不同

      2. 如果是non-durable订阅,调用recover()方法会丢弃所有unacknowledge的消息

  5. 发送消息时的一些选项

    1. 设定消息的持久性(默认是PERSISTENT,也可以是NON_PERSISTENT),non的话对于provider就不进行消息持久化存储了,该特性可以通过Provider的setDeliveryMode方法进行设定

    2. 设定消息的优先级,从0(最低级)到9(最高级),默认是4,Provider会尽量有优先发送高优先级的消息,通过setPriority()进行设定

    3. 设定消息过期,如股票实时报价,在一定时间后就没有意义了,类似场景可以设定消息有效期间,通过Producer的setTimeToLive方法可以设定,单位毫秒,默认为0(永久有效)

    4. 设定延时发送,可以通过Producer的setDeliveryDelay方法进行设定,单位毫秒

  6. 临时发送地(Temporary Destinations)【天啊,看英文文档实在是不知道怎么翻译成中文,还是个复数】

    1. 可以通过JMSContext创建临时的发送目的地

  7. 使用JMS本地事务

    1. 在application client 或者 Java SE client,可以在创建上下文的时候以SESSION_TRANSACTED参数创建local transaction(connectionFactory.createContext(JMSContext.SESSION_TRANSACTED)),之后通过context.submit()和context.rollback()进行事务操作

    2. 在Java EE和EJB中,不能使用本地事务,需要使用JTA事务

  8. 异步发送消息

    1. 目前异步发送消息只能用在application client和 J2SE client,通过在Producer上设定异步回调来实现(setAsync)

  9. 在JaveEE中使用JMS

    1. JaveEE中,每个connection只能创建1个JMSContext

    2. 可以通过annotation和DD(deployment descriptor)的方式创建资源(Destination和ConnectionFactory)

    3. 在javaEE web component, session bean, message driven bean中注入connectionFactory和Topic/Queue时,不能声明为static的,注入factory之后要取得jmsContext需要再进行创建

    4. 1
      2
      3
      4
      @Resource(lookup = "java:comp/DefaultJMSConnectionFactory"
      private ConnectionFactory connectionFactory;
      @Resource(lookup = "jms/MyTopic"
      private Topic topic;

      提供了直接注入JMSContext的方式,可以直接使用@Inject方式,使用默认factory可以用第一种,使用自定义Factory可以使用第二种方式

    5. 1
      2
      3
      4
      5
      6
      @Inject
      private JMSContext context1;
       
      @Inject
      @JMSConnectionFactory("jms/MyConnectionFactory"
      private JMSContext context2;
  10. 在JaveEE web中和EJB中对JMSContext的管理,及时关掉不用的jmsContext是非常重要的

    1. 如果只在某个业务方法里面使用,可以使用JDK的try-with-resources方式去创建JMSContext

    2. 如果在事务或者请求中,可以使用直接注入JMSContext 的方式(@Inject JMSContext context;)

    3. EJB中可以在回调函数@PostConstruct 和 @PreDestory维护context但是一般来说没有必要,如果是有状态Bean(Stateful Bean)可以在@PrePassivate和@PostActivate中处理

  11. 在JaveEE中,事务的控制

    1. 一般使用默认的容器控制的事务(JTA)即可

    2. 也可以使用bean管理的事务 java.transaction.UserTransaction进行控制

  12. 使用消息驱动Bean进行异步消息接收

    1. 必须以@MessageDriven注解,或是使用DD(deployment descriptor)

    2. 必须是public类,并且不能是抽象或者final

    3. 必须包含无参公有构造函数

    4. 可选实现MessageListener接口(否则没有意义啊)

  13. 消息驱动Bean和application client的区别如下

    1. 后者需要依次创建JMSContext, JMSConsumer, setMessageListener,对于前者是自动的

    2. 使用@MessageDriven注解的Bean会包含一个activationConfig注解

    3. 前者可以有多个实例,后者对于一个MessageListener只能是一个线程

    4. 对于前者,acknowledge过程是自动处理的,除非使用Bean管理的事务(UserTransaction)

  14. 如果JMS和应用服务器(jboss, glassfish等)通过resource adapter进行了整合,可以通过它去handle事务的管理 @Resource private MessageDrivenContext mdc;

  15. 管理JTA事务,JTA事务可以是分布式的,EJB和web容器中的JTA事务分2种

    1. 容器管理的事务(EJB会默认使用Required级别的事务)

    2. Bean管理的事务,使用UserTransaction进行手动提交或回滚

    3. 对应专家可以使用手动控制事务的模式,这样可以实现提交一部分事务,然后再开多个事务,还可以让一部分JMS消息在事务外先处理并且acknowledge然后让一部分消息处于事务中处理

    4. 在JTA事务中创建的JMSContext任何参数都将被忽略,因为容器会管理所有的属性

    5. 在non-JTA事务中创建的JMSContext只能是AUTO_ACKNOWLEDGE或者DUPS_OK_ACKNOWLEDGE

    6. 如果是用Bean管理的事务,不能在其中进行acknowledge,只能通过属性设置activation configuration的属性:acknowledgeMode来实现,可以设置成AUTO_ACKNOWLEDGE或者DUPS_OK_ACKNOWLEDGE

    7. 如果在onMessage中抛出了RuntimeException,那么容器不会进行acknowledge,会在未来对消息进行重新发送(redeliver)

  16. 该JSR的DD(deployment descriptor)为:glassfish-resources.xml

    1. 对应DTD: http://glassfish.org/dtds/glassfish-resources_1_5.dtd

  17. END

0 0