常见 JSOR 问题(仅限 Linux)
使用基于远程直接内存访问 (JSOR) 的 Java™ 套接字来利用高性能网络基础结构,例如 InfiniBand。 要使用 JSOR,必须设置、配置和调优各种资源。 如果操作不正确,可能会发生问题。


RDMA 套接字或线程创建失败
在无法创建线程或远程直接存储器存取 (RDMA) 套接字的情况下,可能发生 JSOR 问题。 导致此问题的原因可能是通过 RDMA 传输来运行并发连接。
可能的原因
- RDMA 套接字缓冲区在缺省情况下是固定或内存锁定的。 环境中受限的 memlock 设置可能导致无法创建或注册新的 RDMA 套接字。
- 运行并行连接时,各 RDMA 套接字隐式使用文件描述符进行事件跟踪。 如果最大用户打开文件数限制过低,那么套接字创建可能会失败。
- 运行并行连接时,最大用户进程数限制过低可能会导致线程创建失败。 有关详细信息,请参阅以下技术说明:java.lang.OutOfMemoryError 同时创建新线程。
缓解
- 为避免套接字创建失败,请检查
ulimit -l
设置,并根据套接字缓冲区的使用情况将 memlock 设置更改为适合的值。 - 为避免在运行并发连接时套接字创建失败,请检查
ulimit -n
设置,并根据应用程序的可扩展需求将 nofile 设置更改为适合的值。 - 为避免在运行并发连接时线程创建失败,请检查
ulimit -u
设置,并根据应用程序的可扩展需求将 nproc 设置更改为适合的值。
RDMA 网络提供商初始化失败
在运行 32 位 JVM 时,如果 64 位 Linux 操作系统上的远程直接存储器存取 (RDMA) 网络提供商初始化失败,那么可能发生 JSOR 问题。
在 RDMA 网络初始化阶段,JSOR 运行时环境会检查兼容 OFED 运行时库的可用性。 如果运行时环境无法找到和装入 librdmacm.so 和 libibverbs.so 32 位库,那么您可能会看到此问题。 要避免此问题,请在 64 位 Linux® 机器上安装 32 位 OFED 运行时库以及通常的 64 位库。
RDMA 连接失败
在远程直接存储器存取 (RDMA) 客户机未能连接到 RDMA 服务器的情况下,可能发生 JSOR 问题。
客户机和服务器在同一主机上
如果客户机和服务器位于同一主机上,那么预期会出现此行为,因为当前不支持 RDMA 回送。 为成功进行连接,客户机和服务器应位于由 InfiniBand 交换机通过 RDMA 网络接口适配器连接的不同主机上。
客户机和服务器在不同子网上
RDMA 客户机和服务器应位于由公共 InfiniBand 交换机连接并由单个子网管理器管理的同一网络上。 如果 RDMA 客户机和服务器位于不同子网上,请确保在硬件和软件级别启用网络间交换和包转发。
客户机和服务器在同一子网上
如果客户机和服务器位于同一子网上,那么连接失败可能是由于客户机或服务器配置文件不正确或者一台或两台主机上的 InfiniBand 设置不正确所导致。
确保配置文件中的规则条目定义正确,如 -Dcom.ibm.net.rdma.conf (Linux 仅适用) 中所述。
- 确保通信中涉及的各主机具有相应的 InfiniBand 主机通道适配器或带有有效 InfiniBand 地址的 RDMA 网络接口卡(以前缀 ib 开头的接口)。
- 确保各 InfiniBand 端口处于活动状态且正确设置了最大传输单元。 要检查最大传输单元,请运行以下某个 OFED 运行时命令:ibstat 或 ibv_devinfo。
- 确保 ifconfig 命令列出所有 InfiniBand 接口,并且各接口具有有效的 IP 地址。
- 选择向子网管理器注册的用于制定 JSOR 配置规则的两个有效 InfiniBand 地址,然后通过对所选的 InfiniBand 地址运行 rping 命令来验证主机和客户端机器之间是否可以进行基本 RDMA 通信。
- 类似地,运行 ibv_rc_pingpong 命令。
- 类似地,运行 ib_read_bw 和 ib_write_bw 命令。
RDMA 连接重置异常
尝试数百万次地将小数据区块发送到单个 RDMA 服务器的并发远程直接存储器存取 (RDMA) 客户机可能会抛出连接重置异常。
Java Sockets over Remote Direct Memory Access (JSOR) 采用 R-Sockets 协议作为在 RDMA 基础上实现套接字级 API 的基础。 R-Sockets 协议使用发送和接收队列大小作为在发送方和接收方之间实施数据流和事件控制的基础。 当若干并行客户机尝试百万次地发送少量数据时,它们可能会由于队列大小不足而遇到连接重置异常。 发生此行为是因为队列大小规定了任一端可以排队的工作量。
由于默认队列大小很大(请参阅 JSOR 环境设置(Linux 仅适用)),只有在极少数情况下才需要调整队列大小。 您应根据应用程序的工作负载特征来确定队列大小。 发送和接收操作的最大数量和频率尤其重要。 没有可用于确定最佳队列大小的一般公式。
RDMA 通信似乎挂起
在运行消息大小不可预测的基于 RPC 的工作负载时,客户机和服务器之间的远程直接存储器存取 (RDMA) 通信似乎挂起。
Java Sockets over Remote Direct Memory Access (JSOR) 采用 R-Sockets 协议作为在 RDMA 基础上实现套接字级 API 的基础。 要正确传输数据,R-Sockets 协议需要协调发送方和接收方。 接收方必须准备好一个接收缓冲区,以供发送方放置数据。 该行为与按需自动分配缓冲区的 TCP/IP 不同。 如果事先未提供足够的接收缓冲区,RDMA 接收操作将失败。 有关详细信息,请参阅 Remote Direct Memory Access Transport for Remote Procedure Call 的 IETF 草案中的流量控制部分。
缺省情况下,JSOR 实现提供了大小小于 50 KB 的较小发送和接收缓冲区。 如果 RDMA 客户机或服务器尝试以 1 KB 这样的区块为单位,单向发送较大有效内容(例如 2 MB 或 4 MB),而不包含端点之间的同步数据流,那么接收缓冲区可能会被耗尽,从而导致挂起的情况。 R-Socket 协议尝试回收接收缓冲区,但如果补给速度小于数据发送速度,那么将无法继续运行。 当有上百个并行客户机尝试在同一 RDMA 传输上执行相同操作时,这些影响更加明显,因为这些客户机争用同一组物理网络资源。 R-Sockets 协议从此情况恢复需要较长的时间,因为它依赖于重试和“接收方未就绪”否定确认才能继续运行。 最糟糕的情况是该行为可能会导致端点之间发生死锁情况。
类似地,发送缓冲区的大小应该足够大,以将数据传输到对应的接收缓冲区。
缓解
对于 Java RPC 应用程序,请先调整缓冲区大小,然后再在生产环境中部署该应用程序。 根据应用程序的工作负载特征和最大有效内容大小,设置缓冲区大小。 没有可用于确定最佳缓冲区大小的一般公式。 有关更多信息,请参阅 JSOR 环境设置(Linux 仅适用)。
启用应用程序或运行时数据传输超时以允许客户机取消并重试数据传输,必要时增加缓冲区大小。 请参阅以下 APAR 示例:PM52124: OutOfMemoryError eXtreme Scale 客户端上的错误会导致网格失败。 在该示例中,内存不足导致服务器线程在 socketWrite() 方法中挂起。 建议的解决方法是设置 com.ibm.CORBA.SocketWriteTimeout 属性。
遇到的零拷贝功能的有关问题
启用零复制功能时 Java 应用程序挂起
由于在使用零拷贝功能时,需要在数据源和数据接收器之间进行内部同步,因此如果仅为一个端点启用零拷贝功能,客户机或服务器应用程序可能会挂起。
- 在使用零拷贝功能时,避免对并行读和写操作使用相同的套接字描述符。
- 确保在两个端点上启用零拷贝功能。 有关详细信息,请参阅 -Dcom.ibm.net.rdma.zeroCopy (Linux only)。
- 确保在两个端点上设置相同的零拷贝阈值。 有关更多信息,请参阅 -Dcom.ibm.net.rdma.zeroCopyThreshold (Linux only)。
Java 应用程序未使用零复制函数
即使在指定 -Dcom.ibm.net.rdma.zeroCopy=true 参数之后, Java 应用程序也可能不使用零复制功能。
- 您已指定 -Dcom.ibm.net.rdma.zeroCopy=true 参数。
- 在 Java 读写调用中传递的缓冲区大小超过 -Dcom.ibm.net.rdma.zeroCopyThreshold 参数指定的值。 有关此参数的更多信息,请参阅 -Dcom.ibm.net.rdma.zeroCopyThreshold (Linux only)。
- socketRead0Direct
- socketWrite0Direct
- RDMA_ReadDirect
- RDMA_SendDirect
Java 应用程序不扩展
零拷贝功能是针对大量数据传输而设计的,一次传输一小部分数据。 由于内部同步和资源分配与管理开销,可伸缩性受到传输的数据大小的限制。
请确保使用方案接近于零拷贝方式下数据传输的文件传输 (FTP) 类型的方案。
遇到派生兼容性方式问题
在 Java 客户机与本机派生服务器之间以派生兼容性方式运行时,可能会发生一些问题。
本机服务器错误消息 librdmacm: Fatal: unable to open RDMA
device
- 具有基于融合以太网的 Mellanox RDMA (RoCE) MT26448 适配器的 POWER ® PC 系统
- Redhat Enterprise Linux (RHEL) v6.4
- MLNX_OFED_LINUX-2.0-3.0.0
如果遇到此问题,请升级到操作系统和 OFED 软件的最新版本。 如果问题仍然存在,请考虑升级到 Mellanox RoCE 适配器的最新版本。
Java 客户机挂起
在派生兼容性方式下,当系统连接到本机派生服务器时, Java 客户机可以挂起。 此问题与 RSocket 预装入库关联。 在内部,当处理 fork() 支持时,库会创建指定的信号量 /rsocket_fork。 但在完成时,R-Socket 库不会移除信标,该信标持久存储,直至系统重新引导为止。 先前调用中的此指定信标的任何旧链接或值会阻止本机服务器接受远程客户机连接。
要解决此问题,请使用 rm 命令在 fork() 预装入开始之前取消链接 /rsocket_fork 指定的信号量。 在 Red Hat Enterprise Linux (RHEL) 上,您可以在目录 /dev/shm 中查找指定的信标。 这些文件具有前缀 sem.。
Java 客户机不扩展
RSockets 协议当前仅为理想条件下运行的简单应用程序提供派生预装入支持。 在预装入派生进程时, RSockets 库使用分块语义将连接迁移到 RDMA。
因此,RSocket 中 fork() 方法的当前支持固有地无法扩展。 尝试使用本机互操作性功能连接到本机派生服务器的 Java 多线程客户机可能会迂到大量失败连接。 要缓解此问题,请将客户机连接重试计数增大到 1 以上。