跳到主要内容

Java RTO API最佳实践

上下文和会话线程模型注意事项

建议

  • 尽可能使用“一个会话,一个上下文”的线程模型。 “多个会话,一个上下文”和“多个会话,多个上下文”模型可能会增加消息处理吞吐量,但以增加额外处理为代价。

设计应用程序时需要考虑三种不同的线程模型:

  1. 一个会话一个上下文:使用单个会话和单个上下文。
  2. 多个会话一个上下文:使用一个上下文服务多个会话。
  3. 多个会话多个上下文:应用程序提供或使用多个线程,每个线程包含一个上下文,每个上下文包含一个或多个会话。

在大多数情况下,“一个会话,一个上下文”模型足以用于发布者和消费者应用程序的设计。

如果需要优先处理消息(例如,通过不同的 TCP 连接发送/接收高价值消息),应用程序设计者可能会转向“多个会话,一个上下文”模型。这种方法也可以潜在地增加吞吐量。这意味着可能需要将接收到的消息转发到下游应用程序内部队列,以便由其他应用程序消息处理线程处理。所有接收到的消息可以由相同的回调函数处理,也可以通过创建额外的回调函数为每个会话创建特定的回调函数。

使用“多个会话,多个上下文”模型,设计者可以减轻“多个会话,一个上下文”模型中上下文线程的处理负担,因为所有会话都必须在 select 循环中等待处理。在这种模型中,每个会话可以分离到自己的上下文线程中,从而增强操作系统多线程提供的处理性能。然而,由于线程数量增加,这种方法需要广泛的线程上下文切换,因此对 CPU 的负担更重,资源消耗更多。

上下文线程亲和性

建议

  • 使用 IPCSupport.CONTEXT_PROPERTIES.THREAD_AFFINITY_CPU_LIST 将 API 生成的上下文线程固定到 CPU。

当上下文线程由 C API 自动生成时,可以通过在上下文创建期间使用 IPCSupport.CONTEXT_PROPERTIES.THREAD_AFFINITY_CPU_LIST 参数设置上下文线程的线程亲和性。设置线程亲和性可以将特定的 CPU 专门用于处理改进,并防止上下文线程被其他进程中断。默认情况下,自动生成的上下文线程的线程亲和性未设置,允许操作系统在可用的 CPU 上最优地调度上下文线程。预期的字符串值是用逗号分隔的列表,可以是:

  • 数字 — 介于 0 和系统中 CPU 数量之间的十进制非负整数。

和/或

  • 范围 — 两个数字之间用短横线分隔。

以下示例展示了如何创建 ContextHandle 并使用数字和范围为 CPU 列表设置线程亲和性:

final ContextHandle contextHandle = Solclient.Allocator.newContextHandle();
String[] contextProps = new String[2];
int propIndex = 0;
contextProps[propIndex++] = IPCSupport.CONTEXT_PROPERTIES.THREAD_AFFINITY_CPU_LIST;

contextProps[propIndex++] = "1,2,3,8-10,13-15";

rc = Solclient.createContextForHandle(contextHandle, contextProps);
assertReturnCode("Solclient.createContextForHandle()", rc, SolEnum.ReturnCode.OK);

IPCSupport.CONTEXT_PROPERTIES.THREAD_AFFINITY_CPU_LIST 的默认值为空字符串,结果是没有设置线程亲和性。

有关更多信息和使用细节,请参阅 PubSub+ 消息 API for Java RTO 参考。


内存管理

Java RTO API 的设计目标是在 JVM 中不引发垃圾回收。然而,为了防止垃圾回收,使用 Java RTO API 的应用程序也必须正确设计。

修改全局池缓冲区大小

当初始化 Java RTO API 时,您可以选择修改用于五个池的默认全局数据缓冲区大小。

当您调用 Solclient.init(...) 函数初始化 C API 时,您可以传递 Solclient.GLOBAL_PROPERTIES.DBQUANTASIZE_<0-4> “DBQUANTASIZE” 来指定每个池的数据缓冲区大小(以字节为单位)。

