名词解释:
- RDMA,Remote Direct Memory Access,远程直接内存存取。为低延迟应用提供了一种协议,可以直接访问其他计算机的内存,而不需要操作系统的参与。
- InfiniBand: InfiniBand (IB) 是一项新的基于交换光纤结构的 I/O 技术。 它为将 I/O 设备连接到主机以及主机到主机通信提供了高带宽、低延迟的互连。InfiniBand提供了对RDMA的支持。
- SDP:Sockets Direct Protocol,套接字直接协议。是一种网络协议用于支持在InfiniBand连接上的流连接。
概览
SDP本质上是一种TCP绕过技术。当SDP允许时,一个应用程序尝试打开一个TCP连接,TCP机制被绕过了,通信直接到IB网络。
当应用程序尝试绑定到一个TCP地址时,底层软件根据配置文件里的信息决定是否重新绑定到一个SDP协议。这个过程可以在绑定过程或连接过程(但对每个连接只发生一次)。
不需要修改应用代码里的API就可以利用SDP协议:实现是透明的并被经典网络(java.net)和NIO(java.nio.channels)包支持。
SDP默认是禁止的,开启步骤:
- 创建一个SDP配置文件;
- 设置系统属性指向配置文件路径。
创建SDP配置文件
配置文件的编写规则:配置文件有两种类型的条目,注释行和规则行。注释行是以#
字符开头的。
规则行有两种类型:
- bing规则:只要TCP套接字绑定到与规则匹配的地址和端口,就会使用SDP协议进行传输。
- connect规则:没有绑定的TCP套接字尝试连接匹配规则地址和端口时,就会使用SDP协议进行传输。
配置文件示例:
# 绑定到192.0.2.1时使用SDP,端口任意。
bind 192.0.2.1 *
# 连接到192.0.2.*上的所有应用服务时都使用SDP,且端口是大于等于1024的。用`-`指定的端口范围是闭区间的。
connect 192.0.2.0/24 1024-*
# 用SDP连接到web服务器或数据库
connect examplecluster.example.com 80
connect examplecluster.example.com 3306
启动SDP
在启动JVM时指定SDP的配置文件的路径:
java -Dcom.sun.sdp.conf=sdp.conf -Djava.net.preferIPv4Stack=true Application.class
这里启动时要指定网络格式为IPv4Stack是因为:尽管Java 7和InfiniBand都支持IPv6网络格式,但Solaris和Linux都不支持两者之间的映射。所以启动支持SDP的Java 7 VM时,还是要使用基础、可靠的IPv4网络格式。
调试SDP
通过-Dcom.sun.sdp.debug
标记允许输出调试信息,如果指定了日志文件,则输出到该文件,否则输出到标准输出。
java -Dcom.sun.sdp.conf=sdp.conf -Dcom.sun.sdp.debug ExampleApplicaton
BIND to 192.0.2.1:5000 (socket converted to SDP protocol)
CONNECT to 129.156.232.160:80 (no match)
CONNECT to 192.0.2.2:80 (socket converted to SDP protocol)
或
java -Dcom.sun.sdp.conf=sdp.conf -Dcom.sun.sdp.debug=debug.log ExampleApplication
SDP的技术问题
IPv4地址是32位的,以十进制格式书写,用句点(.)分隔。IPv6是128位的,以十六进制格式书写,用冒号(:)分隔。
IPv4地址不能用在IPv6里,但IPv6确实支持一类特殊地址:IPv4-mapped地址。
在IPv4-mapped地址里,前80位设置为0,接下来16位设置为1,最后的32为表示IPv4地址。
例如:
IPv4 address IPv4-mapped address (for use in IPv6)
192.0.2.1 ::ffff:192.0.2.1
默认是,如果IB适配器支持IPv6,Java平台就可以使用IPv6。但当前Solaris和Linux 系统不支持IPv4-mapped地址。由于这个原因,应该在JDK 7下使用这个配置 -Djava.net.preferIPv4Stack=true
来使用IPv4。
支持的Java API
java.net package
Socket
ServerSocket
java.nio.channels package:
SocketChannel
ServerSocketChannel
AsynchronousSocketChannel
AsynchronousServerSocketChannel
当SDP支持允许时,不需要对代码做任何修改就可以工作,编译也是不必要的。
注意:一个套接字只绑定一次。一个连接是隐式绑定的。如果套接字之前没有进行绑定,在connect
调用时进行绑定。
对于下面的代码片段:
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
ch.bind(local);
Future<Void> result = ch.connect(remote);
在bind
被调用时,异步套接字通道被绑定到本地的一个TCP地址上,代码用这个套接字尝试连接远程地址,如果远程地址使用 InfiniBand,连接将不会转换到SDP,因为套接字之前已被绑定过。
SDP RDMA 图示
借助Java到RDMA的连接点,SDP也能让Java具备非常有力的“零拷贝”能力。“零拷贝”操作指CPU不用将一个内存区域的数据拷贝到另一个内存区域。
- Java 7应用Node 1(JVM启动时使用SDP)使用java.net.Socket API把应用数据块跨网络写给java.net.ServerSocket监听器。
- JVM启动时使用SDP,所以会完全绕过操作系统的TCP/IP栈——应用数据会直接写到InfiniBand的RDMA(要求网卡的物理提供者是InfiniBand)。
- Java 7应用Node 2(JVM启动时也使用SDP)使用java.net.ServerSocket API监听应用数据块,应用数据块由java.net.Socket写入者经RDMA跨网络写入。(要求网卡的物理提供者是InfiniBand)
- 数据会直接写入Java 7 VM的应用缓冲区!不需要操作系统或服务调用——既不需要Node 1的操作系统,也不需要Node 2的操作系统。这就是Java 7 SDP的功能。
SDP TCP绕过图示
参考链接
- http://docs.oracle.com/javase/tutorial/sdp/index.html
- http://www.infoq.com/cn/articles/Java-7-Sockets-Direct-Protocol
欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。