跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

IBM WebSphere 开发者技术期刊: 更新 WebSphere Application Server 企业应用程序时保持持续可用性

Peter Van Sickel (pvs@us.ibm.com), IT 咨询专家, IBM Software Services for WebSphere
Author photo
Peter Van Sickel 是 IBM Software Group WebSphere 分公司的 IBM Software Services 顾问。他的办公室在宾夕法尼亚州匹兹堡,他的主攻方向是 WebSphere Application Server、操作及执行。

简介: 本文描述了在希望保持应用程持续可用性的产品环境中,推出企业应用程序的新版本的方法。并讨论了基于浏览器的客户端及基于 Java™ 的客户端的应用程序。

发布日期: 2004 年 12 月 01 日
级别: 初级
访问情况 : 1320 次浏览
评论: 


引言

本文详细描述了在 IBM WebSphere® Application Server Network Deployment Version 5.x 单元中将 J2EE™ 企业应用程序的新版本迁移到产品中,同时保持站点的持续可用性。并介绍了使用两种不同方式执行应用程序更新的步骤,其中一个是使用多 WebSphere 单元,另一个是使用单 WebSphere 单元。每个方法都有其优缺点,在产品设置中经常结合使用这两种方法,所以理解这两个方法是有益处的。某些 WebSphere 运行时体系结构和 HTTP 插件配置文件结构的背景信息将为迁移过程创造条件。

本文假设您已经熟悉 IBM WebSphere Application Server V5.x 及 J2EE 企业应用程序。

对基于浏览器的客户端,过程利用了通过修改 plugin-cfg.xml 文件来操作 HTTP 服务器插件程序路由表的能力。插件程序的会话亲缘性特征帮助将现有用户路由到当前版本的应用程序服务器,同时新用户被路由到运行应用程序新版本的应用程序服务器。随着新版本的开始使用,使用 plugin-cfg.xml 文件服务器元素的 LoadBalanceWeight 属性可以平稳地“排除”离线服务器。

当考虑将应用程序从一个版本迁移到另一个版本时,取决于版本之间更改的多少,可能会引发几个问题。需要特别注意的是:

  • 数据库模式的兼容性
  • 正在进行的迁移
  • 用户体验的考虑
  • EJB 版本的兼容性。

这些方面的考虑对版本迁移计划和执行产生的影响,也许会大于推出应用程序到产品服务器的机制产生的影响。这些方面不在本文的范围之内,这里假设这些问题已经通过向后兼容或通过独立于应用程序推出的步骤得以适当的解决。

简单起见,我们将假设应用程序服务器只运行待移植的应用程序。实际上,应用程序服务器通常运行不只一个应用程序。假设服务器集群运行应用程序 A,B,C。推荐的方法是每次只移植一个应用程序,如应用程序 A。当然,开发的测试阶段包括一套的测试来保证应用程序 A 的新版本(及其支持的所有的库)与应用程序 B 和 C(及他们支持的库)是兼容的。如果在实际上是不可能的,那么这个移植将需要另外的应用程序服务器集群来运行应用程序 A 的新版本。这通常需要附加硬件设备。

如果产品环境被配置用来使用持续的 HTTP 会话状态,那么就会有出现错误的情形(希望可能性会小些):运行应用程序版本 N 的应用程序服务器可能访问应用程序 N+1 版本的 HTTP 会话状态,反之亦然。假设运行应用程序版本 N 的服务器有出现错误,而随后的请求恰巧被传递到运行应用程序版本 N+1 的应用程序服务器上。如果对象类定义阻止 HTTP 会话状态从应用程序的一个版本改变到另一个版本,那么当会话状态被反串行化时将会抛出 java.io.InvalidClassException。当抛出此异常时应用程序应当适当的做些什么。在这种情况下需要做的最好的事情可能是要求用户重新登录或将用户重定向到起始页,这样就会创建新的会话,这样也会使用户回到运行应用程序新版本的服务器上或其他什么地方。另一方面,如果在迁移过程中有问题发生,那么立即回滚应用程序版本 N+1,并恢复站点到所有应用程序版本为 N 的服务器上。

我们将假设应用程序回滚只会花费相对较短的时间,如最多两个小时。如果回滚周期很长(换句话说,就是推出的时间长到同一用户访问站点并建立了一个以上新的会话),那么很有可能的是对移植所考虑的“用户体验”其中一项是在推出期间需要确保已经看到应用程序新版本的用户在其后来访问的站点上也看到新版本。如果用户已经使用了应用程序的新版本,您可能也不希望用户重新使用老版本。在扩展的过渡时期可能发生上述情况,因为服务器将会运行应用程序的 N 和 N+1 版本。这就需要某些机制,来持久的保持用户应该被导向应用程序版本的哪个版本,如用户概要数据库。当然,这也是在假设所有用户在访问站点时表明自己的身份(例如,通过登录),同样也需要某些机制将用户导向到运行他们的版本的服务器。(创建覆盖这个场景的应用程序的细节超出了本文的范围。)这个扩展的迁移场景与本文包含的快速迁移场景完全不同。在扩展的迁移场景中,应用程序的多个版本会保持长期的运行,通常是当培训用户使用新版本时,某些用户会选择使用以前的版本而同时另一些用户会使用新版本。


