在集群环境中为了使集群中各个节点的会话状态都同步,同步操作是集群重点解决的问题,一般来说有两种同步策略,其一是每次同步都把整个会话对象传给集群中其他节点,其他节点更新整个会话对象;其二是对会话中增量修改的属性进行同步。这两种同步方案各有优缺点,整个会话对象同步策略实现过程比较简单方便,但会造成大量无效信息的传输。增量同步方式则不会传递无效的信息,但在实现上会比较复杂因为涉及到对会话属性操作过程的管理。
这节讨论的正是增量同步方式中涉及的会话对象DeltaSession,这个对象其实是对标准会话对象的扩展使之具备在整个请求过程记录会话所有的增量更改。DeltaSession的类图如下,除了继承StandardSession类外还实现了Externalizable、ClusterSession、ReplicatedMapEntry三个接口,Externalizable接口主要提供对外部的对象读写操作,ClusterSession接口主要提供判断集群会话是否为原始的会话操作,只有原始会话才有资格使会话过期,ReplicatedMapEntry接口提供差异复制的操作。对于DeltaSession其实就是除了继承StandardSession特性外还要额外实现这三个接口。
当客户端发起一个请求时,服务端对请求的处理可能涉及会话相关的操作,例如获取客户端某些属性再根据属性值进行逻辑处理,而且在整个请求过程中可能涉及多次的会话操作,为了将这些改变能同步到集群的其他节点上,必须要有一个机制来实现,实际上同步的颗粒度大小是很重要,颗粒度太大会导致同步不及时,而颗粒度太小则可能导致传输及性能问题,考虑到性能及可行性,tomcat同步的颗粒度是以一个完整的请求为单位的,即从客户端发起请求到服务器完成逻辑处理返回结果之前这段时间为同步颗粒度。这个过程中对某会话的所有操作(对同一个属性的操作只记录最新的操作)都会被记录下来,如下图,绿色箭头表示一个完整的请求过程,期间包括了四个修改属性操作,分别修改了属性a、b、c、d,这四个操作会被抽象成四个动作放进一个列表中,集群其他节点获取列表后根据这些动作就可以对自己本地对应的会话进行同步。
集群成员接收到某节点发送过来的同步消息后,将会逐一执行动作集里面的每个动作,下图大箭头表示同步的整个过程,最下面的为动作集列表,一共有4个动作,按顺序首先取出第一个update1动作,动作对象里面包含了指定修改哪个会话的会话id,根据此id去修改会话集对应的会话的属性。接着把剩下的其余3个动作执行完毕,于是完成了会话同步。
在tomcat中会话增量的具体由DeltaSession类实现,DeltaSession继承了StandardSession标准会话的所有特性且增加了会话增量记录的功能,增量记录功能即通过动作集实现,动作集被封装在DeltaRequest类,所以DeltaSession主要通过DeltaRequest实现动作集的管理,动作集由一个LinkedList<AttributeInfo>结构保存,AttributeInfo描述了动作的一些消息,所以一个动作就被抽象成了一个AttributeInfo对象,它主要包含四个属性 name(String)、value(Object)、action(int)、type(int),name表示会话的属性名,即哪个属性被改;value表示会话属性名对应的值;action表示动作类型,可能是设置属性也可能是删除属性;type表示会话哪种类别的属性将被修改。
整个增量会话的实现机制就是上面所说的,会话的增量拷贝比起全量拷贝有很多好处,即使实现相对比较复杂。