Session引入
NFS4仅支持单服务器,并且客户端和服务器只有一个连接。这意味着客户端不能并发访问服务器数据。同时NFS4虽然支持EOS(Exactly Once Semantics),但存在重大设计缺陷。NFS4.1有两个主要目标:1)修正NFS4的一些重大设计缺陷; 2) 提高并发访问能力。
为此NFS4.1引入一个重大的设计:session。Session的引入是为了解决下面几大问题:
1) 支持EOS(Exactly Once Semantics)
2) 支持回调;
3) 支持trunking(中继)的并发访问
4) Requiring machine credentials for fully secure operation.(这个不谈)
Session建立
当客户端启动后,通过EXCHANGE_ID获取相应的服务器(scope)分配的clientid。紧接着,通过CREATE_SESSION建立特定的session,并向服务器确认clientid。EXCHANGE_ID和CREATE_SESSION取代了NFS4的SETCLIENTID和SETCLIENTID_CONFIRM。
Session,通道(channal),连接(connection)
NFS4.1所有的客户端操作均基于session。每个客户端可有多个session,session可以连接不同的server。每个session最多可以有两个通道(channal): 前端通道和后端通道。每个通道可以拥有多个连接(connection),每个连接的类型可以不同。
客户端发起的请求走前端通道,后端通道作为服务器端的回调通路。Session的请求均基于COMPOUND命令,每个COMPOUND命令可以组合多个操作,完成一组复杂的命令。
中继(trunking)
中继是为了加快数据传输,其本质就是利用位于同一组client和server的多个连接进行并发数据传输。
Session中继:一个客户端可以有多个session,一个session可以有多个连接。客户端和服务器均可以有多个网卡(interface),这意味着同一组客户端和服务器之间的连接其目标地址和源地址均是可以不同的。Session中的connection是否可用于中继传输,最本质的就是判断此连接是否是同一组客户端和服务器的连接。
Clientid中继:在NFS4.1中,多个服务器可以位于同一台机器,及一组服务器拥有同样的资源(集群,共享磁盘),均可为所有客户提供同样的数据。每个clientID唯一表示同一个client。一个client可以拥有多个session。故Clientid 中继只需session位于同样的client和server间即可。
EOS
NFS4可提供EOS保证,但存在设计缺陷。NFS4通过让每个状态请求携带序列号并缓存此类请求的响应,基于此保证EOS。这意味着每个状态请求必须有一个缓存响应的空间。每个客户端的状态可以是无限的,这将极大的浪费服务器的内存空间。故NFS要求客户端限定只能有一个未收到响应的状态请求。这避免浪费内存空间,但极大限制了NFS的并发请求。本质上,序列号和响应缓存只有在客户端未收到响应之前才是有效的,收到响应之后,序列号和缓存就已经没有存在的意义。
NFS4.1同样采用序列号+缓存响应(response)的机制保证EOS,同时共享session内的缓存空间。在客户端建立session时,将同时设置最大的缓存空间,请求大小,response大小等参数。所有的客户端操作均基于特定session,每个操作均携带序列号和slot ID(缓存槽)。服务器在发回响应之前,将响应基本信息或全部信息存于缓存槽。若客户端正确收到响应,则该缓存槽将可用于其他操作。本质:服务器可共享缓存槽。客户端必须控制未收到响应的操作数(不能大于slot数量)。
重用缓存槽还有另一个额外好处,服务器可知道客户端是否收到响应。只要缓存槽被重用,即说明客户端已经收到响应!
每个slot都有自己的序列号。客户端需要记录每个slot的状态:当前序列号,是否可用(是否已收到响应)等。服务器通过判断请求的序列号与当前槽的序列号可判断请求是否有效。槽序列号由客户端维护。槽的大小可调整,故客户端可同时发起无数个请求(理论上)。NFS4.1要求所有的请求都需要携带序列号。
Server Callback Races
有些请求可引发callback,callback可能比相应请求更先被客户端收到。Client必须能够正确处理callback race。
每个客户端请求可通过三元组标识: session ID, slot ID, sequence ID。此三元组将被缓存于slot中,server能够知道其响应是否已经被客户端收到:slot是否被重用。在slot未被重用之前,该请求所引发的callback均需要返回 session ID, slot ID, sequence ID 三元组给客户端。客户端根据此三元组可知道callback是否比响应更早达到客户端。若callback更早到达,则该callback应被推迟处理;因不能无限推迟,故在一段时间后,若请求的响应还未达到,该callback被忽略。
注:规范上的细节非常多,这里仅给出概括。
参考: rfc5661