WebSphere Application Server 体系结构的背景知识

WebSphere Application Server V5.x 的一个重要特性是定义服务器集群的能力。服务器集群中的服务器服务于相同的应用程序。集群的每台服务器都得到分配给他的唯一的克隆 ID,该 ID 被加在会话 cookie 的末尾。HTTP 插件检查会话 cookie 并使用克隆 ID 来确保属于相同会话的请求会返回到相同的服务器,这个就被称为会话亲缘性。

载入的新用户发出的初始请求通过一个简单的循环策略,均衡到集群中的服务器。每个服务器都有 LoadBalanceWeight 属性,可以使用该属性静态的优先选择集群中特定的服务器。如果集群所有的成员有相同的 LoadBalanceWeight,那么他们将平均分配负载。如果某服务器的 LoadBalanceWeight 被设置为 0,那么只有已经与在那个服务器上的会话关联起来的请求才发送给他。(已经将该服务器从处理新会话的服务器池取出。)当发生应用程序版本更新时这是有用的,因为它确保用户在他(她)的会话生命周期内将继续由相同的应用程序版本来服务,由于所有的请求都回到相同的应用程序服务器中。更进一步,这也确保为应用程序旧版本服务的应用程序服务器最终不会再有任何活动的会话。(所有活动会话结束所需要的时间依赖于应用程序的用例场景。)

WebSphere HTTP 插件读取 plugin-cfg.xml 文件来确定何种应用程序与何种应用程序服务器集群关联以并且构建相应的路由表。插件周期性的重读 plugin-cfg.xml 文件,这样就不需要为插件停止并重新启动 HTTP 服务器来检查在 plugin-cfg.xml 文件中何时有更改。(默认的刷新间隔是一分钟,但是可以根据在 plugin-cfg.xml 文件中定义的属性来重新配置。)

某些与应用程序更新相关的集群的关键特性包括:

  • 所有集群成员必须是相同单元的成员。
  • 应用程序不能安装在集群的单独成员上。(有可能关闭自动节点同步并使用手工同步来使管理员在某一时刻在集群成员上安装应用程序,但是这经常超出单元操作过程的计划,而且并不推荐使用这类“窍门”。)
  • 应用程序服务器,集群的成员,被分配给唯一的标识符,称作克隆 ID。在服务器存在自始至终克隆 ID 并不会改变而且是唯一的。

图 1 说明了三个节点的集群(称作 ClusterX)的使用,用来处理一组 HTTP 服务器发出的请求。


图 1.在 WebSphere 单元中定义的服务器集群
图 1.在 WebSphere 单元中定义的服务器集群

为避免图表混乱,只显示一套箭头,代表从一组 HTTP 服务器到应用程序服务器集合的请求。与应用程序服务器关联的号码:9081、9082 及 9083 代表 Web 容器监听端口。

回滚场景

任何推行计划都要重点考虑制定一个很好的回滚计划。好的回滚计划具有如下重要特征:

  • 不需要具备卸载/安装环节,这可能有潜在的错误并可能持续很久。
  • 不需要服务器启动,避免这点是要避免服务器启动需要的时间。
  • 回滚过程需要简单的切换操作。例如,在 IP 发射器路由表中或 plugin-cfg.xml 中改变入口点。

如果您的组织有严格的测试流程且您的测试小组提供时间及资源,在模拟负载环境中(可以精确的反应产品负载)做功能及负荷测试,那么应用程序新版本将会顺利的推行到产品中,对么?不尽然。因此,您需要回滚计划,且该计划需要进行测试。当应用程序新版本被提交到产品负载,某些潜伏的问题可能会被发现,这样就需要回滚。在本文中描述的推行过程满足回滚计划的这些特征,使得它可以快速、容易的进行回滚。


多单元方法

某些站点使用多单元配置,因为它有很好的容错的特性。多单元配置也使得应用程序更新相对简单。为简化本文中的解释,只使用两个单元,称他们为:单元 X 及单元 Y。

在非常巨大的多单元配置范围内,有可能有单独的 HTTP 服务器组,每个单元一个,每个 HTTP 服务器组专有地为一个单元中的服务器的请求服务。(参见图 2)在此种情况下,有必要用 IP 发射器完成会话亲缘性。IP 发射器(例如 WebSphere Load Balancer)可以将它所指向的事物作为基于路由的内容,使用拥有克隆 ID 的 WebSphere Application Server 会话 cookie 发送:

  • 所有在单元 X 中意欲给服务器到与单元 X 相关联的 HTTP 服务器的请求。
  • 所有在单元 Y 中意欲给服务器到与单元 Y 相关联的 HTTP 服务器的请求。

其他厂商的 IP 发射器有相似的方法完成 HTTP 服务器层的粘连性。当您有 HTTP 服务器层的会话亲缘性时,两个单元操作相对独立(除可能共享后端服务器外),这样可以实现完全分离的管理单元。


