技术开发 频道

在 WebSphere Application Server 中部署多个共存应用程序并解决相应

    JCA 和 JDBC 连接池

    每个 J2C 连接工厂和每个 JDBC 数据源本身都有连接到相应远程系统(企业信息系统或数据库)的连接池。这些连接在使用同一 J2C 连接工厂或 JDBC 数据源的所有应用程序之间共享,它们按“先来先服务”原则从每个池向所有请求应用程序分配。

    与连接相关的注意事项和权衡方式非常类似于前几部分中讨论的与线程和线程池相关的注意事项和权衡方式。每个连接通常使用应用服务器自身中的大量资源,而且也大量使用位于每个连接另一端的后端系统资源。因此,尽可能合用和共享连接一般较为可取。但是,连接与线程类似,也是一种有限的资源,在多个应用程序之间共享连接时也会出现争用和供应不足问题。

    缓解这些问题的技术与线程池类似:基于来自所有应用程序的预期,合并要求认真配置每个共享连接池的大小,或安排每个应用程序使用单独的 J2C 连接工厂或 JDBC 数据源,即使它们最终连接到同一后端系统也应这样做。许多客户“为了安全起见”倾向于分配太多的连接。但是,大多数应用程序都很适合传统的“漏斗线程”(funnel threading) 模型(应用程序比检索数据花费更多的时间去处理数据和构建表示层)。因此,大多数应用程序在 Web 容器中比在 JDBC/JCA 层中需要更多的线程。当然,大多数准确的测量来自模拟生产条件的负载测试,以正确评估这些池的大小。

    对于使用连接到同一后端系统的多个 J2C 连接工厂或 JDBC 数据源而言,必须特别注意的一点是,跨服务器中多个应用程序的单一事务可能最终使用到同一后端系统的多个连接。这种情况不一定不正确,但可能会强制使用开销更大的事务两阶段提交协作。当从一个或多个应用程序分配的所有连接来自一个池时,可以根据需要将 WebSphere Application Server 连接管理子系统配置为启用 J2EE 可共享连接工具,该工具不能跨多个独立连接池使用。

    在使用可共享连接时,即使一个给定的事务请求多个到同一后端系统的连接,WebSphere Application Server 将确保事务实际上始终得到同一(单一)连接的副本。对于某些应用程序的使用模式,这明显可以减少所使用连接的总数量,从而减少潜在的争用和供给不足问题。但另一方面,要知道可共享连接在其他程序使用模式中还会带来连接争用加剧的风险。由于系统预先不知道某个给定的事务在完成之前是否多次请求同一连接,因此该连接在整个事务过程中保持分配给该事务,即使该应用程序表现为明显释放了该连接也如此。所以,使用可共享连接工具可以减少每个事务所使用连接的总数,但可能增加每个连接使用的时间间隔,因此导致无法将这些连接分配到其他应用程序或事务。总而言之,是否使用可共享连接实际上将导致总体减少或者增加争用情况,因为连接在很大程度上取决于每个特定应用程序的特定连接使用模式。

    而且还要知道,WebSphere Application Server V6.x 还提供了一个用于定义应用程序范围资源的工具,从开始关联和部署单一应用程序时就定义这些资源。在此情况下,应用程序之间的任何共享问题显然可以解决。这可以大大简化许多资源的管理。

    通用库和其他通用代码

    有时,多个应用程序使用同一个打包为 JAR 文件(对于 Java 代码)或本机库(对于通过 JNI 访问的代码)的实用程序库。它们可以嵌入到应用程序的 EAR 文件中(在此情况下,将成为该应用程序的专用库),也可以通过 WebSphere Application Server 中的共享库对象对它们进行管理。共享库既可以在服务器级别进行配置(在此情况下,该库的单一副本可以访问该服务器上的所有应用程序),也可以在应用程序或模块级别进行配置(在此情况下,引用共享库的每个应用程序或模块都通过不同的 Java 类加载器获得自己的库副本。)

    类似地,在其他一些情况下,Web 或 EJB 模块提供的一些通用功能有时可能用于多个应用程序。这样我们就有这样一个选择:是在每个请求应用程序中部署通用模块的单独副本,还是安排所有应用程序远程访问物理部署在单个应用程序(这可能是一个独立的应用程序,它的唯一目的就是承载通用模块,为服务器上的所有其他应用程序提供方便)中的通用模块的单一副本。

    这提出一个重要的权衡问题。您如果倾向于使用大多数通用代码组件的单一副本,则必须知道许多通用组件(代码和数据)使用的内存通常很多,所以使用同一组件的多个副本通常会增加服务器的内存使用量。但是,在另一方面,使用一个通用组件的多个独立副本在某些情况下可以防止某个故障影响到多个应用程序。大多数通用组件不只是包含代码,还包含状态信息,形式有 Java 静态变量、独立对象和本机内存缓冲区以及由该通用组件间接引用的任何其他资源。如果任何一种状态信息遭到破坏(通常由于在实现组件中的缺陷或不可预知的环境因素),则共享该组件同一副本的所有应用程序多数情况下都会受到影响。另外,如果通用组件中的代码包含瓶颈(例如许多并行应用程序请求必须通过单一监视器或关键节),则共享同一副本的所有应用程序将会相互竞争,从而扩大瓶颈的影响。当然,在需要某个特定的应用程序时,使用多个独立副本可以更容易地将组件替换为不同的实现或版本,而不会影响其他组件的稳定性。

    在实践中,应该对每个应用程序、通用库或模块逐一进行权衡和评估。

    类加载器

    WebSphere Application Server 运行时创建了一个 Java 类加载器的复杂层次结构,以协调每个程序的各种 Web 模块、EJB 模块和依赖库中所有 Java 类的负载。从共享或隔离应用服务器 JVM 中加载的各种类的角度而言,类加载器非常重要。由不同类加载器加载的两个类严格限制相互之间的可视性,因此可以限制不必要的相互干扰。而且,如果类由不同的类加载器加载,还可以加载同一类的多个副本(同一实现或不同实现)。前面管理通用库和其他通用代码部分提供了在共享与类关联对象的优缺点方面需要进一步考虑的因素。

    完整讨论各种类加载器策略的全部细节超出了本文的讨论范围,但从共存应用程序角度而言,我们应知道直接影响多个应用程序之间共享的类加载策略的一个特定方面:在每个应用服务器的全局配置中,您必须选择一个特定的服务器范围的类加载器策略(“单个”或“多个”)。当“单个”服务器类加载器策略在起作用时,将使用单个类加载器为服务器上部署的所有应用程序加载大多数类。相反,当“多个”服务器类加载器策略在起作用时,将对每个应用程序使用一个单独的类加载器。

    因此,要在不同应用程序中的类之间执行任何类型的分离(包括上述共享库和应用程序之间任何其他可能的交互),您需要将服务器类加载器策略设置为“多个”。根据一般经验,除非特定的应用程序或环境存在严格约束,使用“多个”服务器类加载器策略通常较为可取。

0
相关文章