技术开发 频道

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

    3. 仔细评估可能在应用程序之间共享的所有资源和其他对象

    在简介中已经提到,部署和管理共存应用程序是为了找到一种平衡,既要共享与每个应用程序关联的各种资源,尽可能提高使用效率和性能,又要尽可能减少这种共享,以便于隔离和确定问题。

    尽管共存应用程序的声明目标之一是为了共享多种服务器资源,但有许多与应用程序关联的项在与其他应用程序共享或合并时几乎不能提供什么好处。

    另一方面,应用程序之间越分离,上面提到的许多故障诊断技术(包括一般的分析方面和隔离方法)也越能发挥其作用。例如:

    *能够快速确定某个给定的资源属于某个特定应用程序还是另一个应用程序,便能够将注意力集中于与该资源关联的错误消息分析和行为上。

    *能够启用、禁用或重新配置只影响一个应用程序的给定资源可以极大地方便隔离方法的使用。

    *一般情况下,任何共享项目都会创建一个通道,一个应用程序中的问题通过该通道可能影响另一应用程序的正确行为。例如,应用程序可能争用线程、后台连接等等。那么从这一角度出发,尽可能限制共享还是比较值得的。

    让我们从应用程序共享这一角度,了解一下每个应用服务器中存在的一些主要资源和其他项目。

    线程池 

    在一个典型的 WebSphere Application Server V6.x 服务器中,需要考虑四个主要线程池类型:

   * Web 容器线程池。该池中的每个线程负责处理一个入站 HTTP 请求,并负责执行与该请求关联的所有进程,如执行 Servlet、JSP 和间接从这些 Servlet 或 JSP 调用的任何其他对象(例如位于同一服务器上的 EJB 等等)。除非在非常特殊的配置中,一般在整个服务器范围只有一个 Web 容器线程池在所有应用程序之间共享。

    *ORB 线程池。此线程池中的每个线程负责处理通过 RMI/IIOP 传入的一个入站请求,该请求通常发送到一个 EJB。此同一线程将执行第一个 EJB 和任何其他 EJB 或调用它的其他对象和资源中的代码。在服务器范围内存在一个 ORB 线程池,该服务器上部署的所有应用程序和所有 EJB 共享该线程池。

    *JCA 资源适配器线程池。这些线程池中的每个线程负责处理从服务器中配置的 JCA 资源适配器接收的一个入站消息,并执行关联的消息驱动 Bean (MDB) 和间接从该 MDB 调用的任何其他 EJB 或其他对象中的代码。缺省情况下,创建的所有 JCA 资源适配器都共享一个线程池;不过,可以为每个 JCA 资源适配器明确定义一个不同的线程池。

    *消息侦听器线程池。该池中的每个线程负责处理从侦听器端口接收的入站消息,它通常与一个不使用 JCA 规范的 JMS 提供程序(如 WebSphere MQ 提供程序)关联。对于 JCA,该线程将执行关联 MDB 和间接从该 MDB 接收的任何其他 EJB 或其他对象中的代码。在每个服务器中,对于该服务器中定义并由所有应用程序使用的所有侦听器端口,仅存在一个消息侦听器服务和一个相应的线程池。

    尽管所有这些线程池互不相同,但它们都使用 WebSphere Application Server 中的一个通用池工具实现,因此可以使用一组相同标准的配置参数(最大值、最大值、静止超时和“可增长”标记)控制每个线程池。

    正确管理线程池非常重要,因为线程对于服务器中的内存使用量以及其他低级操作系统资源而言是相当珍贵的资源。因此,我们通常需要保持很少数量的线程,但足够大的线程池可以满足服务器的性能和容量需求。这意味着通常需要对有时关联一个应用程序、有时关联另一应用程序的服务请求启用同一组线程,而不是对每个应用程序都保留一组完全不同的线程。但是,此方法同时会导致严重的性能问题:如果两个应用程序同时需要来自同一线程池的大量线程,它们显然会相互影响,并且您会看到性能下降。在极端情况下,如果一个应用程序在某个特定时段内占用线程池中的大多数或全部线程,则所有其他应用程序可能会“挨饿”,从而导致应用程序的性能非常低甚至会“挂起”。

    假设 WebSphere Application Server 中的大多数线程池是服务器范围的线程池,则这些线程池中的线程实际上通常在所有应用程序之间共享。为最大限度减少应用程序之间的竞争现象(这种竞争现象可能导致应用程序性能低下和供给不足),每个线程池应该足够大,以便能够满足服务器中所有应用程序共同平均稳定状态的需求。当某个应用程序有一个临时的超过平均峰值的负载时,应用程序之间可能会发生竞争。线程池中的线程仅按“先来先服务”原则进行分配;WebSphere Application Server 中没有提供标准机制,为一个应用程序提供优于另一应用程序的优先权。

    不过,为避免应用程序之间发生严重的线程供给不足问题,可以配置一个线程池,允许线程的分配超出最大线程大小。这意味着,当存在大量的活动时,线程池将临时创建其他线程,这样所有应用程序都可以使用所需的线程。不过,在使用此机制时应格外小心:

    *它可以有效地删除允许服务器创建的线程数量的任何上限,因此在极端负载情况下,服务器可能会创建许多线程,以致于无法有效地发挥功能,导致耗尽内存甚至崩溃。

    *在这些条件下创建的其他线程根本不在池中存储;它们在每次处理新请求时创建并在处理完成后销毁。与服务器的正常操作相比,这可能导致性能下降。

    出于这些原因(尽管此机制可以针对线程供给不足提供额外的安全级别),通常更为可取的方法是调整最小和最大池大小来应对大多数情形。另外还需要注意,即使将一个线程池中的线程数配置得非常大或者没有限制,仍可能存在有效地限制服务器能够同时处理多少请求的其他约束,例如,可以接收入站请求的 HTTP 连接数、ORB 连接数或者 JCA 或 JMS 连接数。

    在 WebSphere Application Server 的较新版本中,异步 I/O 工具 (AIO) 还提供一个缓解通信中峰值的附加级别。如果没有足够的线程提供服务,则传入请求(特别是 Web 请求)可以在 AIO 工具中排队,而不是立即被拒绝。这有助于系统在过分负载期间反应比较流畅。不过,对于上述的“可增长线程池”,此解决方案并不是十全十美:在 AIO 工具中排队会带来额外的开销和延迟。这在短期的大量活动时还可以接受,但要获得服务器及其应用程序的稳定操作状态,则不应依赖于此解决方案。AIO 工具中的队列与它向其分派请求的线程池类似,也是服务器范围的,因此也在所有应用程序之间共享。

    最后,对于与 JCA 资源适配器相关联的连接池,事实上可以对不同的资源适配器使用不同的线程池。例如,如果两个应用程序访问不同的 JCA 资源,并因此使用两个不同的资源适配器,则它们可以使用单独的线程池或一个共享的线程池。即使两个应用程序访问同一 JCA 资源,它们也可以为该 JCA 资源定义两个不同的资源适配器,因此能够使用两个不同的线程池。权衡是否使用多个线程池应根据具体情况进行评估,同样需要考虑上述与线程相关的资源使用和可能的线程供给不足问题。

    本部分中的整个讨论内容重点集中在如何使服务器功能尽可能地高效和可靠,并没有讨论如何确定问题。对于涉及服务器中线程研究的大部分问题(挂起、崩溃等等),您解决这些问题的能力在很大程度上取决于这些线程是否在应用程序之间共享。对于这些问题,关键解决技巧一般是获取涉及多种线程的堆栈跟踪,并从查看该堆栈跟踪中涉及的方法和类确定哪个应用程序当前在该线程上执行,并准确地确定该应用程序在执行什么操作。从本质上讲,这取决于您识别有问题的方法和类的能力,而不是识别线程本身。

0
相关文章