图 2. 多单元配置
图 2. 多单元配置

中级范围的站点可能只有一组 HTTP 服务器,但仍有多个单元。一组 HTTP 服务器在两个单元中载入交叉服务器的均衡请求。在这种情况下,每个单元的 plugin-cfg.xml 文件需要在一个集群中进行合并(从 HTTP 插件角度来看),即使从 WebSphere Application Server 管理流程的角度来看(每个单元的部署管理员)也有多个集群,每个单元中一个。

在多单元配置中的更新应用程序的详细情况将在下一部分中描述,但要点是从产品中拿出一个单元、在那个单元中安装应用程序的新版本、开始向那个单元发送请求,然后,在经过一些内建时期,使得应用程序新版本可以在产品中独立之后,在其他单元服务器中重复这个回滚过程。这个过程假设在处理回滚时,活动单元中有足够的容量可以处理整个站点的负载。(在两个单元的实例中,去掉一个单元意味着空闲出 50% 的容量,在回滚期这可能主要取决于负载情形。可以将可用的硬件分布在多个单元中,这样在一个单元中离线的容量的百分比就会降低到允许剩下的容量来处理在回滚期的负载。回滚过程本身在概念上还是相同的。)

多单元应用程序回滚

这部分介绍使用多单元配置进行应用程序回滚的步骤。正如在前面所提到的,为简单起见,这里只使用两个单元,但从概念上讲配置多于两个单元的流程与这是一样的。

A. 起始状态

起始状态如下:

  • 单元 X, ClusterX -- 所有服务器运行应用程序版本 N
  • 单元 Y, ClusterY -- 所有服务器运行应用程序版本 N
  • 每个单元中有足够的容量来处理转变期间的全部负载。

B. 开始转变

图 3 说明了转变到应用程序新版本的第一部分:

  1. 重新配置 IP 发射器来发送所有没有与会话(也就是新会话)关联而只与单元 Y 关联的请求。在单元 X 上与现有会话关联的请求继续从 IP 发射器流向到与单元 X 关联的 HTTP 服务器。
  2. 预留出运行于单元 X 上的应用服务器完成用户会话的时间。这通常称为“放弃”应用服务器。一段时间后,单元 X 服务器上的所有活动的会话都将终止。(实际时间的总量是由应用程序确定。)有多种方法可以确定逗留在单元 X 服务器上的活动会话的数量:
    • 使用 Tivoli® Performance Viewer 查看性能监控接口数据。
    • 监控 HTTP 服务器访问日志。
    • 监控 IP 发射器的传输模式。
  3. 在单元 X 应用程序服务器上安装应用程序版本 N+1。
  4. 使用映射到测试虚拟主机上的测试虚拟 IP 测试单元 X 版本 N+1。这是在产品设置中使用轻负荷所做的最后的质量保证测试。实际的负载/压力测试大概要在性能测试环境中进行,至少要模拟产品环境,如果不复制的话。测试结束时,将为 Web 应用程序定义的虚拟主机改为产品虚拟主机。(可以通过 WebSphere Application Server 中的管理控制台中或利用 wsadmin 脚本来完成,要使更改生效需要重新启动应用服务器。)

图 3. 将单元 X 服务器转变为版本 N+1 并测试
图 3. 将单元 X 服务器转变为版本 N+1 并测试

C. 转变为版本 N+1

图 4 演示了这些步骤:

  1. 重新配置 IP 发射器来直接向在单元 X 中运行版本 N+1 的应用程序服务器请求相关联的新会话。在 IP 发射器中的亲缘性将版本 N+1 用户的请求发送回单元 X 中的服务器,这样就可以继续使用相同版本的应用程序。
  2. 仔细监视单元 X 应用服务器,确保产品负载下的正确操作。如果发生故障,停止转换流程。使用 IP 发射器停止额外的到单元 X 请求的流。在单元 X 上重新安装应用程序版本 N,并打开请求流以完全恢复配置。
  3. 一旦您有信心可以在产品中正常操作版本 N+1,重新配置 IP 发射器来停止单元 Y 中直接发送给服务器的新请求。单元 Y 中与现有会话关联的请求继续从 IP 发射器流向与单元 Y 向关联的 HTTP 服务器,这样就不会突然的停止那些会话。
  4. 放弃单元 Y 服务器。
  5. 在单元 Y 服务器上安装应用程序版本 N+1。
  6. 使用虚拟 IP 和测试虚拟主机测试单元 Y。(在安装过程中可能不需要,这取决于您的信心。)完成测试后,将为 Web 应用程序定义的虚拟主机改为产品虚拟主机。
  7. 重新配置 IP 发射器向与单元 Y 相关联的 HTTP 服务器发送请求。

图 4. 使单元 X,版本 N+1 上线,将单元 Y 转变为版本 N+1
图 4. 使单元 X,版本 N+1 上线,将单元 Y 转变为版本 N+1

D. 完成转换

所有单元中的服务器都运行应用程序版本 N+1,所有单元都是活动的。图 5 演示了所有运行应用程序版本 N+1 服务器的完整转换过程。