有关更多信息,请参阅 PubSub+ 消息 API for Java RTO 参考。

配置消息缓冲区大小

在创建会话时,应用程序可以配置以下与内存和资源分配相关的会话属性参数:

  • SessionHandle.PROPERTIES.BUFFER_SIZE
    用于 TCP 会话传输消息的会话缓冲区大小。此参数指定要缓冲的消息的最大数量(以字节为单位)。为了获得最佳性能,当发送小消息时,会话缓冲区大小应设置为典型消息大小的多倍。

    C API 始终至少接受一个消息进行传输。因此,即使单个消息的大小超过了设置的缓冲区大小,只要当前缓冲区数据为零,它也会被接受并传输。然而,直到缓冲区中的数据量减少到低于设置的缓冲区大小之前,不会再接受其他消息。

  • SessionHandle.PROPERTIES.SOCKET_RCV_BUF_SIZE
    订阅者数据套接字的接收缓冲区大小(以字节为单位)。默认值为 150,000。如果此属性设置为 0,则接收缓冲区大小使用操作系统默认值。

    在 Windows 平台上,接收套接字缓冲区大小必须比发送套接字缓冲区大小大得多,以防止在发送和接收消息时丢失数据。例如,User: 继续说 Kimi: 默认的发送套接字和内部缓冲区大小设置为 90,000,而默认的接收套接字缓冲区大小设置为 150,000。如果您更改了默认大小,建议保持类似的大小比例。

  • SessionHandle.PROPERTIES.SOCKET_SEND_BUF_SIZE
    此参数允许应用程序设置发布者数据套接字的发送缓冲区大小(以字节为单位)。默认值为 90,000。如果此属性设置为 0,则发送缓冲区大小使用操作系统默认值。

对象池化

尽可能不要分配和释放对象,而是预先分配并重用对象。这包括 Java RTO API 提供的所有对象,以及应用程序中的所有其他对象。Solace 建议应用程序设计者遵循对象池模式来实现这一点。

对象池模式涉及使用和重用初始化对象池,而不是根据需要销毁和重新创建对象。只有当池中没有可用对象时,才创建新对象,以尽量减少使用中的总对象数量。

获取与占用

使用 MessageHandle.getRxMessage() 获取消息时,Java RTO API 保留消息及其分配内存的所有权。消息回调完成后,API 会自动释放消息。为了获得最佳性能,Solace 建议使用 MessageHandle.getRxMessage()

使用 MessageHandle.takeRxmessage(MessageHandle) 获取消息时,应用程序获取消息的所有权。使用 Handle.destroy() 销毁消息成为应用程序的责任。使用 MessageHandle.takeRxmessage(MessageHandle) 会在 Java RTO API 内部触发一次复制。

SessionHandleFlowHandleCacheSessionHandle 中的等效方法也适用相同的获取与占用区分。

TCP发送和接收缓冲区大小

建议

  • 调整 TCP 发送和接收缓冲区大小,以优化 TCP 性能,特别是在发布大消息或优化 WAN 性能时。

对于 TCP,带宽延迟乘积是指数据链路的容量与其往返延迟时间的乘积。结果表示网络上任何给定时间可以存在的最大数据量。由于 WAN 环境的固有长往返延迟,预计带宽延迟乘积较大,因此 TCP 只有在发送者发送足够大量的数据以填满网络可以接受的最大数据量时,才能实现最佳吞吐量。这意味着需要调整 TCP 发送和接收缓冲区大小。

具体到 Windows 平台,接收套接字缓冲区大小必须比发送套接字缓冲区大小大得多,以防止在发送和接收消息时丢失数据。推荐的比例是发送缓冲区占 3 份,接收缓冲区占 5 份。

