简介
多线程应用程序可以满足当前不断增长的业务需求,同时还可以减少所需系统 的数量。但是多线程应用程序的可伸缩性却受不到了不可并发执行的代码的限制 ;这些串行组件对可伸缩性造成了限制,请参见 阿达姆定律 和 I/O 问题。我们 的上一篇文章 Horizontal Scaling on a Vertical System Using Solaris Zones 介绍了如何使用分区(Zone)扩展 Xitami/NexSRS,即在每个分区中都运 行一个副本。在每个分区中都运行一个副本可将性能提升一倍,但是这仍然不是 Xitami 可伸缩问题的解决方案。一些解决方案要么将 Long Running Web Process (LRWP) 协议迁移到 Sun Web Server,要么让 NexSRS 使用 Netscape Server API (NSAPI)。我们决定采用完全不同的方式:在 Java 中实现 LRWP 协 议并在 Web 容器中运行。GlassFish 是现行可用的开放源码项目,因此我们选择 使用 GlassFish 来实现我们的想法。我们期望这种方式在小型系统上的性能能够 接近 Xitami/NexSRS 性能,并且可以很好地扩展到较大的系统中。
实现要快于 Xitami/NexSRS —— Xitami 是使用 C 语言编写的一款非常小的 Web 服务器,而且名列十佳 Web 服务器之一。我们的实现可以更好地扩展到较大 的 CMT 系统中,但是使用 Java 实现 LRWP 在单核系统中具有 23% 的性能优势 ,而在 4 核系统中具有 78% 的性能优势,这显示了其从单核系统到多核系统的 可伸缩性,而 Xitami 实现扩展到 4 核系统上只能达到约 15K CPM。如图 1 所 示。
图 1:Xitami/C 与 GlassFish/Java 的可伸缩性比较
Long Running Web Process (LRWP)
Xitami Web 服务器使用 LRWP 协议与其对等体(peer)进行通信。对等体是 与 Web 客户机通信的进程。Web 客户机可以是浏览器或其他类型的使用 HTTP 通 信的客户机。LRWP 类似于这样一种 CGI:Web 客户机请求调用 cgi-bin/context ,cgi-bin/context 允许 Web 容器调用 cgi-bin 可执行程序,并将来自 Web 客 户机的输入传递给可执行程序,再将输出返回给 Web 客户机。在 LRWP 中,LRWP 对等体与 LRWP 代理之间将建立一个 TCP 连接。LRWP 代理可以是 Web 容器或运 行在 Web 容器中的进程,LRWP 对等体可以是运行于网络中的任何进程。连接时 ,LRWP 对等体将注册感兴趣的 Web 上下文。Web 上下文可以是任何上下文,比 如说 /osp 、/tep 或 /cgi-bin 本身。当针对该上下文发起请求时,代理会将输 入传递给 LRWP 对等体,并将对等体返回的输出发送给 Web 客户机。LRWP 代理 还可以同时支持多个对等体。对等体可以是一个进程中的多个不同线程,也可以 多个进程。各个对等体将建立连接并注册感的上下文。
使用 Java 实现 LRWP
要使用 Java 实现此协议,我们需要一个 Web 容器来处理 HTTP。由于 ISV 比较喜欢开放源码的 Web 容器,因此我们选择使用 GlassFish。GlassFish 是一 款 Java Platform Enterprise Edition (Java EE) 应用服务器,它构建于 Apache Tomcat Web 容器之上。它使用 servlets 监听 HTTP 请求,并将请求传 递给在容器中运行的 LRWP 代理。然后,LRWP 代理将请求传递给正确的 LRWP对 等体,并将应答返回给 servlet。LRWP 代理服务器将注册对等体感兴趣的上下文 并等待对这些上下文的请求。如果有请求匹配某个上下文,则 servlet 线程将进 入上下文锁定休眠状态,然后代理会将该请求传递给 LRWP 对等体,并等待对等 体的应答,然后唤醒 servlet 线程并将应答传递给它。最后,servlet 线程将应 答返回给 Web 客户机。
使用 Java 实现 LRWP
我们已经实现了 LRWP 代理,即通过一个 Web 应用程序监听 "/*" 上下文, 这样所有请求都将传入这个应用程序。如果请求的对象是 LRWP 对等体注册的某 个上下文,则将请求传递给 LRWP 对等体进行下一步处理;如果请求的对象是未 通过 LRWP 代理注册的上下文,则将该请求发送给默认 servlet 使用 ServletContext RequestDispatcher 对象进行下一步处理。希望提供 LRWP 服务 的 Service Provider(LRWP 对等体应用程序)必须通过 LRWP 代理使用 LRWP 协议注册自己。经过初始信息交换之后(依照 LRWP 协议),LRWP 代理和对等体 之间将通过 LRWP RequestHandler 建立起连接。每个对等体应用程序将创建一个 LRWP RequestHandler 实例。对等体应用程序将注册一个相关的 URL 上下文,对 该上下文的请求都将转发给对等体应用程序。LRWP 对等体可以与 LRWP 代理建立 多个连接,从而通过注册相同的上下文实现负载均衡。LRWP 对等体应用程序还可 以注册多个 URL 上下文。