对于多单元方法:

  • 不需要生成新的 plugin-cfg.xml 或以任何方式更改。路由表会在 IP 发射器中处理,它会比修改 plugin-cfg.xml 文件更加容易管理。
  • 过程相对简单且管理相当好。
  • 需要更多的硬件设备,因为更新硬件设备的某些部分时他们已经被服务所占据。
  • 回退程序包括关闭运行应用程序新版本单元的应用程序服务器的运输流量,非常简单。然而,这需要假设,运行应用程序版本 N 的单元中有足够硬件设备来支持站点。使所有服务器退回到运行版本 N,这会包括在已经转换为版本 N+1 的单元上重新安装应用程序。

图 5. 完成转换。两个单元都运行版本 N+1
图 5. 完成转换。两个单元都运行版本 N+1

单一单元方法

许多站点只运行一个单元。在单一单元配置中,您仍可以使用多集群来完成应用程序回滚,同时保持连续的可用性。该方法的本质是运行一套活动集群及一套静止的(停止的)集群。在本实例中,为简单起见,我们只使用两个集群。这些集群名为 ClusterX 及 ClusterY,分别拥有成员服务器 X1、X2、X3 及 Y1、Y2、Y3。在应用程序版本 N+1 回滚期间,静止的集群被唤醒、被测试及上线,而运行应用程序版本 N 的服务器集群离线,且当所有在那些服务器上的会话停止时,他们就会关闭。

在两个集群(活动及静止的)集合中的服务器都定义在相同的硬件设备上。使用的硬件设备需要有足够的能力来运行负载运输、活动服务器还有即将转变为活动状态过程中的服务器。基本上,这意味着要有足够的内存使所有的 JVM 能同时运行而不用分页。在线服务器的 CPU 的利用将会等待新会话被发送给应用程序新版本。运行应用程序旧版本服务器的 CPU 利用当现有会话结束时应当也结束。

HTTP 插件配置文件

要理解转换过程的详细信息,您需要有一些插件配置文件方面的背景知识。

插件配置文件中有趣的东西是 ServerCluster 元素。下面是一个显示用于 ClusterX 的集群元素的例子(已经修改用来只显示相关属性及元素,并与本文空间巧妙的结合)。插件基于集群成员定义将传输路由给服务器集群,如清单所示。如果 plugin-cfg.xml 文件的范围是整个单元(通常情况),在每个定义于单元中的集群中都有一个单独的 ServerCluster 元素。HTTP 插件没有关于目标服务器或目标应用程序对那些服务器而不是在插件配置文件中定义的服务器的映射信息。所以即使服务器集合是在 WebSphere 单元中定义为两个独立的集群,从插件的角度来看在一个集群中定义他们也是一件容易的事情。只是要修改 ServerCluster 元素,使它包含其它集群中的服务器即可。这就是所要做的无缝转换,从运行应用程序版本 N 的服务器集群转换为运行应用程序版本 N+1 的服务器集群。

清单 1. Cluster X 集群元素

<ServerCluster LoadBalance="Round Robin" Name="ClusterX">
   <Server CloneID="v7oe1ii4" LoadBalanceWeight="2" Name="ServerX1">
     <Transport Hostname="test1.ibm.com" Port="9081" Protocol="http"/>
   </Server>
    <Server CloneID="v7oe1j1e" LoadBalanceWeight="2" Name="ServerX2">
      <Transport Hostname="test2.ibm.com" Port="9082" Protocol="http"/>
    </Server>
    <Server CloneID="v7oe1k2f" LoadBalanceWeight="2" Name="ServerX3">
      <Transport Hostname="test3.ibm.com" Port="9083" Protocol="http"/>
    </Server>
    <PrimaryServers>
      <Server Name="ServerX1"/>
      <Server Name="ServerX2"/>
      <Server Name="ServerX3"/>
    </PrimaryServers>
</ServerCluster>

服务器元素有一个 CloneID 属性,在前面提到过。这个值是在应用服务器中 Web 容器创建的会话 cookie 的一部分。每个请求都有一个会话 cookie,插件从 cookie 值中解析出克隆 ID 并使用它将请求发送回服务器,那台服务器的会话是活动的。

plugin-cfg.xml 文件另外一个重要的细节是服务器元素的 LoadBalanceWeight 属性。正如前面所提到的,这个属性用来静态的分配与集群中服务器的(新)请求循环分布相关联的权重因素。为本文的目的,要记住 LoadBalanceWeight 的一件重要事情是它何时被置为 0,这是插件停止向应用服务器(即将离线)发送新请求的信号。这使得管理员可以温文地关闭服务器。那台服务器上与现有会话相关联的请求将会继续流向它,但是当这些会话终结时(由于用户显式的推出或由于会话过期),服务器会及时的不再拥有任何活动的会话。(使用轻量 PMI 设置及 Tivoli Performance Viewer 监视服务器中活动会话的数量。)

plugin-cfg.xml 文件中使用其它的元素来映射应用程序 URI 到为他们服务的集群。下面描述了这些元素。

清单 2. Plugin-cfg 映射元素

