164 lines
11 KiB
XML
164 lines
11 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!-- ============================================================================= -->
|
||
<!-- Copyright © 2009 Red Hat, Inc. and others. -->
|
||
<!-- -->
|
||
<!-- The text of and illustrations in this document are licensed by Red Hat under -->
|
||
<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). -->
|
||
<!-- -->
|
||
<!-- An explanation of CC-BY-SA is available at -->
|
||
<!-- -->
|
||
<!-- http://creativecommons.org/licenses/by-sa/3.0/. -->
|
||
<!-- -->
|
||
<!-- In accordance with CC-BY-SA, if you distribute this document or an adaptation -->
|
||
<!-- of it, you must provide the URL for the original version. -->
|
||
<!-- -->
|
||
<!-- Red Hat, as the licensor of this document, waives the right to enforce, -->
|
||
<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent -->
|
||
<!-- permitted by applicable law. -->
|
||
<!-- ============================================================================= -->
|
||
<chapter id="using-core">
|
||
<title>使用HornetQ内核</title>
|
||
<para>HornetQ内核是一个与JMS无关的消息系统,它有一套自己的API。我们称它为<emphasis>内核API</emphasis>.</para>
|
||
<para>你可以直接使用内核API。使用内核API可以完成JMS同样的功能,只是比起JMS API使用更加简单方便。另外,内核API
|
||
还提供了JMS不具有的额外的功能。</para>
|
||
<section>
|
||
<title>内核消息系统的相关概念</title>
|
||
<para>内核消息系统中有许多概念是与JMS相似的,但有些方面是不同的。总的来说内核消息系统的接口相对简单。这是因为
|
||
在内核中没有队列(queue)、话题(topic)和订阅(subscription)的概念。下面我们就内核消息中的概念作逐一介绍。
|
||
但是每个API的详细说明还是要参见相应的javadoc。</para>
|
||
<section>
|
||
<title>消息</title>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>一个消息就是客户端与服务器传递信息的单位数据。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>一个消息有一个消息体(body),即一个缓存用以写入数据或从中读取数据。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>一个消息有一个属性集,这个属性集实际上包含的是主键-值的集合。每个属性的主键是一个字符串,值可
|
||
以是一个整数(integer)、长整数(long)、短整数(short)、字节(byte)、字节数组(byte[])、
|
||
字符串(String),双精度值(double)、浮点数(float)或是布尔值(boolean)。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>每个消息都有一个<emphasis>地址(address)</emphasis>做为它的目的地。当一个消息被发到
|
||
服务器上时,它会被路由到与该地址绑定的所有队列中(queue)。如果queue配置了过滤器(filter),
|
||
那么只有与过滤器相匹配的消息才会被路由到该queue。一个地址可以绑定多个queue,也可以一个也不
|
||
绑定。注意这里所说的queue是内核的概念,不是JMS的queue。除了queue之外,还有其它一些实体可以
|
||
绑定到某一地址上。比如<emphasis role="italic">divert(转发器)</emphasis>。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>消息可以是持久的(durable)或非持久的(non-durable)。持久的消息不会因为服务器故障或重启而丢失。
|
||
非持久消息则会因为服务器的故障或重启而丢失。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>消息具有优先级。优先级的值为从0到9的整数。0代表最低优先级,9代表最高优先级。HornetQ总
|
||
会尝试先传送优先级高的消息。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>消息还有一个可选的失效时间。如果一个消息过了失效时间,HornetQ将不再传送它。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>消息还有一个可选的时间戳(timestamp)。这个时间戳表示的是消息被发送的时间。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>HornetQ还支持大消息的发送。它可以处理大到内存装不下的超大消息。</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</section>
|
||
<section>
|
||
<title>地址(Address)</title>
|
||
<para>HornetQ服务器保存有地址和queue的映射集。一个地址对应零个或多个queue。每个queue还可以拥有消息
|
||
过滤器(filter)。当一个消息在服务器内进行路由时,它将会被送往与其地址相绑定的所有的queue中。但是
|
||
如果其中某个queue有过滤器,那么只有与其过滤器相匹配的消息才会被发到这个queue中。</para>
|
||
<para>其它的实体如<emphasis role="italic">diverts</emphasis>也可以与一地址进行绑定,消息也会被同样
|
||
路由到相应的实体中。</para>
|
||
<note>
|
||
<para>在内核中,没有Topic的概念。只有<emphasis>地址(address)</emphasis> 和
|
||
<emphasis>queue</emphasis>。</para>
|
||
<para>假如想在内核实现JMS topic的功能,只要将一地址绑定到多个queue即可。其中的每一个queue就相当
|
||
于一个订阅(subscription)。类似地,一个JMS queue则可以通过一个地址与一个queue的绑定来实现。</para>
|
||
</note>
|
||
</section>
|
||
<section>
|
||
<title>Queue</title>
|
||
<para>Queue可以的持久的。意思是如果queue中的消息是持久的,那么当发生服务器故障或重启时,这些消息不会丢失。
|
||
Queue也可是非持久的,这意谓着如果服务器发的故障或重启,queue中的消息将会丢失,不管消息是不是持久的。</para>
|
||
<para>Queue也可以是临时的,意思是临时的queue在客户端断开连接时,它将会被删除。</para>
|
||
<para>Queue可以有一个过滤器表达式。服务器在向这样的queue路由消息时,先判定消息是否与过滤器表达式相匹配,
|
||
只有匹配的消息才会被发到该queue。</para>
|
||
<para>一个地址可以绑定多个queue、。但是一个queue只能被绑定到一个地址上。</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientSessionFactory</title>
|
||
<para>客户端使用 <literal>ClientSessionFactory</literal> 类的实例创建 <literal
|
||
>ClientSession</literal> 实例。 <literal>ClientSessionFactory</literal>
|
||
知道如何连接到服务器并创建会话(session)。它是可以根据不同需要灵活配置的。</para>
|
||
<para><literal>ClientSessionFactory</literal>实例是通过 <literal
|
||
>HornetQClient</literal> 工厂类创建的。</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientSession</title>
|
||
<para>客户端使用ClientSession来发送和接收消息,并控制事务的使用。ClientSession可以支持事务性
|
||
和非事务性的应用。它还提供了一个 <literal
|
||
>XAResource</literal> 接口,因些它可以加入到一个<ulink url="http://java.sun.com/javaee/technologies/jta/index.jsp">JTA</ulink>
|
||
交易中。</para>
|
||
<para>ClientSession 管理着ClientConsumers和ClientProducers。</para>
|
||
<para>ClientSession 实例可以注册一个可选的 <literal
|
||
>SendAcknowledgementHandler</literal>。每当消息被送达HornetQ服务器中时,
|
||
HornetQ就用它来异步地发出通知。有了这个独特的功能,客户可以不必阻塞在每次消息的发送操作上来保证
|
||
消息安全到达服务器。如果采用阻塞的方法,那么每一个消息的发送都要包括往返两次的网络传递操作,开销
|
||
是很大的。有了这个异步方式就可以避免这种开销,建立真正的异步的端到端间的系统。这是标准的JMS接口
|
||
无法做到的。参见 <xref linkend="send-guarantees"/>了解相关的更详细的信息。</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientConsumer</title>
|
||
<para>客户端使用 <literal>ClientConsumer</literal> 实例来接收来自queue的消息。HornetQ的内核同时支持
|
||
同步与异步的消息接收。<literal>ClientConsumer</literal> 实例可以配置有可选的过滤器。它只接收与过滤
|
||
器相匹配的消息。</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientProducer</title>
|
||
<para>客户端使用<literal>ClientSession</literal>创建 <literal>ClientProducer</literal> 实例
|
||
来向服务器发送消息。ClientProducer可以指定一个地址,用来向其发送消息。或者不指定地址,消息在发送时
|
||
再指定地址。</para>
|
||
</section>
|
||
<warning>
|
||
<para>请注意 ClientSession、 ClientProducer和ClientConsumer 实例是可以被
|
||
<emphasis>重用</emphasis>的。</para>
|
||
<para>在每次发送或接收一个消息时都创建新的 ClientSession, ClientProducer 和 ClientConsumer是不符合
|
||
设计模式的要求的。这样做会导致性能低下。在<xref linkend="perf-tuning"/>中我们会做进一步的讨论。</para>
|
||
</warning>
|
||
</section>
|
||
<section>
|
||
<title>一个内核的应用实例</title>
|
||
<para>下面是一个非常简单的使用内核API来发送的接收消息的实例:</para>
|
||
<programlisting>
|
||
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();</programlisting>
|
||
</section>
|
||
</chapter>
|