TCP 的套接字发送和接收缓冲区大小可以通过 API 的会话属性设置进行配置。会话属性参数及其默认值如下。如果使用值 0 设置这些属性,则使用操作系统的默认大小。

  • SessionHandle.PROPERTIES.SOCKET_RCV_BUF_SIZE;默认值为 150,000 字节。
  • SessionHandle.PROPERTIES.SOCKET_SEND_BUF_SIZE;默认值为 90,000 字节。

会话建立

阻塞连接

建议

  • 连接阻塞调用会序列化每个会话连接,增加会话建立延迟。如果序列化不是必要的,请禁用阻塞连接以提高整体会话连接速度。

启用阻塞连接会序列化上下文中配置的每个单独会话连接。这样做会增加连接时间。如果序列化不重要,请考虑禁用阻塞连接。

阻塞连接属性为 SessionHandle.PROPERTIES.CONNECT_BLOCKING

主机列表

建议

  • 作为最佳实践,使用主机列表(见下文注释)。 主机列表适用于您使用复制进行故障转移支持以及软件事件代理的主机列表高可用性(HA)支持时。

不应在主动/主动复制部署中使用主机列表。

对于复制故障转移支持,客户端应用程序必须配置一个包含两个地址的主机列表,每个站点的启用保证消息的虚拟路由器各一个。如果一个主机的连接失败,则客户端会尝试连接到即将成为活动状态的复制主机,然后再尝试连接同一个主机。因此,建议将每个主机的重新连接尝试次数设置为 1。

主机列表不应在主动/主动复制部署中使用,其中客户端应用程序从两个站点的复制活动消息 VPN 上的端点消费消息。

同样,对于软件事件代理 HA 故障转移支持,如果切换机制设置为主机列表而不是 IP 地址接管,则客户端应用程序必须提供一个包含两个地址的主机列表。

有关主机列表配置的更多详细信息,请参阅 HA 组配置。

客户端API保持活动

建议

  • 客户端保持活动间隔应与客户端配置文件上的 TCP 保持活动设置处于同一数量级。

客户端应用程序和事件代理之间存在两种类型的保持活动机制。

一种是 TCP 保持活动,它在 TCP 层由事件代理发送到客户端应用程序。这是 RFC 1122 中描述的 TCP 保持活动机制。客户端应用程序的 TCP 堆栈响应事件代理的 TCP 保持活动探测。默认情况下,事件代理在检测到空闲连接 3 秒后发送一个保持活动消息。然后,它以每秒 1 次的间隔发送 5 个探测。因此,如果事件代理在 8 秒后未收到响应,则会将客户端标记为 TCP 保持活动失败。

还有客户端 API 保持活动,它与 TCP 保持活动同时发生。这是 API 的内置保持活动机制,运行在 TCP 之上的 API 层。它由 API 发送到事件代理。默认情况下,客户端保持活动以每 3 秒一次的间隔发送,并且在 API 声明事件代理不可达之前可以错过 3 次保持活动响应,即 9 秒后。

这些保持活动机制的存在是为了能够在通知相应方之前告知应用程序或事件代理其对端已死亡。保持活动机制还用于防止因网络空闲而导致的断开连接。然而,如果其中一种机制设置得比另一种更具侵略性(即,检测时间更短),则连接可能会过早断开。例如,如果客户端 API 保持活动设置为 500 毫秒间隔,有 3 次保持活动响应,而 TCP 保持活动保持默认值不变,则客户端 API 保持活动将触发激进的断开连接。

高可用性故障转移和重新连接尝试

建议

  • 在设计支持高可用性(HA)的应用程序时,重新连接持续时间应设置为至少 300 秒。

在使用高可用性(HA)设备设置时,从一个设备到其配对设备的故障转移通常会在 30 秒内发生。然而,应用程序应尝试重新连接至少 5 分钟。以下是使用以下会话属性值将重新连接持续时间设置为 5 分钟的示例:

  • 连接尝试次数:1
  • 重新连接尝试次数:20
  • 重新连接尝试等待时间:3,000 毫秒
  • 每个主机的连接尝试次数:5

