第 6 章 Web 应用程序中的集群

6.1. 会话复制

6.1.1. 关于 HTTP 会话复制

会话复制可确保集群中节点的故障切换不会破坏可分布式应用的客户端会话。群集中的每个节点共享有关持续会话的信息,并在节点消失时接管会话。

会话复制是 mod_cluster、mod_jk、mod_proxy、ISAPI 和 NSAPI 集群提供高可用性的机制。

6.1.2. 在应用程序中启用会话复制

若要利用 JBoss EAP 高可用性(HA)功能并启用 Web 应用的集群,您必须将应用配置为可分布。如果您的应用未标记为 distributable,则永远不会分发其会话。

使应用程序可分发
  1. 在应用程序的 web.xml 描述符文件的 < web-app> 标签中添加 < distributable/> 元素

    示例:可分布式应用程序的最小配置

    <?xml version="1.0"?>
    <web-app  xmlns="http://java.sun.com/xml/ns/j2ee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                                  http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd"
              version="3.0">
    
          <distributable/>
    
    </web-app>

  2. 接下来,如果需要,修改默认的复制行为。如果要更改影响会话复制的任何值,您可以在 应用程序的 WEB -INF/jboss-web.xml 文件中的 <jboss-web> 元素 覆盖它们。对于给定元素,仅在您想要覆盖默认值时包含它。

    示例:& lt;replication-config> Values

    <jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_10_0.xsd">
       <replication-config>
          <replication-granularity>SESSION</replication-granularity>
        </replication-config>
    </jboss-web>

<replication-granularity> 参数决定复制数据的粒度。它默认为 SESSION,但可以设置为 ATTRIBUTE,以提高大多数属性保持不变的会话的性能。

<replication-granularity> 的有效值可以是 :

  • SESSION :默认值。如果任何属性为脏属性,则会复制整个会话对象。如果对象引用由多个会话属性共享,则需要此策略。共享对象引用在远程节点上维护,因为整个会话都以一个单元序列化。
  • ATTRIBUTE :这仅适用于会话中的脏属性和某些会话数据,如最后一次访问的时间戳。
不可变会话属性

对于 JBoss EAP 7,会话更改或会话的任何可变属性访问时会触发会话复制。会话属性会被假定为可变,除非以下条件之一为 true:

  • 该值是一个已知的不可变值:

    • null
    • java.util.Collections.EMPTY_LIST,EMPTY_MAP,EMPTY_SET
  • 值类型是或实现一个已知的不可变类型:

    • Java.lang.Boolean, Character,Byte,Short,Integer,Long,Float,Double
    • java.lang.ClassnumStackTraceElementString
    • java.io.File,java.nio.file.Path
    • java.math.BigDecimal, BigInteger, MathContext
    • java.net.Inet4Address, Inet6Address, InetSocketAddress, URI, URL
    • java.security.Permission
    • java.util.Currency,Locale,TimeZone,UUID
    • Java.time.Clock,Duration,Instant,LocalDate,LocalDateTime,LocalTime,MonthDay,Period,Year,YearMonth,ZoneId,ZoneOffset,ZonedDateTime
    • java.time.chrono.ChronoLocalDate, Chronology, Era
    • java.time.format.DateTimeFormatter, DecimalStyle
    • java.time.temporal.TemporalField, TemporalUnit, ValueRange, WeekFields
    • java.time.zone.ZoneOffsetTransition, ZoneOffsetTransitionRule, ZoneRules
  • 值类型带有以下注解:

    • @org.wildfly.clustering.web.annotation.Immutable
    • @net.jcip.annotations.Immutable

6.1.3. 会话属性 marshalling

通过减少通过网络发送的字节数或保留到存储的字节数,最小化单个会话属性的复制或持久性有效负载可能会直接提高性能。通过使用 web 应用程序,您可以使用以下方法优化会话属性的总结:

  • 您可以自定义 Java Development Kit(JDK)序列化逻辑。
  • 您可以实施自定义外部化器。

externalizer 实施 org.wildfly.clustering.marshalling.Externalizer 接口,用于指定类的 marshalling。外部化器不仅会直接从对象读取或写入输入/输出流,还执行以下操作:

  • 允许应用程序在未实现 java.io.Serializable的会话中存储对象
  • 消除序列化对象类描述符及其状态的需要

    示例

    public class MyObjectExternalizer implements org.wildfly.clustering.marshalling.Externalizer<MyObject> {
    
        @Override
        public Class<MyObject> getTargetClass() {
            return MyObject.class;
        }
    
        @Override
        public void writeObject(ObjectOutput output, MyObject object) throws IOException {
            // Write object state to stream
        }
    
        @Override
        public MyObject readObject(ObjectInput input) throws IOException, ClassNotFoundException {
            // Construct and read object state from stream
            return ...;
        }
    }

注意

服务加载器机制会在部署过程中动态加载外部化器。实施必须在名为 /META-INF/services/org.wildfly.clustering.marshalling.Externalizer 的文件中进行枚举。