<UriGroup Name="prod_vhost_ClusterX_URIs">
        <Uri AffinityCookie="JSESSIONID"
            AffinityURLIdentifier="jsessionid" Name="/user/*"/>
</UriGroup>
<Route ServerCluster="ClusterX"
        UriGroup="prod_vhost_ClusterX_URIs" VirtualHostGroup="prod_vhost"/>
<UriGroup Name="test_vhost_ClusterY_URIs">
        <Uri AffinityCookie="JSESSIONID"
            AffinityURLIdentifier="jsessionid" Name="/user/*"/>
</UriGroup>
<Route ServerCluster="ClusterY" UriGroup="test_vhost_ClusterY_URIs"
          VirtualHostGroup="test_vhost"/>

  • UriGroup -- 这个元素列举给定应用程序的 URL。通常 URL 是由上下文根及星号所定义(如清单 2 所示),与 URL 以那个上下文根开始的其余部分向匹配。这个特殊的例子显示有两个运行的应用程序,他们有相同的上下文根“user.”。这个潜在的混淆由 Route 元素来解决。
  • Route -- 这个元素将 UriGroup 映射到 VirtualHostGroup 和 ServerCluster。在本实例中,有两个有相同上下文根的 URL 组,每个都使用不同的 VirtualHostGroup,“prod_vhost”以及“test_vhost”。这意味着全 URL 在 URL 的主机名及端口部分中将不同。有“prod_vhost”的 URL 将发送给 ClusterX 中的服务器,有“test_vhost”的 URL 将发送给 ClusterY 中的服务器。(这个例子是从转换阶段的 plugin-cfg.xml 文件中截取出来的,在 ClusterX 中的服务器为应用程序版本 N 产品服务,在 ClusterY 中的服务器运行应用程序版本 N+1,并通过虚拟 IP 映射到“test_vhost”进行测试。)

单一单元,多集群转换过程


图 6. 单一单元,两个集群配置
图 6. 单一单元,两个集群配置

A. 开始状态

下面是开始状态的描述,如图 6 所示:

  1. ClusterX 中的服务器是活动的且运行应用程序版本 N。
  2. ClusterY 中的服务器已经关闭。
  3. plugin-cfg.xml 中的路由表只列出了 ClusterX 中用于处理请求的候选成员。
  4. 定义了两个虚拟主机:
    • 一个叫做“prod_vhost”,用于运行在活动集群上的应用程序产品版。
    • 一个叫做“test_vhost”,用于测试应用程序新版本,该应用程序将运行在最后测试阶段的静止集群上。需要为“test_vhost”分配一个测试虚拟 IP 地址,这样测试人员就可以使用它了。

B. 开始转换

下面的步骤描述了转换状态,如图 7 所示:

  1. 在 ClusterY 上安装应用程序版本 N+1:
    1. 为方便管理员,指定应用程序的名称,该名称包括版本号。
    2. 设置 Web 应用程序虚拟主机为“test_vhost”。(在安装期间使用管理控制台或 wsadmin 脚本完成此项操作。)
    3. 倾斜出新的 plugin-cfg.xml 文件。其中将定义两个集群和两个版本的应用程序。每个 Web 应用程序的根上下文是相同的。因为使用了两个不同应用程序版本的虚拟主机,路由表将被分离出来。
    4. plugin-cfg.xml 文件复制到 HTTP 服务器中。HTTP 服务器将以在文件内部定义的刷新时间间隔自动重新装载 plugin-cfg 文件的新版本。
  2. 为了测试唤醒静止集群或某些服务器的子集。在产品配置中运行应用程序新版本的轻量级测试。这是确保正确配置及请求发送的最后测试。这些服务器与产品服务器共享硬件设备积极的处理负载,因此运行重量级测试负载就不是一个好主意。

图 7. 开始转换到版本 N+1
图 7. 开始转换到版本 N+1

C. 插件配置文件详细描述

在流程的这个阶段,HTTP 服务器使用的 plugin-cfg.xml 文件与由 WebSphere GenPluginCfg 脚本或管理控制台生成的一样。其中定义了两个服务器集群、两个虚拟主机及两个 URI 组,每个都是相同的 URI 模式,但是每个都使用不同的路由,这是由于一个使用 prod_vhost 而另一个使用 test_vhost。

D. 转换到版本 N+1