有关设置连接尝试、重新连接尝试、重新连接尝试等待时间和每个主机的连接尝试参数的说明,请参阅“配置连接超时和重试”。

复制故障转移和重新连接尝试

建议

  • 在复制故障转移期间,应将重新连接尝试次数设置为 -1,以便 API 无限期地重试。

一般来说,复制故障转移的持续时间是非确定性的,因为它可能需要操作干预进行切换,这可能需要数十分钟甚至数小时。因此,建议将重新连接尝试次数设置为 -1,以便 API 为复制感知型客户端应用程序无限期地重新连接。

有关如何设置重新连接尝试参数的说明,请参阅“重新连接尝试”。

复制故障转移和会话重新建立

建议

  • API 版本高于 7.1.2 是复制感知型的,并且在复制故障转移发生时自动处理会话重新建立。运行较低 API 版本的客户端应用程序必须在重新连接后重新建立会话。

在 7.1.2 之前,当客户端在已断开连接的会话中发布保证消息时,需要在复制故障转移后重新建立会话,因为尽管重新连接成功,但由于新连接的事件代理在复制站点中没有流状态信息(与 HA 故障转移不同,HA 故障转移会同步此信息),因此需要重新建立流。建议捕获 unknown_flow_name 事件并重新建立新会话以创建流。从 7.1.2 版本开始,API 是复制感知型的,并且透明地处理会话重新建立。

文件描述符限制

建议

  • 应用程序创建的 Solace 会话数量不应超过底层操作系统每个进程支持的文件描述符数量。 对于 Unix 变体,此数字为 1024,对于 Windows 为 63。

Unix 平台上的文件描述符限制限制了每个进程可以管理的文件数量,默认为 1024。因此,应用程序不应在每个上下文中创建超过 1023 个会话。会话代表一个 TCP/IP 连接,此类连接占用一个文件描述符。文件描述符是一个元素——通常是一个数字——它允许您识别,即在本例中,从套接字中识别数据流。从磁盘打开文件以读取信息也会占用一个文件描述符。

文件描述符被称为“文件”,因为最初它们只用于标识文件,尽管最近,它们也可以用于标识磁盘上的文件、套接字、管道等。

同样,在 Windows 平台上,单个上下文最多只能管理 63 个会话。


订阅管理

以下最佳实践可用于管理订阅:

  • 如果您正在添加或删除大量订阅,请在最终订阅上设置等待确认标志(SessionHandle.SolEnum.SubscribeFlags.WAIT_FOR_CONFIRM),以确保所有订阅都已由事件代理处理。 为了提高性能,建议在所有其他订阅上不设置等待确认,除了最后一个。
  • 在会话断开连接时,您可以配置 API 在重新连接时重新应用最初由应用程序添加的订阅。 为了重新应用订阅,请启用会话属性 SessionHandle.PROPERTIES.REAPPLY_SUBSCRIPTIONS。建议使用此设置。

发送消息

阻塞发送

建议
  • 发送阻塞调用会自动限制事件代理可以接受消息的发布速率。使用非阻塞发送以提高应用程序性能。

在发送阻塞模式下,每个发送函数调用的调用线程将被阻塞,直到 API 接受消息,因此,发送速率自动限制为事件代理可以接受消息的速率。发送调用将保持阻塞,直到:

  • 被 API 接受,或者
  • 相关联的阻塞写入超时到期。

与非阻塞模式相比,无法被 API 接受的发送调用将立即向客户端应用程序返回 would_block 错误代码。在此期间,客户端应用程序可以继续处理其他操作。随后,API 将收到一个 can_send 事件,这表明客户端应用程序可以再次重试 send() 函数调用。

发送阻塞参数是 SessionHandle.PROPERTIES.SEND_BLOCKING

批量发送

