|
通过 WebLogic Server,可以配置应用程序确定其工作执行优先级的方式。根据您定义的规则以及通过监视实际的运行时性能,WebLogic Server 可以优化应用程序的性能,维护服务级协议。通过定义工作管理器并将其全局应用到 WebLogic Server 域或者应用到一个特定的应用程序组件,可以定义应用程序的规则和约束。
在 WebLogic Server 的以前版本中,执行处理是在多个执行队列中进行的。根据优先级和顺序要求,不同类别的工作在不同的队列中执行以避免死锁。除了默认执行队列 weblogic.kernel.default 之外,还有一些专门用于内部管理流量的预先配置好的队列,如 weblogic.admin.HTTP 和 weblogic.admin.RMI。
用户可以通过修改默认队列中的线程数来控制线程的使用,还可以配置自定义执行队列以确保特定的应用程序可以访问固定的执行线程数,而不管整体系统负载如何。
WebLogic Server 现在使用一个线程缓冲池,所有类型的工作都在此缓冲池中执行。WebLogic Server 会根据您定义的规则以及运行时规格(包括执行请求所耗的实际时间,以及请求进出缓冲池的速率)确定工作的优先级。
公用线程缓冲池会自动更改其大小以最大化吞吐量。队列随时监视吞吐量,并根据历史记录确定是否调整线程数。例如,如果历史吞吐量统计信息表明较大的线程数提高了吞吐量,则 WebLogic 会增大线程数。同样,如果统计信息表明较少的线程数没有降低吞吐量,则 WebLogic 会减小线程数。这种新策略使管理员分配处理资源和管理性能变得更容易,从而避免了配置、监视和调整自定义执行队列所涉及的工作和复杂性。
WebLogic Server 根据执行模型确定工作的优先级和分配线程,该执行模型会考虑管理员定义的参数以及实际的运行时性能和吞吐量。
管理员可以配置一套调度指南,并将其与一个或多个应用程序相关联,或者与特定的应用程序组件相关联。例如,您可以将一套调度指南与一个应用程序相关联,将另一套调度指南与另一个应用程序相关联。在运行时,WebLogic Server 使用这些指南将待定的工作和排队的请求分配给执行线程。
要管理应用程序中的工作,可以定义下列一个或多个工作管理器组件:
您可以通过在应用程序部署描述符中引用组件名的方式,使用上述任何组件来控制应用程序的性能。另外,您还可以定义一个封装上述所有组件(上下文请求类除外,请参阅上下文请求类)的工作管理器,并在应用程序部署描述符中引用该工作管理器的名称。您可以定义多个工作管理器,适用的数量取决于在 WebLogic Server 上承载的应用程序中存在多少不同的需求配置文件。
可以在下列一个配置文件中的域级别、应用程序级别和模块级别配置工作管理器:
清单 2-1 是一个工作管理器定义示例。
<work-manager>
<name>highpriority_workmanager</name>
<fair-share-request-class>
<name>high_priority</name>
<fair-share>100</fair-share>
</fair-share-request-class>
<min-threads-constraint>
<name>MinThreadsCountFive</name>
<count>5</count>
</work-manager>
要在某个 Web 应用程序的调度策略中引用清单 2-1 示例中使用的工作管理器,请将清单 2-2 中的代码添加到该 Web 应用程序的 web.xml 文件中:
<init-param>
<param-name>wl-dispatch-policy</param-name>
<param-value>highpriority_workmanager</param-value>
</init-param>
请求类表示 WebLogic Server 用于为请求分配线程的调度指南。请求类有助于确保将高优先级的工作安排在不太重要的工作之前进行,即使此高优先级工作是在低优先级工作之后提交的,也是如此。WebLogic Server 会考虑每个模块完成请求所需的时间。
请求类有多种类型,每种类型都以不同的术语表达一个调度指南。工作管理器只能指定一个请求类。
| 注意: | 公平共享请求类的值是以相对值形式指定的,而不是百分比。因此,在上面的示例中,如果这两个请求类分别定义为 400 和 100,那么它们仍将具有相同的相对值。 |
例如,假设上面示例中的 ModuleA 和 ModuleB 的响应时间目标分别为 2000 ms 和 5000 ms,单个请求的实际线程使用时间小于其响应时间目标。在具有充足需求的时间段内,在每个模块的请求流都很稳定,以致于请求数超过了线程数,并且响应和请求之间没有“思考时间”延迟的情况下,WebLogic Server 为 ModuleA 和 ModuleB 分配请求时会将平均响应时间的比例保持在 2:5。ModuleA 和 ModuleB 的实际平均响应时间可能会高于响应时间目标或低于响应时间目标,但会按照所声明的目标成比例缩小或增大。例如,如果 ModuleA 请求的平均响应时间为 1,000 ms,则 ModuleB 请求的平均响应时间为 2,500 ms。
context-request-class - 此类型的请求类根据上下文信息(如当前用户或当前用户的组)为请求分配请求类。
例如,上下文请求类中的 context-request-class 会根据请求的 subject 和 role 属性值为请求分配请求类。
通过上下文请求类,可以根据用户的上下文在应用程序的部署描述符中定义请求类。例如:
<work-manager>
<name>responsetime_workmanager</name>
<response-time-request-class>
<name>my_response_time</name>
<goal-ms>2000</goal-ms>
</response-time-request-class>
</work-manager>
<work-manager>
<name>context_workmanager</name>
<context-request-class>
<name>test_context</name>
<context-case>
<user-name>system</user-name>
<request-class-name>high_fairshare</request-class-name>
</context-case>
<context-case>
<group-name>everyone</group-name>
<request-class-name>low_fairshare</request-class-name>
</context-case>
</context-request-class>
</work-manager>
在上面的内容中,我们通过将调度与使用同一请求类的其他工作建立关联,介绍了基于公平共享和响应时间的请求类。混合了公平共享和响应时间两种类型的请求分类在调度时会明显优先考虑响应时间调度。
约束会定义分配给执行请求的最大线程数和最小线程数,以及 WebLogic Server 开始拒绝请求之前可以排队或执行的请求总数。
max-threads-constraint - 此约束会限制执行来自受约束工作集的请求的并发线程数。默认值是无限制。例如,假设约束被定义为最多具有 10 个线程,并且由 3 个入口点共享。调度逻辑可确保执行来自三个入口点组合的请求的线程不超过 10 个。
max-threads-constraint 可以按照请求所依赖资源(如连接缓冲池)的可用性进行定义。
max-threads-constraint 可能(但不一定)会阻止请求类采用其线程的公平共享或者达到其响应时间目标。一旦达到约束,服务器就不会再调度此类型的请求,直到并发执行数降到此限制之下。然后服务器将根据公平共享或响应时间目标来调度工作。
min-threads-constraint - 此约束会保证服务器将要分配给受影响请求的线程数,从而可以避免死锁。默认值为零。将 min-threads-constraint 值设置为一会很有用(例如,对于一个从对等对象同步调用的复制更新请求而言)。
min-threads-constraint 不一定会提高公平共享。此类型的约束主要在服务器实例接近于死锁状况时有效。但是,在这种情况下,该约束将导致 WebLogic Server 调度一个来自服务类的请求,即使该服务类中的请求最近已经超过了其公平共享,也是如此。
capacity - 这种约束将导致服务器仅在达到其容量时才拒绝请求。默认值为 –1。请注意,该容量包括来自受约束工作集的所有排队或正在执行的请求。当超过单个的容量阈值,或超过全局容量时,都将拒绝工作。
为了应对阻塞线程,您可以定义一个阻塞线程工作管理器组件,将其用于关闭工作管理器、将应用程序切换至管理模式或将服务器实例标记为失败。
例如,在两个线程阻塞的时间超过 30 秒时,清单 2-4 中定义的工作管理器将关闭工作管理器。
<work-manager>
<name>stuckthread_workmanager</name>
<work-manager-shutdown-trigger>
<max-stuck-thread-time>30</max-stuck-thread-time>
<stuck-thread-count>2</stuck-thread-count>
</work-manager-shutdown-trigger>
</work-manager>
从本质上来说,工作管理器有三种类型,每种类型都是按照其范围以及定义其和使用其的方式进行分类的。这三种类型为:
为了处理线程管理和执行自我调节,WebLogic Server 实现了默认工作管理器。当应用程序部署描述符中没有指定任何其他工作管理器时,应用程序将使用此工作管理器。
在很多情况下,默认工作管理器可能就足以满足大多数应用程序的要求了。默认情况下,WebLogic Server 的线程处理算法会为每个应用程序分配其自己的公平共享。对于应用程序将提供相等的线程优先级,防止它们独占线程。
可以通过创建和配置一个名为 default 的工作管理器,来替换默认工作管理器的行为。这样就可以控制 WebLogic Server 的默认线程处理行为了。
下面是一些有助于确定何时使用工作管理器来自定义线程管理的指南:
您可以创建可用于服务器上部署的所有应用程序和模块的工作管理器。全局工作管理器在 WebLogic 管理控制台中创建,在 config.xml 中定义。
应用程序使用全局定义的工作管理器作为模板。每个应用程序都会创建其自己的实例,用于处理与该应用程序相关的工作,并将该工作与其他应用程序分隔开来。这种分隔用于处理指向使用相同调度策略的两个应用程序的流量。通过单独处理每个应用程序的工作,可以在不影响其他应用程序的线程管理的情况下关闭应用程序。尽管每个应用程序都会实现其自己的工作管理器实例,但是底层组件是共享的。
除了全局作用域的工作管理器之外,还可以创建只能用于特定应用程序或模块的工作管理器。工作管理器可在下列描述符中指定:
如果未对应用程序显式分配工作管理器,则该应用程序会使用默认工作管理器。
可使用部署描述符中的 <dispatch-policy> 元素,将方法分配给工作管理器。<dispatch-policy> 也可标识自定义执行队列,以便向后兼容。有关示例,请参阅清单 2-2 在 Web 应用程序中引用工作管理器。
weblogic-ejb-jar.xml - weblogic-enterprise-bean 下现有 dispatch-policy 标记的值,可以是一个已命名的 dispatch-policy。为了实现向后兼容,它还可以命名 ExecuteQueue。另外,我们还允许 dispatch-policy、max-threads 和 min-threads 来为一列方法指定已命名的(或者使用数字值来指定未命名约束)策略和约束,这与现有的 isolation-level 标记类似。
weblogic.xml - 还支持与 web.xml 的 filter-mapping 类似的映射,其中,已命名的 dispatch-policy、max-threads 或 min-threads 是针对 url-patterns 或 Servlet 名称映射的。
此部分包含了几个示例,说明了在各种类型的部署描述符中如何定义工作管理器。
<weblogic-ejb-jar xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd">
<weblogic-enterprise-bean>
<ejb-name>WorkEJB</ejb-name>
<jndi-name>core_work_ejb_workbean_WorkEJB</jndi-name>
<dispatch-policy>weblogic.kernel.System</dispatch-policy>
</weblogic-enterprise-bean>
<weblogic-enterprise-bean>
<ejb-name>NonSystemWorkEJB</ejb-name>
<jndi-name>core_work_ejb_workbean_NonSystemWorkEJB</jndi-name>
<dispatch-policy>workbean_workmanager</dispatch-policy>
</weblogic-enterprise-bean>
<weblogic-enterprise-bean>
<ejb-name>MinThreadsWorkEJB</ejb-name>
<jndi-name>core_work_ejb_workbean_MinThreadsWorkEJB</jndi-name>
<dispatch-policy>MinThreadsCountFive</dispatch-policy>
</weblogic-enterprise-bean>
<work-manager>
<name>workbean_workmanager</name>
</work-manager>
<work-manager>
<name>stuckthread_workmanager</name>
<work-manager-shutdown-trigger>
<max-stuck-thread-time>30</max-stuck-thread-time>
<stuck-thread-count>2</stuck-thread-count>
</work-manager-shutdown-trigger>
</work-manager>
<work-manager>
<name>minthreads_workmanager</name>
<min-threads-constraint>
<name>MinThreadsCountFive</name>
<count>5</count>
</min-threads-constraint>
</work-manager>
<work-manager>
<name>lowpriority_workmanager</name>
<fair-share-request-class>
<name>low_priority</name>
<fair-share>10</fair-share>
</fair-share-request-class>
</work-manager>
<work-manager>
<name>highpriority_workmanager</name>
<fair-share-request-class>
<name>high_priority</name>
<fair-share>100</fair-share>
</fair-share-request-class>
</work-manager>
<work-manager>
<name>veryhighpriority_workmanager</name>
<fair-share-request-class>
<name>veryhigh_priority</name>
<fair-share>1000</fair-share>
</fair-share-request-class>
</work-manager>
这些 EJB 已配置为获取与它们所依赖资源(连接缓冲池以及应用程序作用域的连接缓冲池)实例数量同样多的线程。
</weblogic-ejb-jar>
<weblogic-ejb-jar xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd">
<weblogic-enterprise-bean>
<ejb-name>ResourceConstraintEJB</ejb-name>
<jndi-name>core_work_ejb_resource_ResourceConstraintEJB</jndi-name>
<dispatch-policy>test_resource</dispatch-policy>
</weblogic-enterprise-bean>
<weblogic-enterprise-bean>
<ejb-name>AppScopedResourceConstraintEJB</ejb-name>
<jndi-name>core_work_ejb_resource_AppScopedResourceConstraintEJB
</jndi-name>
<dispatch-policy>test_appscoped_resource</dispatch-policy>
</weblogic-enterprise-bean>
<work-manager>
<name>test_resource</name>
<max-threads-constraint>
<name>pool_constraint</name>
<pool-name>testPool</pool-name>
</max-threads-constraint>
</work-manager>
<work-manager>
<name>test_appscoped_resource</name>
<max-threads-constraint>
<name>appscoped_pool_constraint</name>
<pool-name>AppScopedDataSource</pool-name>
</max-threads-constraint>
</work-manager>
</weblogic-ejb-jar>
有关使用 commonJ 的详细信息,请参阅将 CommonJ 用于 WebLogic Server 和 commonJ Javadocs。
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
http://www.bea.com/ns/weblogic/90/weblogic-application.xsd">
<max-threads-constraint>
<name>j2ee_maxthreads</name>
<count>1</count>
</max-threads-constraint>
<min-threads-constraint>
<name>j2ee_minthreads</name>
count>1</count>
</min-threads-constraint>
<work-manager>
<name>J2EEScopedWorkManager</name>
</work-manager>
</weblogic-application>
此 Web 应用程序是作为清单 2-8 weblogic-application.xml 中定义的企业应用程序的一部分进行部署的。此 Web 应用程序的描述符定义了两个工作管理器。两个工作管理器指向了同一个最大线程数约束 j2ee_maxthreads,该约束是在该应用程序的 weblogic-application.xml 文件中定义的。每个工作管理器都指定了一个不同的响应时间请求类。
<weblogic xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
http://www.bea.com/ns/weblogic/90/weblogic.xsd">
<work-manager>
<name>fast_response_time</name>
<response-time-request-class>
<name>fast_response_time</name>
<goal-ms>2000</goal-ms>
</response-time-request-class>
<max-threads-constraint-name>j2ee_maxthreads
</max-threads-constraint-name>
</work-manager>
<work-manager>
<name>slow_response_time</name>
<max-threads-constraint-name>j2ee_maxthreads
</max-threads-constraint-name
<response-time-request-class>
<name>slow_response_time</name>
<goal-ms>5000</goal-ms>
</response-time-request-class>
</work-manager>
</weblogic>
此描述符定义了一个使用 context-request-class 的工作管理器。
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
http://www.bea.com/ns/weblogic/90/weblogic-web-app.xsd">
<work-manager>
<name>foo-servlet-1</name>
<request-class-name>test-fairshare2</request-class-name>
<max-threads-constraint>
<name>foo-mtc</name>
<pool-name>oraclePool</pool-name>
</max-threads-constraint>
</work-manager>
<work-manager>
<name>foo-servlet</name>
<context-request-class>
<name>test-context</name>
<context-case>
<user-name>anonymous</user-name>
<request-class-name>test-fairshare1</request-class-name>
</context-case>
<context-case>
<group-name>everyone</group-name>
<request-class-name>test-fairshare2</request-class-name>
</context-case>
</context-request-class>
</work-manager>
</weblogic-web-app>
此部分描述了如何启用与执行队列的向后兼容,以及如何将应用程序从使用执行队列迁移到使用工作管理器。
WebLogic Server 8.1 版本实现了执行队列以处理线程管理,从而使您能够创建用来确定如何处理工作负载的线程缓冲池。WebLogic Server 仍然提供了执行队列以便向后兼容,这样做主要是为了简化应用程序迁移。但是,新的应用程序开发应利用工作管理器来更加高效地执行线程管理。
启用执行队列会禁用所有工作管理器配置和线程自调整。执行队列的工作方式与 WebLogic Server 8.1 中完全一样。请参阅“WebLogic Server 性能及调整”中的“使用用户定义的执行队列”。
当应用程序从 WebLogic Server 8.1 进行迁移时,迁移之前服务器配置中定义的任何执行队列将仍然存在。WebLogic Server 不会将执行队列自动转换为工作管理器。
在 WebLogic Server 9.x 上部署了实现执行队列的 8.1 应用程序后,将创建执行队列并使用执行队列来处理针对请求的线程管理。但是,只有其 dispatch-policy 映射到执行队列的那些请求才会利用此功能。
通过使用 WorkManagerMBean 配置 Mbean 可以访问工作管理器。有关详细信息,请参阅 WorkManagerMBean。
可以在运行时树或配置树中访问 WorkManagerMBean,具体取决于应用程序如何访问工作管理器。
WebLogic Server 工作管理器提供了服务器级别的配置,从而使管理员能够为其 Servlet 和 EJB 设置调度策略。
WebLogic Server 还提供了一种用来处理应用程序中的工作的编程方式。这是通过 CommonJ API 提供的。Weblogic Server 实现了 CommonJ 规范的 commonj.work 和 commonj.timers 包。
有关 CommonJ 规范的一般信息,请访问 http://dev2dev.bea.com/wlplatform/commonj/twm.html。有关 CommonJ 的 WebLogic Server 实现的具体信息,请参阅 CommonJ Javadocs。
CommonJ 的 WebLogic Server 实现使应用程序能够将一个请求任务分为多个工作项,并使用 WebLogic Server 中配置的多个工作管理器来分配这些工作项以并发执行。不需要执行并发工作项的应用程序也可以使用配置的工作管理器,方法是在其部署描述符中引用或创建工作管理器,或(对于 J2EE 连接器)使用 JCA API。
下面是 WebLogic Server 实现和 CommonJ 规范之间的一些区别:
与 WebLogic Server 工作管理器不同(该工作管理器只能通过调度策略从应用程序进行访问),您可以直接从应用程序访问 CommonJ 工作管理器。下面的代码示例演示了如何使用 JNDI 来查找 CommonJ 工作管理器:
InitialContext ic = new InitialContext();
commonj.work.WorkManager wm = (WorkManager);
ic.lookup(`java:comp/env/wm/myWM');
有关使用 CommonJ 工作管理器的详细信息,请参阅 CommonJ Javadocs。
您可以将一个外部定义的 CommonJ 工作管理器与 WebLogic Server 工作管理器进行映射。例如,如果您在描述符(如 ejb-jar.xml)中将一个 CommonJ 工作管理器定义为:
<resource-ref>
<res-ref-name>minthreads_workmanager</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
可通过确保 WebLogic Server 描述符(如下面的 weblogic-ejb-jar.xml)中的 name 元素与上述对应元素完全相同,将此工作管理器链接到一个 WebLogic Server 工作管理器:
<work-manager>
<name>minthreads_workmanager</name>
<min-threads-constraint>
<count>5</count>
</min-threads-constraint>
</work-manager>
此过程与 web.xml 中定义的 resource-ref 相似。WebLogic Server 工作管理器可以在模块描述符(例如,weblogic-ejb-jar.xml 或 weblogic.xml)中定义,也可以在应用程序描述符 (weblogic-application.xml) 中定义。
|