103 lines
9.2 KiB
XML
103 lines
9.2 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="send-guarantees">
|
||
<title>发送与提交的保证</title>
|
||
<section>
|
||
<title>事务保证</title>
|
||
<para>在提交或回滚事务时,HornetQ将提交或回滚的请求发送到服务器,客户端阻塞等待服务器的响应。</para>
|
||
<para>当服务器端收到提交或回滚的请求时,它将事务信息记录到日志(journal)中。然后向客户端发回
|
||
响应。参数<literal>journal-sync-transactional</literal>控制着如何向客户端发回响应。
|
||
如果它的值是<literal>false</literal>,服务器向客户端发回响应时事务的处理結果不一定已经被
|
||
保存到磁盘中。可能会在之后的某个时间保存。如果期间服务器发生故障那么事务的处理信息可能丢失。
|
||
当它的值是<literal>true</literal>时,服务器将保证在向客户端发回响应时,事务的处理信息
|
||
已经被保存到了磁盘中。默认值是<literal>true</literal>。</para>
|
||
<para>显然将这个参数设为<literal>false</literal>可以提高性能,但是要以牺牲事务的持久性为代价。</para>
|
||
<para>这个参数在 <literal>hornetq-configuration.xml</literal>文件中。</para>
|
||
</section>
|
||
<section id="non-transactional-sends">
|
||
<title>非事务性消息发送的保证</title>
|
||
<para>使用非事务性会话发送消息时,经过适当配置HornetQ,客户端在发送后以阻塞的方式等待,直到确认发出
|
||
的消息已经到达服务器后再返回。可以对持久化或非持久化的消息分别配置,具体参数如下:</para>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><literal>BlockOnDurableSend</literal>。如果设为<literal>true</literal>则通过
|
||
非事务性会话发送持久消息时,每次发送都将阻塞直到消息到达服务器并返回通知为止。默认值是
|
||
<literal>true</literal>。
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para><literal>BlockOnNonDurableSend</literal>。如果设为<literal>true</literal>,
|
||
则通过非事务性会话发送非持久消息时,每次发送都将阻塞直到消息到达服务器并返回通知为止。默认值是
|
||
<literal>false</literal>。</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
<para>将发送设置为阻塞方式会降低程序的效率。因为每次发送都需要一次网络往返的过程,然后才可以进行下次发送。
|
||
这样发送消息的速度将受网络往返时间(RTT)的限制。这样你的网络带宽就可能没有被充分利用。为了提高效率,我们
|
||
建议采用事务来批量发送消息。因为在事务中,只有在提交或回滚时阻塞。另外你还可以利用HornetQ高级的
|
||
<emphasis>异步发送通知功能</emphasis>。这一功能在<xref linkend="asynchronous-send-acknowledgements"/>
|
||
进行了描述。</para>
|
||
<para>使用JMS时,如果JMS的连接工厂是在服务器端被注册到JNDI服务,你需要配置
|
||
<literal>hornetq-jms.xml</literal>文件中的<literal>block-on-durable-send</literal>
|
||
和<literal>block-on-non-durable-send</literal>。如果不使用JNDI,可以调用
|
||
<literal>HornetQConnectionFactory</literal>相应的设置方法进行配置。</para>
|
||
<para>如果你使用的是内核服务,你可以直接在<literal
|
||
>ClientSessionFactory</literal>上用相关的方法设置相应的参数。</para>
|
||
<para>当服务器从一个非事务性的会话收到一个消息时,如果这个消息是持久的并且此消息被路由到至少一个持久的队列中,
|
||
则该消息会被持久化到永久存贮介质中。如果日志(journal)的参数<literal
|
||
>journal-sync-non-transactional</literal>设为<literal>true</literal>,服务器在向客户
|
||
发送响应时,它能保证消息已经被持久化到磁盘中。默认值是<literal>true</literal>。</para>
|
||
</section>
|
||
<section id="send-guarantees.nontrans.acks">
|
||
<title>非事务性通知的保证</title>
|
||
<para>当客户端使用非事务性会话向服务器通知消息收到时,可以配置HornetQ使得客户端的通知阻塞直到服务器收到
|
||
了通知并返回为止。其相应的配置参数是<literal>BlockOnAcknowledge</literal>。如果该参数设为
|
||
<literal>true</literal>则所有的通过非事务会话的消息通知都是阻塞式的。如果你想要的消息传递策略是
|
||
<emphasis>最多一次</emphasis>的话,那么你需要将此参数设为。默认值是<literal>false</literal>。</para>
|
||
</section>
|
||
<section id="asynchronous-send-acknowledgements">
|
||
<title>异步发送通知</title>
|
||
<para>如果你使用的是非事务会话来发送消息,并且希望保证每个发送出去的消息都到达服务器的话,你可以将HornetQ配置
|
||
成阻塞的方式,如<xref linkend="non-transactional-sends"/>讨论的那样。这样做的一个缺点是性能的降低。
|
||
因为这样每发送一个消息就需要一次网络的往返通信。如果网络时延越长,消息发送的效率就越低。同时网络的带宽对消息
|
||
的发送没有影响。</para>
|
||
<para>我们来做一个简单的计算。假设有一个1Gib的网络,客户端与服务器间往返时间为0.25ms。</para>
|
||
<para>这样,在阻塞方式的情况下,客户端<emphasis>最大</emphasis>的消息发送速度为 1000/ 0.25 =
|
||
4000 消息每秒。</para>
|
||
<para>如果每个消息的大小< 1500字节,而且网络的最大传输单元(MTU)是1500字节。那么理论上1GiB的网络
|
||
最大的传输速率是 (1024 * 1024 * 1024 / 8) / 1500 = 89478 消息每秒!尽管这不是一个精确的工程计算但
|
||
你可以看出阻塞式的发送对性能的影响会有多大。</para>
|
||
<para>为了解决这个问题,HornetQ提供了一种新的功能,称为<emphasis>异步发送通知</emphasis>。
|
||
它允许消息以非阻塞的方式发送,同时从另一个连接流中异步地接收服务器的通知。这样就使得消息的发送与通知分开来,
|
||
避免了阻塞方式带来的缺点。在保证消息可行发送到服务器的同时提高了呑吐量。</para>
|
||
<para>参数用来定义消息发送通知的窗口大小。它属于连接工厂或客户会话工厂。参见<xref linkend="client-reconnection"/>
|
||
以获取更多的相关信息。</para>
|
||
<section>
|
||
<title>异步发送通知</title>
|
||
<para>如果使用核心API,你需要实现<literal
|
||
>org.hornetq.api.core.client.SendAcknowledgementHandler</literal>接口并将一个实例设置到
|
||
<literal>ClientSession</literal>中。</para>
|
||
<para>然后使用这个<literal>ClientSession</literal>发送消息。当消息到达服务器后,服务器向客户端异步地发送通知,
|
||
并在客户端调用你的SendAcknowledgementHandler实例的<literal
|
||
>sendAcknowledged(ClientMessage message)</literal>方法。其中传入的参数就是发送的消息的引用。</para>
|
||
<para>为了使异步发送通知正常工作你必须确保<literal>confirmation-window-size</literal>的值为一个正整数,例如 10MiB</para>
|
||
<para>相关的例子请参见 <xref linkend="asynchronous-send-acknowledgements-example"/>。</para>
|
||
</section>
|
||
</section>
|
||
</chapter>
|