建议
  • 使用批量发送功能以优化发送性能。 这对于性能基准测试客户端应用程序尤其有用。

使用批量发送功能以优化发送性能。这对于性能基准测试客户端应用程序尤其有用。

可以通过单个 API 调用发送多达 50 条消息。这允许消息以批量形式发送。消息可以是直接消息或保证消息。在通过发送多个 API 批量发送消息时,应该为批次中的所有消息设置相同的传输模式,即直接模式或持久模式。批次中的消息可以设置为不同的目标。

除了使用批量发送 API 之外,应尽可能预先分配并重用消息,以用于批量发送。具体来说,不要为每次调用批量发送 API 重新分配新消息。

批量发送 API 调用是 SessionHandle.send()

消息生存时间

建议
  • 如果用例允许丢弃旧的或过时的消息,则在发布的保证消息上设置 TTL 属性,以减少未消费消息意外堆积的风险。

发布应用程序应考虑使用保证消息可用的 TTL 功能。发布者可以在将消息发送到事件代理之前为每条消息设置 TTL 属性。一旦消息被暂存,如果消息在指定的 TTL 内未被消费,则消息将被自动丢弃(或者如果配置了队列的死信队列,则移动到队列的死信队列)。这种常见做法可以减少未消费消息意外堆积的风险。

或者,队列有一个 max-ttl 设置,可以用来代替发布者在每条消息上设置 TTL。有关如何为队列设置 max-ttl 的说明,请参阅“配置最大消息 TTL”。

配置尊重 TTL

队列应配置为 respect-ttl,因为默认情况下,此功能在所有队列上都是禁用的。有关如何设置 respect-ttl 的说明,请参阅“强制尊重 TTL”。

接收消息

接收消息时的内存管理

建议
  • 在接收消息时,建议允许 API 保留消息的所有权。如果将所有权传递给应用程序,它必须确保在使用后释放消息。

通常情况下,回调接收到的消息缓冲区由 API 所有。这些消息缓冲区在消息回调完成后由 API 自动释放。然而,所有权可以传递给应用程序。在这种情况下,应用程序必须在完成使用后释放消息,以释放内存。

处理重复消息发布

建议
  • 如果客户端应用程序使用最后值队列(LVQ)来确定事件代理在重新启动时成功暂存的最后一条消息,则可以避免发布重复消息。

当客户端应用程序意外重新启动时,它可能会与消息发布序列不同步。应该有一种机制,使它可以确定最后一条成功发布到并被事件代理接收的消息,以便在不注入重复消息的情况下正确恢复发布。

一种方法是发布应用程序维护一个数据库,将发布的消息标识符与它从事件代理收到的确认进行关联。这种方法完全在客户端应用程序端进行,但如果管理不当,可能会引入处理延迟。

另一种方法是利用最后值队列(LVQ)功能,LVQ 存储队列上暂存的最后一条消息。发布客户端应用程序可以浏览 LVQ 以确定事件代理暂存的最后一条消息。这允许发布者在不引入重复消息的情况下恢复发布。

有关如何设置 LVQ 的说明,请参阅“配置最大暂存使用值”。

处理重新投递的消息

建议
  • 当从端点消费时,客户端应用程序应适当处理重新投递的消息。

当客户端应用程序重新启动,无论是意外的还是正常的,并重新绑定到队列时,它可能会收到已经处理并确认的消息。这可能会发生,因为确认可能在到达事件代理的途中由于网络问题而丢失。重新投递的消息将标记为 redelivered 标志。

消息的 redelivered 标志:

  • 在高可用性(HA)故障转移之间主备事件代理之间持续存在。
  • 在复制到灾难恢复(DR)站点时不会持续。

绑定到非独占队列的客户端应用程序也可能收到设置了 redelivered 标志的消息,即使这些消息是客户端应用程序首次接收的。这是由于其他客户端连接到同一个非独占队列并在没有应用程序确认收到的消息的情况下断开连接。然后,这些消息将重新投递到绑定到同一个非独占队列的其他客户端应用程序。