关于有多少节点要转换不尽相同。如果您只想测试在产品负载下的运行应用程序新版本的服务器,您可以只对一个节点进行转换。如果您对应用程序新版本充满信心,或如果您正在操作多个集群,可以在某一时刻在集群中转换所有的节点。转换集群中的所有节点的一个特性是运行应用程序新版本的故障切换(failover)服务器的有效性。依赖于所包含服务器的数量,您可能希望以组的形式转换他们,比如大约 5 个。在第一组转换为活动状态后并运行一段时间,证明应用程序新版本可以独立于产品负载下,您可能会更快的转换剩余的服务器:

  1. 修改应用程序版本 N+1 的虚拟主机映射,这样它可以使用产品虚拟主机:prod_vhost。需要重新启动 ClusterY 服务器来获得虚拟主机中的改变。
  2. 将版本 N+1 服务器(ClusterY)从静止集群移动到活动集群(ClusterX)中:
    1. 将在这个描述中所指的持有两个活动服务器的节点(一个运行应用程序版本 N,另外一个运行应用程序版本 N+1)作为转换节点。所描述的集群的所有三个成员同时转换。
    2. 需要按如下清单 3 所描述的那样修改 plugin-cfg.xml 文件。在我们的实例中,将 ClusterY 中的服务器转移到 ClusterX 中。
    3. 将 ClusterX 服务器的 LoadBalanceWeight 设置为 0,这样插件就不会向他们发送任何更多的请求,因为他们已与会话无关。这些服务器将只接收与现有会话相关联的请求,现有会话与那些服务器通过会话密切性联系在一起。
  3. plugin-cfg.xml 文件复制到 HTTP 服务器上。一旦 HTTP 服务器插件重新读取这个 plugin-cfg.xml 的最新副本,路由表将包括服务器产品集合中的 ClusterY 服务器(运行应用程序版本 N+1)。(参阅清单 3。)没有与活动会话关联的请求("新"请求)将会以通常的循环方式发送给 ClusterY 服务器。

E. 插件配置文件详细描述

在这点上,在 plugin-cfg.xml 文件中用于 ClusterX 的 ServerCluster 元素与清单 3 相似。对 ClusterX 中所有实际成员的 LoadBalanceWeight 都设置为 0。ClusterY 的所有实际成员都已经转移到 ClusterX 元素中且都有一个正的 LoadBalanceWeight。在清单中没有显示的是实际已经安装在 ClusterY(应用程序版本 N+1)上的应用程序的 UriGroup 及 Route 元素,已经将他们从 plugin-cfg.xml 文件中移除了。另外,ClusterY 的 ServerCluster 元素也已移除。

清单 3

<ServerCluster LoadBalance="Round Robin" Name="ClusterX">
  <Server CloneID="v7oe1ii4" LoadBalanceWeight="0" Name="ServerX1">
    <Transport Hostname="test1.ibm.com" Port="9081" Protocol="http"/>
  </Server>
  <Server CloneID="v7oe1j1e" LoadBalanceWeight="0" Name="ServerX2">
    <Transport Hostname="test2.ibm.com" Port="9082" Protocol="http"/>
  </Server>
  <Server CloneID="v7oe1k2f" LoadBalanceWeight="0" Name="ServerX3">
    <Transport Hostname="test3.ibm.com" Port="9083" Protocol="http"/>
  </Server>
  <Server CloneID="v7oe3bhc" LoadBalanceWeight="2" Name="ServerY1">
    <Transport Hostname="test1.ibm.com" Port="9181" Protocol="http"/>
  </Server>
  <Server CloneID="v7oe3c36" LoadBalanceWeight="2" Name="ServerY2">
    <Transport Hostname="test2.ibm.com" Port="9182" Protocol="http"/>
  </Server>
  <Server CloneID="v7oe4cu8" LoadBalanceWeight="2" Name="ServerY3">
    <Transport Hostname="test3.ibm.com" Port="9183" Protocol="http"/>
  </Server>
  <PrimaryServers>
      <Server Name="ServerX1"/>
      <Server Name="ServerX2"/>
      <Server Name="ServerX3"/>
      <Server Name="ServerY1"/>
      <Server Name="ServerY2"/>
      <Server Name="ServerY3"/>
  </PrimaryServers>
</ServerCluster>

F. 转换完成

在最后阶段,ClusterX 的成员已经关闭。(他们一直运行到停止且确信不再需要回滚。)

对于单一单元,多集群方法:

  • 有效利用可用的硬件设备,因为您不能依靠硬件设备的某些部分支持站点的全部负载。
  • 有一些与 plugin-cfg.xml 文件有关的稍微复杂的管理“欺骗”。
  • 有好的回滚过程,因为在您要回滚到的所有应用服务器上,仍然安装了应用程序版本 N。回滚过程包含使用开始阶段的 plugin-cfg.xml 文件版本。

主题的变化

现在您已经看到了应用程序回滚的多单元及单一单元方法,您可以想象潜在的变化会使流程比这里所描述的更加适合您的特定情形。

多单元中只有一个变化这种方法是为两个单元使用相同的物理硬件设备,一个单元处于活动状态,另一个单元处于静止(停止)状态。这里只是总结一下这个回滚过程,但它与在前面提及过的单一单元,多集群方法很相似,与操纵 plugin-cfg.xml 文件有关。在回滚期,静止单元被唤醒,并且在上面安装应用程序的新版本。可以通过合并两个单元所插件配置文件来完成测试,使用两个集群(每个单元一个集群),但是对于应用程序版本 N+1 使用测试虚拟主机和虚拟 IP 地址。使用这种方法,需要足够多的硬件设备来支持回滚期间的两个节点代理和并行运行的每台机器上的两个应用服务器。转换期包括构建与两个单元中的服务器合并的 plugin-cfg.xml 文件,该文件被定义为单一集群元素的一部分,设置版本 N 服务器的 LoadBalanceWeight 为 0,这样可以放弃他们。一旦版本 N 服务器闲置下来,版本 N 单元就可以关闭了。然后就可以使用从版本 N+1 单元生成的 plugin-cfg.xml 文件配置 HTTP 服务器,这样转换就完成了。


