199 lines
12 KiB
XML
199 lines
12 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="paging">
|
||
<title>分页转存</title>
|
||
<para>HornetQ可以在有限的内存下支持包含百万消息的超大规模的队列。</para>
|
||
<para>当有限的内存无法装得下如此多的消息时,HornetQ将它们<emphasis>分页转存</emphasis>到磁盘中,在内存
|
||
有空闲时再将消息分页装载到内存。通过这样的处理,不需要服务器有很大的内存就可以支持大容量的队列。</para>
|
||
<para>通过配置可以给一个地址设置一个最大消息值。当这个地址消息数在内存中超过了这个值时,HornetQ开始将多余的消息
|
||
转存到磁盘中。</para>
|
||
<para>默认情况下HornetQ不转存任何消息。这一功能必须显式地通过配置来激活。</para>
|
||
<section>
|
||
<title>分页文件</title>
|
||
<para>消息按照所属的地址分别保存在不同的文件中。每一个地址有一个单独的文件夹,每个文件夹内消息被保存在
|
||
数个文件中(分页文件)。每个文件保存固定数量的消息(由参数<literal>page-size-bytes</literal>
|
||
设定)。当从分页文件中读取消息时,一个文件的所有消息被读到内存并被路由。当所有消息处理后,该文件就
|
||
被删除。</para>
|
||
</section>
|
||
<section id="paging.main.config">
|
||
<title>配置</title>
|
||
<para>你可以配置分页转存文件夹的位置。</para>
|
||
<para>在主配置文件<literal>hornetq-configuration.xml</literal>)中
|
||
可以定义全局的分页转发参数。</para>
|
||
<programlisting><configuration xmlns="urn:hornetq"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd">
|
||
|
||
...
|
||
|
||
<paging-directory>/somewhere/paging-directory</paging-directory>
|
||
|
||
... </programlisting>
|
||
<para>
|
||
<table frame="topbot">
|
||
<title>分页转存的配置参数</title>
|
||
<tgroup cols="3">
|
||
<colspec colname="c1" colnum="1"/>
|
||
<colspec colname="c2" colnum="2"/>
|
||
<colspec colname="c3" colnum="3"/>
|
||
<thead>
|
||
<row>
|
||
<entry>参数名</entry>
|
||
<entry>说明</entry>
|
||
<entry>默认值</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>paging-directory</literal></entry>
|
||
<entry>分页转存文件的位置。HornetQ在这个位置下为每个地址建立一个文件夹。</entry>
|
||
<entry>data/paging</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
</section>
|
||
<section id="paging.mode">
|
||
<title>分页转存模式</title>
|
||
<para>一个地址只要消息的数量超过定义的值,它就转到分页转存的模式。</para>
|
||
<note>
|
||
<para>分页转存是针对每个地址设置的。如果你为一个地址配置了一个max-size-bytes,那么每个匹配的地址
|
||
都有一个最大值的限制。但是这并不表示所有匹配的地址的大小总和受这个参数的限制。</para>
|
||
</note>
|
||
<section>
|
||
<title>配置</title>
|
||
<para>有关分页转存的配置在主要配置文件(<literal>hornetq-configuration.xml</literal>)
|
||
的地址设置的部分内。</para>
|
||
<programlisting> <address-settings>
|
||
<address-setting match="jms.someaddress">
|
||
<max-size-bytes>104857600</max-size-bytes>
|
||
<page-size-bytes>10485760</page-size-bytes>
|
||
<address-full-policy>PAGE</address-full-policy>
|
||
</address-setting>
|
||
</address-settings>
|
||
</programlisting>
|
||
<para>下面列出了可用的参数:</para>
|
||
<para>
|
||
<table frame="topbot">
|
||
<title>分页转存参数设置</title>
|
||
<tgroup cols="3">
|
||
<colspec colname="c1" colnum="1"/>
|
||
<colspec colname="c2" colnum="2"/>
|
||
<colspec colname="c3" colnum="3"/>
|
||
<thead>
|
||
<row>
|
||
<entry>参数名称</entry>
|
||
<entry>说明</entry>
|
||
<entry>默认值</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>max-size-bytes</literal></entry>
|
||
<entry>地址的最大内存值。当消息占用内存超过此值时,进入分页转存模式。</entry>
|
||
<entry>-1 (关闭分页转存功能)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>page-size-bytes</literal></entry>
|
||
<entry>每个分页文件的大小。</entry>
|
||
<entry>10MiB (10 * 1024 * 1024 字节)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>address-full-policy</literal></entry>
|
||
<entry>要使用分页转存,这个参数必须设为PAGE。PAGE表示多余的消息会被保存到磁盘。
|
||
如果设为DROP,那么多余的消息将会被丢弃。如果设为BLOCK,当消息占满设定的最大
|
||
内存时,在客户端消息的发送者将被阻塞,不能向服务器发送更多的消息。</entry>
|
||
<entry>PAGE</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
</section>
|
||
</section>
|
||
<section>
|
||
<title>丢弃消息</title>
|
||
<para>一个地址除了可以分页转存多余的消息外,还可以配置为丢弃多余消息。</para>
|
||
<para>只要将<literal>address-full-policy</literal>设为<literal>DROP</literal>即可。</para>
|
||
</section>
|
||
<section>
|
||
<title>阻塞发送者(producer)</title>
|
||
<para>一个地址除了可以分页转存多余的消息外,还可以通过配置使得消息的发送者在消息达到最大值时阻塞消息
|
||
的发送,以防止服务器由于消息过多而耗尽内存。</para>
|
||
<para>随着服务器的内存被释放,发送者自动解除阻塞,继续发送消息。</para>
|
||
<para>这种方式需要将<literal>address-full-policy</literal>设为<literal>BLOCK</literal>。</para>
|
||
<para>在默认的配置中,所有的地址在消息的量达到10MiB后将阻塞发送者。</para>
|
||
</section>
|
||
<section>
|
||
<title>对于有多个队列绑定的地址的配置注意事项</title>
|
||
<para>当一个消息被路由到一个绑定了多个队列(queue)的地址时(比如JMS的订阅),在内存中仍然只有一分消息的拷贝。每个
|
||
队列所持有的不过是它的一个引用。因此,只有所有队列中的消息都成功地传递出去后,这个消息才会从内存中清除。也就是说
|
||
只要有一个队列没有传递这个消息,那么就会造成这个消息处于未被传递的状态。 </para>
|
||
<para>例如:</para>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>一个地址绑定了10个队列(queue)。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>其中一个队列没有传递它的消息(也许因为接收者很慢)。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>消息不断增加,触发了分页转存模式。</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>而其它9个队列尽管发送了消息,但由于地址将多余的消息转存到磁盘,所以它们都是空的。</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
<para>在这个例子中,必须要等到最后一个队列传递了一些消息后,那些转存的消息被装载回内存,其它队列才有机会得到更多的消息。</para>
|
||
</section>
|
||
<section>
|
||
<title>分页转存与消息的选择器(selector)</title>
|
||
<note><para>请注意消息选择器只对内存的消息进行操作。如果大量的消息被转存在磁盘中,而其中有些消息与选择器是相匹配的,
|
||
那么只有内存的消息被传递,这些消息被重新装载入内存后才有可能被传递出去。
|
||
HornetQ不会扫描在磁盘中的消息来找出与选择器匹配的消息。这样做的话需要实现并管理一种索引机制才能使扫描有效地进行,另外
|
||
需要其它额外的工作。所有这些如果去完成的话,相当于实现一个关系型数据库!这并不是消息系统的主要任务。如果你要完成的任务是
|
||
从海量的消息中选择少数消息,那么你很可能需要使用的是一个关系型数据库,不是消息系统。因为这相当于表的查询。</para></note>
|
||
</section>
|
||
<section>
|
||
<title>分页转存与浏览器</title>
|
||
<note><para>请注意浏览器只对内存中的消息进行操作,它不对转存到磁盘中的消息进行操作。
|
||
消息是在被路由到任何队列<emphasis>之前</emphasis>进行转存的,所以在转存时刻,它们还没有进入到任何队列中,
|
||
自然也就不可能出现在对某个队列浏览的結果中。
|
||
</para></note>
|
||
</section>
|
||
<section>
|
||
<title>分页转存与未通知的消息</title>
|
||
<note><para>
|
||
请注意如果消息没有被通知,它会一直留在服务器的内存中,占用着内存资源。只要消息在被接收者收到并通知后,它才
|
||
会在服务器端被清除,空出内存空间以便转存在磁盘上的消息被装载到内存进行传递。如果没有通知,消息不会被清除,
|
||
也就不会空出内存空间,转存到磁盘上的消息也就无法装载到内存进行传递。于是在接收端就会呈现出死机的现象。
|
||
|
||
如果消息的通知是依靠<literal>ack-batch-size</literal>的设定进行的批量通知,那么一定要注意不要将
|
||
分页转存的消息临界值设得小于<literal>ack-batch-size</literal>,否则你的系统可能会发生死机现象!
|
||
</para></note>
|
||
</section>
|
||
|
||
|
||
<section>
|
||
<title>例子</title>
|
||
<para><xref linkend="examples.paging"/>是一个说明如何使用HornetQ的分页转发功能的例子。</para>
|
||
</section>
|
||
</chapter>
|