消费应用程序应包含一个消息处理机制,以处理上述提到的情况。

处理意外的消息格式

建议
  • 客户端应用程序应能够处理意外的消息格式。 在从端点消费时,即使消息格式意外,客户端应用程序也应确认收到的消息。

客户端应用程序应能够应对意外的消息格式。不应假设消息的有效负载;例如,有效负载可能包含一个空的附件。应用程序应编写代码,以避免崩溃,并在使用保证消息时记录消息内容并向事件代理发送确认。如果客户端应用程序在未发送确认的情况下崩溃,则当它们重新连接时,相同的消息将被重新投递,导致应用程序再次失败。

客户端确认

建议
  • 当使用客户端确认模式时,客户端应用程序应在完成处理消息后尽快确认收到的消息。

一旦应用程序完成处理消息,它应向事件代理确认收到消息。只有当事件代理收到保证消息的确认时,消息才会从其消息暂存中永久删除。如果客户端在没有发送确认的情况下断开连接,那么这些消息将被重新投递。对于独占队列的情况,这些消息将被传递给下一个连接的客户端。对于非独占队列的情况,这些消息将被重新投递到绑定到队列的其他客户端。

有两种确认方式:

  • API(也称为传输)确认。这是 API 和事件代理之间的内部确认,不暴露给应用程序。保证传输确认窗口大小、确认定时器和确认阈值设置控制 API 确认。未传输确认的消息将由事件代理自动重新投递。
  • 应用程序确认。这种确认机制在 API 确认之上。其主要目的是确认消息处理已完成,并且相应的消息可以从事件代理中永久删除。有两种应用程序确认模式:自动确认和客户端确认。当使用自动确认模式时,API 代表应用程序自动生成应用程序级别的确认。当使用客户端确认模式时,客户端应用程序必须明确发送每个收到的消息的确认。

有关不同确认模式的更详细讨论,请参阅“接收保证消息”。

回调中不要阻塞

应用程序必须避免在消息接收、事件和计时器回调中阻塞,并应尽快返回,以便调用线程可以处理下一个消息、事件或计时器并执行内部 API 维护。事务性会话的唯一例外是,应用程序可以在事务性会话的消息接收回调中调用 API 提供的阻塞函数,如提交、回滚和发送。

队列和流

每次接收一条消息

建议
  • max-delivered-unacked-msgs-per-flow 设置为 1,并将保证传输窗口大小设置为 1,以确保消息从事件代理到客户端应用程序一次一条且时间一致地投递。

API 只有在满足以下条件之一时才会发送传输确认:

  1. 它已收到配置的保证传输窗口消息的配置确认阈值(例如 60%)。
  2. 自上次确认发送以来,已过去配置的保证传输确认时间(例如 1 秒),以先到者为准。

应用程序确认会搭便车到传输确认上,用于从客户端应用程序到事件代理的投递。并且只有在事件代理收到确认后,才会释放更多消息。

因此,虽然将 max-delivered-unacked-msgs-per-flow 设置为 1 可以确保消息一次一条投递到客户端应用程序,但如果保证传输窗口大小不是 1,则条件 1 不会立即满足。这可能会导致接收延迟变化,因为 API 只有在条件 2 满足后才会发送确认。这与预期的端到端消息接收延迟不一致。为了避免这种情况,事件代理会告知 API 端点的 max-delivered-unacked-msgs-per-flow 设置。然后 API 使用此信息自动调整其确认阈值,以防止接收延迟变化。

有关如何在队列上配置 max-delivered-unacked-msgs-per-flow 的说明,请参阅“配置每个端点允许的最大未确认消息数”。

设置临时端点暂存大小

建议
  • 如果客户端应用程序频繁创建临时端点,请谨慎行事,以确保所有临时端点的暂存大小总和不超过为消息 VPN 配置的总暂存大小。