Java 客户端应用程序转换

接下来,我们将看一下从当前版本到新版本,管理 Java 客户端应用程序转换的过程。Java 客户端转换通常不是所关心的主题,这是由于 Java 客户端不是按通常做法开发的。开发他们时,在客户端上有充分的管理控制,使得它可以与应用程序新版本出现的同时发布新客户端。然而,应当包含更大范围的 Java 客户端场景,下面描述的流程使用相对简单的管理任务就可以完成流畅的转换。

在这个流程中:

  • 假设与客户端 API 有关的 EJB 方法或者没有更改或者能与现有客户端应用程序向后兼容。
  • 在我们的例子中,只有一个单独的 EJB 组件用于客户端 API,名为 SessionFacade。简单应用程序的名称是 userHitCount。
  • 这个方法假设定义了有多集群的单一单元,一个处于活动状态,一个处于静止状态,如图 8 所示。

短语“Java 客户端”是指独立的 Java 客户端,不是运行在应用服务器中的客户端。运行在应用服务器上的 EJB 客户端的情况可以与这里描述的情况等同对待,简而言之:没有必要考虑使用哪个初始上下文提供者 URL。运行在应用服务器上的任何客户端都可以使用默认的初始上下文提供者。

对新版应用程序回滚,对于独立 Java 客户端有两个问题需要考虑:

  • 从何处取得初始上下文
    初始上下文提供者 URL 通常定义为客户端的配置参数或命令行输入。不幸的是,如果要为新服务器集群提供新版本的应用程序,您就无权改变提供者 URL。
  • EJB 绑定
    这些定义在客户端的部署描述符中。如果您无权访问客户端执行程序,您就不能改变他们。

WebSphere Application Server V5 有在 JNDI 中配置绑定能处理上述问题的特性。可以利用初始上下文提供者 URL 创建单元持久字符串绑定。可以使用单元持久间接绑定接触运行应用程序当前版本的 EJB 服务器。

可以从 Environment => Naming => Namespace Bindings 下的管理控制台定义并管理配置的 JNDI 入口。也可以利用 wsadmin 脚本来配置他们。

安排独立的 Java 客户端使用“bootstrap”初始化上下文提供者,该提供者指向单元的节点代理(打算一直运行,这样可以认为他们一直是可用的)。对运行时初始上下文提供者 URL 进行查找,该提供者 URL 指向运行最新版本应用程序集群中的服务器。(在清单 4 中将会详细描述。)


图 8. 供 Java 客户端使用的配置 JNDI 绑定的管理控制台视图
图 8. 供 Java 客户端使用的配置 JNDI 绑定的管理控制台视图

当进行转换时要切换配置绑定的值:

清单 4

