常见 jVerbs 问题(仅限 Linux)
您可以使用 jVerbs 接口来开发使用高速网络基础结构 (例如 InfiniBand) 的 Java™ 应用程序。 在使用 jVerbs 接口时,可能会看到以下问题。
IBM® SDK,Java 技术版,第 8 版中删除了之前被弃用的 RDMA 实现。
尝试连接时生成了连接事件 RDMA_CM_EVENT_REJECTED
当没有服务器在运行时,或者当服务器忙于其他处理时,在客户机上会生成此事件。
要避免此问题,请确保服务器正在意向端口上运行。 如果出现失败,那么还应编写应用程序来重试连接。
队列对错误,操作码为 IBV_WC_WR_FLUSH_ERR
如果发送和接收缓冲区大小不匹配,那么发送或接收请求可能会产生无法恢复的队列对错误。 可以向通信过程中添加步骤来避免此问题。
如果接收缓冲区的大小与发送缓冲区的大小不匹配,那么可能会发生此问题。 发送操作失败,操作码为 IBV_WC_LOC_LEN_ERR(在接收方端)和 IBV_WC_REM_INV_REQ_ERR(在发送方端)。 此类错误会导致队列对进入错误状态,并且进一步发送或接收请求将生成操作码 IBV_WC_WR_FLUSH_ERR。 无法恢复队列对。
要避免此问题,请确保发布的接收缓冲区的长度足以存放发送请求。 如果长度未知,那么可以对应用程序进行编程,以在发送之前传达所需长度。 在另一端,可以为缓冲区准备用于接收的相应大小。
接收到操作码为 IBV_WC_RETRY_EXC_ERR 的工作完成事件
客户机或服务器未响应发布的请求(发送或接收)。
此问题在一端完成发送请求但接收缓冲区尚未发布时较为普遍。 在此情况下,发送端会接收到此工作完成事件。
要避免此问题,请确保发布缓冲区以在发送数据之前先接收数据。 如果是多次发送数据,请确保接收端发布足够的缓冲区来存放所有并行发送请求。
发生本机 OutOfMemory 异常
jVerbs 接口使用直接字节缓冲区来传输数据,并以内部方式用于有状态 verbs 方法操作以及将复杂数据结构传递到本机代码。 因此,在不符合应用程序的内存需求的计算机上可能会接收到本机 OutOfMemory 异常。
- 使用 DBB.cleaner().clean() 方法,将已用缓冲区标记为适合于进行垃圾回收。
- 如果不再使用缓冲区(例如,由于发布尚未完成),请考虑复用这些缓冲区。
- 使用 -XX:MaxDirectMemorySize=<size> 命令行选项以在内存分配达到指定大小时触发垃圾回收。
- 创建一次有状态 verbs 方法,然后多次对其进行调用(如果参数相同)。 调用该方法后,使用 StatefulVerbMethod 对象的 free() 方法将分配的内存标记为适合于垃圾回收。
内存损坏
如果在远程读取、写入或接收操作正在使用缓冲区时,该缓冲区用于其他操作,那么可能会发生内存损坏。
请确保在复用缓冲区之前,针对为该缓冲区发布的操作接收到完成事件。
getConnectionEvent(-1) 或 getCompletionEvent(-1) 方法永久阻止
如果将 -1 作为参数传递到 getConnectionEvent(int timeout) 或 getCompletionEvent(int timeout) 事件方法来指示无超时,那么即使方法等待事件的通道已损坏,这些方法也会永久阻止。
此问题是底层 OFED 实施存在的一个已知问题。 要避免此问题,请仅在您知道将接收到事件时才将这些方法与 -1 参数配合使用。 或者,指定超时值或使用 pollCQEvent() 方法。