默认情况下,消息 VPN 和端点的消息暂存配额基于过度订阅模型。例如,可以将多个端点的消息暂存配额设置为与整个消息 VPN 的配额相同。客户端应用程序创建的临时端点默认为 Solace 应用程序 4000 MB,软件事件代理为 1500 MB。当客户端应用程序广泛使用临时端点时,基于临时端点按需创建的消息暂存过度订阅模型可能会迅速失控。因此,建议客户端应用程序覆盖端点的默认消息暂存大小,设置为与预期使用量一致的值,特别是如果广泛使用临时端点时。

建议
  • API 上配置的保证传输窗口大小不应大于事件代理上为队列设置的 max-delivered-unacked-msgs-per-flow 值。

max-delivered-unacked-msgs-per-flow 控制事件代理可以向客户端应用程序投递多少条消息而无需收到确认。保证传输窗口大小控制在事件代理和客户端应用程序之间传输的消息数量。因此,如果保证传输窗口大小大于 max-delivered-unacked-msgs-per-flow,则 API 可能无法及时确认它接收到的消息。实际上,保证传输窗口大小受到 max-delivered-unacked-msgs-per-flow 设置值的限制。例如,如果保证传输窗口大小设置为 10,而 max-delivered-unacked-msgs-per-flow 设置为 5,则无论客户端应用程序的保证传输窗口大小设置为 10,事件代理实际上一次只能发送 5 条消息。

有关如何在队列上设置 max-delivered-unacked-msgs-per-flow 的说明,请参阅“配置每个端点允许的最大未确认消息数”。

流的数量和保证传输窗口大小

建议
  • 根据客户端应用程序主机的可用内存限制以及事件代理上每个客户端出口队列分配的默认工作单位数量,对每个会话预期的流数量及其相关的保证传输窗口大小进行调整。

API 会缓冲接收到的保证消息,通常还拥有这些消息并负责释放它们。客户端使用的缓冲区数量主要由每个会话使用的流数量乘以保证传输窗口大小决定。例如,如果一个接收客户端应用程序使用窗口大小为 255 的流绑定到事件代理上的 10 个不同队列,假设消息平均大小为 1MB,则最大缓冲区使用量将达到 2560MB。如果在同一主机上有 10 个这样的客户端,则需要 25.6GB 的内存。

同样,事件代理会为每个客户端出口队列分配一个缓冲区,用于暂存要传输到客户端应用程序的消息。默认情况下,这是 20,000 个工作单位,相当于 40MB 的缓冲区,因为每个工作单位为 2048 字节。为了使一个客户端出口队列支持 2560MB 的缓冲区,该特定客户端的工作单位数量需要增加到 130,560。因此,根据应用程序的使用情况,建议您根据每个会话预期的流数量调整保证传输窗口大小,使其在每个客户端连接的默认 20,000 个工作单位的缓冲区内。

错误处理和日志记录

日志和日志级别

建议
  • 在生产环境中不应启用客户端应用程序的调试级别日志。

客户端应用程序事件日志可能会对性能产生重大影响,因此在生产环境中不建议启用调试级别日志。

详细日志级别(如调试和信息)可能会导致 JVM 执行垃圾回收。这将无意中违背 Java RTO API 的设计原则,即在 JVM 中不引发垃圾回收。

处理会话事件/错误

建议
  • 在创建会话时,客户端应用程序应注册会话事件处理程序接口/委托/回调的实现,以接收会话事件。

客户端应用程序应在创建会话时注册会话事件处理程序接口/委托/回调的实现,以接收会话事件。随后,应根据客户端应用程序的使用情况适当处理会话事件。

