Chapter 8. 使用HornetQ内核

HornetQ内核是一个与JMS无关的消息系统,它有一套自己的API。我们称它为内核API.

你可以直接使用内核API。使用内核API可以完成JMS同样的功能,只是比起JMS API使用更加简单方便。另外,内核API 还提供了JMS不具有的额外的功能。

8.1. 内核消息系统的相关概念

内核消息系统中有许多概念是与JMS相似的,但有些方面是不同的。总的来说内核消息系统的接口相对简单。这是因为 在内核中没有队列(queue)、话题(topic)和订阅(subscription)的概念。下面我们就内核消息中的概念作逐一介绍。 但是每个API的详细说明还是要参见相应的javadoc。

8.1.1. 消息

  • 一个消息就是客户端与服务器传递信息的单位数据。

  • 一个消息有一个消息体(body),即一个缓存用以写入数据或从中读取数据。

  • 一个消息有一个属性集,这个属性集实际上包含的是主键-值的集合。每个属性的主键是一个字符串,值可 以是一个整数(integer)、长整数(long)、短整数(short)、字节(byte)、字节数组(byte[])、 字符串(String),双精度值(double)、浮点数(float)或是布尔值(boolean)。

  • 每个消息都有一个地址(address)做为它的目的地。当一个消息被发到 服务器上时,它会被路由到与该地址绑定的所有队列中(queue)。如果queue配置了过滤器(filter), 那么只有与过滤器相匹配的消息才会被路由到该queue。一个地址可以绑定多个queue,也可以一个也不 绑定。注意这里所说的queue是内核的概念,不是JMS的queue。除了queue之外,还有其它一些实体可以 绑定到某一地址上。比如divert(转发器)

  • 消息可以是持久的(durable)或非持久的(non-durable)。持久的消息不会因为服务器故障或重启而丢失。 非持久消息则会因为服务器的故障或重启而丢失。

  • 消息具有优先级。优先级的值为从0到9的整数。0代表最低优先级,9代表最高优先级。HornetQ总 会尝试先传送优先级高的消息。

  • 消息还有一个可选的失效时间。如果一个消息过了失效时间,HornetQ将不再传送它。

  • 消息还有一个可选的时间戳(timestamp)。这个时间戳表示的是消息被发送的时间。

  • HornetQ还支持大消息的发送。它可以处理大到内存装不下的超大消息。

8.1.2. 地址(Address)

HornetQ服务器保存有地址和queue的映射集。一个地址对应零个或多个queue。每个queue还可以拥有消息 过滤器(filter)。当一个消息在服务器内进行路由时,它将会被送往与其地址相绑定的所有的queue中。但是 如果其中某个queue有过滤器,那么只有与其过滤器相匹配的消息才会被发到这个queue中。

其它的实体如diverts也可以与一地址进行绑定,消息也会被同样 路由到相应的实体中。

Note

在内核中,没有Topic的概念。只有地址(address)queue

假如想在内核实现JMS topic的功能,只要将一地址绑定到多个queue即可。其中的每一个queue就相当 于一个订阅(subscription)。类似地,一个JMS queue则可以通过一个地址与一个queue的绑定来实现。

8.1.3. Queue

Queue可以的持久的。意思是如果queue中的消息是持久的,那么当发生服务器故障或重启时,这些消息不会丢失。 Queue也可是非持久的,这意谓着如果服务器发的故障或重启,queue中的消息将会丢失,不管消息是不是持久的。

Queue也可以是临时的,意思是临时的queue在客户端断开连接时,它将会被删除。

Queue可以有一个过滤器表达式。服务器在向这样的queue路由消息时,先判定消息是否与过滤器表达式相匹配, 只有匹配的消息才会被发到该queue。

一个地址可以绑定多个queue、。但是一个queue只能被绑定到一个地址上。

8.1.4. ClientSessionFactory

客户端使用 ClientSessionFactory 类的实例创建 ClientSession 实例。 ClientSessionFactory 知道如何连接到服务器并创建会话(session)。它是可以根据不同需要灵活配置的。

ClientSessionFactory实例是通过 HornetQClient 工厂类创建的。

8.1.5. ClientSession

客户端使用ClientSession来发送和接收消息,并控制事务的使用。ClientSession可以支持事务性 和非事务性的应用。它还提供了一个 XAResource 接口,因些它可以加入到一个JTA 交易中。

ClientSession 管理着ClientConsumers和ClientProducers。

ClientSession 实例可以注册一个可选的 SendAcknowledgementHandler。每当消息被送达HornetQ服务器中时, HornetQ就用它来异步地发出通知。有了这个独特的功能,客户可以不必阻塞在每次消息的发送操作上来保证 消息安全到达服务器。如果采用阻塞的方法,那么每一个消息的发送都要包括往返两次的网络传递操作,开销 是很大的。有了这个异步方式就可以避免这种开销,建立真正的异步的端到端间的系统。这是标准的JMS接口 无法做到的。参见 Chapter 20, 发送与提交的保证了解相关的更详细的信息。

8.1.6. ClientConsumer

客户端使用 ClientConsumer 实例来接收来自queue的消息。HornetQ的内核同时支持 同步与异步的消息接收。ClientConsumer 实例可以配置有可选的过滤器。它只接收与过滤 器相匹配的消息。

8.1.7. ClientProducer

客户端使用ClientSession创建 ClientProducer 实例 来向服务器发送消息。ClientProducer可以指定一个地址,用来向其发送消息。或者不指定地址,消息在发送时 再指定地址。

Warning

请注意 ClientSession、 ClientProducer和ClientConsumer 实例是可以被 重用的。

在每次发送或接收一个消息时都创建新的 ClientSession, ClientProducer 和 ClientConsumer是不符合 设计模式的要求的。这样做会导致性能低下。在Chapter 46, 性能调优中我们会做进一步的讨论。

8.2. 一个内核的应用实例

下面是一个非常简单的使用内核API来发送的接收消息的实例:

ClientSessionFactory factory =  HornetQClient.createClientSessionFactory(
                                        new TransportConfiguration(
                                           InVMConnectorFactory.class.getName()));

ClientSession session = factory.createSession();

session.createQueue("example", "example", true);

ClientProducer producer = session.createProducer("example");

ClientMessage message = session.createMessage(true);

message.getBodyBuffer().writeString("Hello");

producer.send(message);

session.start();

ClientConsumer consumer = session.createConsumer("example");

ClientMessage msgReceived = consumer.receive();

System.out.println("message = " + msgReceived.getBodyBuffer().readString());

session.close();