InitialContextProvider (when ClusterX is active, note the odd port #s)
corbaloc::test1.ibm.com:9811,:test2.ibm.com:9813,:test3.ibm.com:9815
InitialContextProvider (when ClusterY is active, note the even port #s)
corbaloc::test1.ibm.com:9812,:test2.ibm.com:9814,:test3.ibm.com:9816
EJB indirection JNDI binding when ClusterX is active:
 com/ibm/samples/userHitCount/SessionFacadeEJB
	Provider URL (odd port #s):
		corbaloc::test1.ibm.com:9811,:test2.ibm.com:9813,:test3.ibm.com:9815
	Binding: cell/clusters/ClusterX/ejb/com/ibm/samples/uhc/ejbs/SessionFacadeHome
EJB indirection JNDI binding when ClusterY is active:
 com/ibm/samples/userHitCount/SessionFacadeEJB
	Provider URL (even port #s):
		corbaloc::test1.ibm.com:9812,:test2.ibm.com:9814,:test3.ibm.com:9816
	Binding: cell/clusters/ClusterY/ejb/com/ibm/samples/uhc/ejbs/SessionFacadeHome

客户端代码会有一个本地资源环境引用:

java:comp/env/myInitialConext


和一个本地 EJB 引用:

java:comp/env/ejb/mySessionFacade

独立的 Java 客户端在他的部署描述符中有两个绑定:

java:comp/env/myInitialContext

绑定:

cell/persistent/com/ibm/samples/userHitCount/InitialContextProvider

和:

java:comp/env/mySessionFacade

绑定:

cell/persistent/com/ibm/samples/userHitCount/SessionFacadeEJB

客户端部署描述符中使用的绑定必须与 JNDI 名指定的配置绑定相匹配。在本实例中,配置绑定的范围是名称空间的单元持久(单元/持久)部分。JNDI 名称的其余部分明确针对实例,并由包及应用程序名称组成。

“bootstrap”初始化上下文提供者 URL 有一系列节点代理,由于节点代理总是不顾是当前是哪个服务器集群在运行。在 Java 客户端的命令行中提供这个提供者 URL,或作为配置文件的属性。客户端有方法去完全打乱 URL 中提供者的顺序,以避免所有的客户端使用相同的节点代理或应用程序服务器作为他们的名字服务提供者。(在大型 Java 客户端情况下,那样会导致超载处理。)

Java 客户端中执行初始化查找的代码看上去如下所示:

清单 5

try
{
	// The url is a parameter from the command line
	String randomizedURL = randomizeURL(url);
	env.setProperty(Context.PROVIDER_URL, randomizedURL);
	env.setProperty(Context.INITIAL_CONTEXT_FACTORY,DEFAULT_FACTORY);
	// Get the "bootstrap" context
	bootstrap_ctx = new InitialContext(env);
	// lookup the "runtime" context
	myProviderURL = (String)
		bootstrap_ctx.lookup("java:comp/env/myProviderURL");
	randomizedURL = randomizeURL(myProviderURL);
	env.setProperty(Context.PROVIDER_URL, randomizedURL);
	// turn off caching for JNDI lookups, to avoid stale home issues.
	env.setProperty(PROPS.JNDI_CACHE_OBJECT,
		PROPS.JNDI_CACHE_OBJECT_NONE);
	runtime_ctx = new InitialContext(env);
}


图 9. Java 应用程序更新的起始状态
图 9. Java 应用程序更新的起始状态

A. 起始状态

起始状态如图 9 中所描述的:

  1. ClusterX 中的服务器正在运行应用程序的版本 N。
  2. ClusterY 中的服务器已停止。
  3. 配置 JNDI 中的绑定指向 ClusterX 中的服务器。
  4. Java 客户端是 ServerX 中的工作负载管理成员。

图 10. 测试 ClusterY 上的版本 N+1
图 10. 测试 ClusterY 上的版本 N+1

B. 开始转换

在这里,应用程序的版本 N+1 安装在 ClusterY 上且启动了服务器以提供关于产品硬件设备的最终测试环境。可以配置某些测试 Java 客户端来使用指向 ClusterY 服务器的测试绑定。由于 ClusterY 服务器和 ClusterX 中的产品服务器共享相同的硬件设备,所以应保持最小的测试负载。

C. 转换到版本 N+1

转换都立刻发生。在 plugin-cfg.xml 中没有像对 Web 客户端路由表一样对 EJB 路由表的直接访问,所以唯一的转换选择是立刻转换所有的服务器:

  1. 修改两个配置绑定:InitialContextProvider 字符串绑定和指向集群 N+1 的 EJB 间接绑定(本例中是 ClusterY)。
  2. 集群 N+1(ClusterY)服务器将需要停止并启动来获得在单元持久命名空间中的这个变更。
  3. 在任何一个 Java 客户端的重新启动之后,他们将获得新绑定并开始与应用程序的版本 N+1 一起工作。
  4. 版本 N 服务器一直运行直到所有 EJB 活动都可以停止为止。管理员可以使用 netstat 监视 ORB 端口连接到版本 N 服务器的数量,以此来确定活动级别。或者,可以使用 Tivoli Performance Viewer 监视 EJB 活动,但是用于监视 EJB 方法调用活动的 PMI 可能会引出比预想的更多的开销。

图 11. 转换到版本 N+1 服务器
图 11. 转换到版本 N+1 服务器

D. 转换完成

一旦确定了服务器版本 N 上没有(或非常少)活动,他们就会关闭。在服务器被用作 Web 客户端及 Java 客户端的情况下,用户还需要检查在 Web 应用程序中的活动。


结束语

本文详细描述了在产品设置中更新应用程序的同时要保持应用程序的持续可用性的方法。可能最简单的方法是在所有都运行在他们自己硬件上的多单元中使用服务器集群。然而,那个方法不能有效利用硬件设备。有效利用硬件设备而在管理上更复杂的方法是使用定义的活动/静止集群(或单元)对来使用同样的硬件。在从应用程序版本 N 转换到版本 N+1 的过程中,两组服务器都要运行,虽然版本 N 是“ramping down”,版本 N+1 是“ramping up”。假设一切进行正常,当版本 N 服务器处于非活动状态,他们就会关闭。这些过程提供了快速、容易的回滚操作以便需要时转变到应用程序以前的版本。Web 客户端及 Java 客户端场景都讨论过了。


致谢

几位顾问为本文提供了资料:

  • Randy Powelson, Premier ITC
  • Renuka Chekkala, IBM Software Services for WebSphere
  • Ben Neu, IBM Software Services for WebSphere
  • Keys Botzum, IBM Software Services for WebSphere
  • Jack Gibson, Brulant.

参考资料

关于作者

Author photo

Peter Van Sickel 是 IBM Software Group WebSphere 分公司的 IBM Software Services 顾问。他的办公室在宾夕法尼亚州匹兹堡,他的主攻方向是 WebSphere Application Server、操作及执行。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=57934
ArticleTitle=IBM WebSphere 开发者技术期刊: 更新 WebSphere Application Server 企业应用程序时保持持续可用性
publish-date=12012004
author1-email=pvs@us.ibm.com
author1-email-cc=

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。