Java RTO (SolEnum. SessionEventCode)描述
ACKNOWLEDGEMENT已确认的最老传输的持久/非持久消息。
ASSURED_DELIVERY_DOWN保证消息发布不可用。
CAN_SEND发送不再阻塞。
CONNECT_FAILED_ERROR会话尝试连接但未成功。
DOWN_ERROR会话已建立,然后断开。
MODIFYPROP_FAIL会话属性修改失败。
MODIFYPROP_OK会话属性修改完成。
PROVISION_ERROR端点创建/删除命令失败。
PROVISION_OK端点创建/删除命令完成。
RECONNECTED_NOTICE会话的自动重新连接成功,会话重新建立。
RECONNECTING_NOTICE会话已断开,正在进行自动重新连接尝试。
REJECTED_MSG_ERROR设备拒绝发布的消息。
REPUBLISH_UNACKED_MESSAGES在成功重新连接已断开的会话后,API 在重新连接保证传输发布流时收到未知发布者流名称响应。
RX_MSG_TOO_BIG_ERRORAPI 丢弃了一个超过会话缓冲区大小的接收消息。
SUBSCRIPTION_ERROR应用程序拒绝订阅(添加或删除)。
SUBSCRIPTION_OK订阅或取消订阅操作成功。
TE_UNSUBSCRIBE_ERROR主题端点取消订阅命令失败。
TE_UNSUBSCRIBE_OK主题端点取消订阅完成。
UP_NOTICE会话已建立。
VIRTUAL_ROUTER_NAME_CHANGED在重新连接操作期间,设备的虚拟路由器名称发生了变化。

处理流事件/错误

建议
  • 在创建流时,客户端应用程序应注册流事件处理程序接口/委托/回调的实现,以接收流事件。

客户端应用程序应在创建流时注册流事件处理程序接口/委托/回调的实现,以接收流事件。根据客户端应用程序的使用情况,应适当处理流错误/事件。

| Java RTO
(SolEnum.

FlowEventCode)描述
UP_NOTICE流已建立。
DOWN_ERROR流已建立,然后被设备断开,可能是因为操作员干预。
BIND_FAILED_ERROR流尝试连接但未成功。
SESSION_DOWN流的会话已断开。
ACTIVE流已激活。
INACTIVE流已停用。
RECONNECTING当启用流重新连接时,而不是 DOWN_ERROR 事件,API 会生成此事件并尝试重新绑定流。
如果流重新绑定失败,API 会监控绑定失败,并在以下原因之外终止重新连接尝试:
  • 队列关闭
  • 主题端点关闭
  • 服务不可用
    有关流重新连接的更多信息,请参阅“流重新连接”。| | RECONNECTED| 流已成功重新连接。 |

影响客户端应用程序行为的事件代理配置

最大重新投递

建议
  • 默认情况下,消息将无限次从端点重新投递给客户端。 在事件代理上为端点设置最大重新投递选项,以限制每条消息的最大重新投递次数。

可以在端点上设置最大重新投递选项,以控制该端点上每条消息的投递次数。端点的重新投递次数超过最大值后,消息将被丢弃或移动到死信队列(DMQ),如果已配置且消息设置为 DMQ 合格。

当端点上的重新投递次数不是无限的(默认情况下重新投递模式设置为永远重新投递)时,客户端应用程序将受益。例如,如果客户端应用程序无法处理意外的毒药消息,该消息最终将被丢弃或移动到 DMQ,以便进行进一步检查。

拒绝消息发送方在丢弃时

建议
  • 除非有充分理由,否则应在端点上启用 reject-msg-to-sender-on-discard

当向事件代理发布保证消息时,消息可能会因为消息暂存区满、消息最大大小超过、端点关闭等原因而被丢弃。如果端点上的消息丢弃选项(即 reject-msg-to-sender-on-discard)已启用,则客户端应用程序将能够检测到正在发生丢弃,并采取纠正措施,例如暂停发布。API 没有明确支持暂停发布;这应由客户端应用程序逻辑完成。

考虑禁用 reject-msg-to-send-on-discard 的一个原因是,当有多个队列订阅发布保证消息的主题时,目的是让其他队列继续接收消息,即使其中一个队列被认为无法接受消息。