|
Long Running Web Process (LRWP) The Long Running Web Process (LRWP) 是一种协议,Web 服务器使用该协议与其对等体(Peer)进行通信。LRWP 类似于 CGI,但是速度更快,因为对等体对于所有请求都是持久性的。在 LRWP 中,TCP 连接在 LRWP 对等体与 LRWP 代理之间建立。LRWP 代理可以是 Web 容器或在 Web 容器中运行的进程,LRWP 对等体可以是网络中运行的任何进程。连接中的 LRWP 将注册对等体感兴趣的 Web 上下文。 Web 上下文可以是任何上下文,比如说 "/osp"、"/tep" 或 "/cgi-bin" 本身。当针对该上下文发起请求时,代理会将输入传递给 LRWP 对等体,并将对等体返回的输出发送给 Web 客户机。LRWP 代理还可以同时支持多个对等体。对等体可以是一个进程中的多个不同线程,也可以多个进程。各个对等体将建立连接并注册感兴趣的上下文。 LRWP 协议 实现 LRWP 协议的 Web 服务器将监听 TCP/IP 端口(默认为 1081),以便于 LRWP 对等体连接服务器。对等体连接服务器的方法是打开一个 TCP/IP 连接并发送上下文名称和可选的主机名称。主机名称的作用是支持虚拟主机名称。然后,对等体等待 Web 服务器应答。应答可以是 OK 消息(表示连接注册成功)也可以是错误消息。成功注册连接之后,对等体将等待来自 Web 服务器的请求。Web 服务器将发送环境变量(如 cgi-bin 请求)和相关数据,并等待对等体响应。对等体使用 cgi-bin 程序应答之类的环境变量及相关数据表示响应。Web 服务器和对等体都可以通过关闭 TCP/IP 连接来终止连接。有关协议实现的详细信息,请参阅 Xitami 页面 "Extending Xitami with External peer Processes"。 Xitami Web 服务中的 LRWP 实现 Xitami 是一款轻量级的、多线程的 Web 服务器,它是 ServerWatch 公司的旗舰产品。它支持以下特性: - HTTP/1.0、FTP、CGI/1.1、SSI 协议和扩展、SSL、CGI、通过 LRWP 协议实现持久性(快速 CGI)、日志记录、虚拟主机。
- 支持 Windows、OS/2、UNIX 和 OpenVMS 操作系统。
- 即使在小型系统中也具有极快的速度和极低的内存占用。
在 Java 平台中设计 LRWP 代理 在 Java 平台中实现 LRWP 协议的设计方案是:使用 servlet 容器处理 HTTP 请求,利用 servlets 执行 LRWP 处理。最初的想法是构建一个多线程的 LRWP 代理服务器(在 servlet 容器中运行),用于充当 LRWP 对等体和 servlets 之间的代理程序。它可以接收来自 LRWP 对等体的请求,并将传入的 HTTP 请求传递给对等体,然后将对等体的应答信息返回给 servlets。对于 HTTP 请示,servlet 将 HTTP 请求传递给 LRWP 代理,这样便会阻塞 servlet 线程并解锁对等体线程,并将请求传递给 LRWP 对等体。然后,将来自对等体的应答传回 servlet,同时唤醒 servlet 线程并阻塞对等体线程。经过改良设计方案之后,我们不再使用多线程的 LRWP 代理,而是使用单线程代理接收来自 LRWP 对等体的连接请求并将连接存储在 ContextAssistantManager 中。这样,将请求传递给代理(Agent)时就不用再阻塞 servlet 线程了。取而代之的是, servlet 线程将使用 ContextAssistantManager 查找与对等体的连接,然后将转换为 LRWP 协议本身的 HTTP 请求传递给 LRWP 对等体,并等待 LRWP 对等体应答,然后返回应答。 此设计的特点包括: - 此设计支持多个 LRWP 代理实例,可在部署过程中配置。
- 每个对等体都可以与同一 LRWP 代理建立多个连接,这同样可以通过 web.xml 进行配置。
- 每个 LRWP 代理只使用一个线程;针对对等体连通性执行 servlet 线程管理实现。
- 通过用户界面使
LRWPAgentManager 和 RequestHandler 的实现具有透明性。 LRWP 的 Java 实现 接口类 LRWPAgentManager 此类提供以下方法由 LRWPAgentManager 实现类(implementation Class)实现。  | | start()
| 启动 LRWPAgentManager。 | | setNumOfAgents
| 定义要运行的代理的数量。 | | setStartPort()
| 定义 LRWP 代理实例要绑定的起始端口。比如说,如果将起始端口定义为 1081 并且代理数量为 2,那么就会启动两个 LRWP 代理实例 —— 第一个实例绑定到端口 1081,第二个实例绑定到端口 1082。 | LRWPAgentRegistrar 此类提供以下方法由LRWPAgentRegistrar 实现类实现。  | | register()
| 注册代理服务实例(Proxy Service Instance) (LRWP RequestHandler) | | deregister()
| 取消注册代理服务实例(Proxy Service Instance) (LRWP RequestHandler) | HttpProxyService 此类提供以下方法由 LRWP RequestHandler 类实现。  | | service()
| 实现此方法中的请求服务算法。 | | stop()
| 停止 RequestHandler/Proxy 服务实例的方法。 |
类 HttpProxyServlet 这个简单的 HTTP servlet 实现了以下 servlet 方法:  | | init()
| 从 servlet 部署文件 (web.xml) 读取初始化参数,并执行变量的初始化操作。从部署参数“Proxy Manager”获取实现类名称之后,它还将创建一个 LRWPAgentProxyManager 实例。 | | destroy()
| 停止 LRWPAgentProxyManager 实例并销毁 servlet。 | | processRequest()
| 此方法用于处理 HTTP 请求。此方法将请求转发/委托给 LRWPAgentManager。这时 LRWPAgentProxyManager 将响应此请求。 | LRWPAgent LRWP 代理是一个服务器线程,它会将自己绑定到配置文件(web.xml)中指定的代理端口。如果配置文件中定义了多个 LRWP 代理实例,则 web.xml 中定义的端口将作为初始端口。当一个新的 LRWP 对等体进程连接到某个 LRWP 代理实例时,它将创建一个 RequestHandler 实例并再次等待新的 LRWP 对等体。此类将实现以下方法:  | | run()
| 这是 LRWP 代理类重写的一个线程类方法。LRWP 代理将自己绑定到配置文件中定义的服务器端口,并等待对等体进程。当对等体进程与 LRWP 代理建立连接之后,此方法会马上实例化一个 LRWP RequestHandler。 | | stopThread()
| 停止 LRWP 代理服务器线程并关闭通信的套接字端口。 | LRWPAgentProxyManager 此类用于管理 LRWP 代理实例。它还维护一个对等体存储库,该存储库可处理虚拟主机路径(url) 请求。此类实现了 LRWPAgentManager 和 LRWPAgentRegistrar 接口。它拥有以下方法:  | | start()
| 创建 LRWPAgent 类的一个或多个实例并启动 LRWP 代理线程(一个或多个)。 | | stop()
| 停止 LRWP 代理实例(一个或多个)。 | | setNumOfAgents()
| 设置要启动的代理的数量。 | | setStartPort()
| 设置 LRWP 代理的起始端口。新创建的 LRWP 代理实例将绑定到新端口(起始端口+n)。 | | register()
| 在存储库中为虚拟主机、路径和 LRWP RequestHandler (Service Class 接口的实现程序)创建一个条目。 | | deregister()
| 从存储库中删除虚拟主机、路径和 LRWP RequestHandler 条目。 | | Service()
| 此方法所实现的逻辑是获取处理客户机请求的 RequestHandler 实例。如果没有 RequestHandler 实例支持请求,或者处于忙碌状态,则让请求等待或者使用默认响应。 | LRWP RequestHandler 此类可将来自客户机的 HTTP 请求转换为 LRWP 请求。然后,通过套接字连接将请求发送给 LRWP 对等体。每个 LRWP RequestHandler 只与一个 LRWP 对等体绑定在一起(通过套接字连接)。通过多个套接字连接,一个 LRWP 对等体进程可以连接到多个请求处理程序实例。此类实现了 HttpProxyService 接口。它实现了以下方法:  | | init()
| 接收与确认来自 LRWP 对等体的 init 消息,该消息包含与虚拟主机及其路径有关的信息。如果从 LRWP 对等体进程成功接收到 init 方法,则使用“OK”消息确认,否则确认消息将以“ERROR”作为初始字符串。 | | service()
| 这个主方法(main method)用于将 HTTP 请求转换为 LRWP 请求。并将转换后的请求发送给 LRWP 对等体进程。然后,将应答转换为 HTTP 应答并直接发回给 Web 客户机(浏览器)。 |
在 GlassFish(Java 应用服务器)上安装和部署LRWP 代理 需求: - GlassFish Java EE 应用服务器
- LRWP Agent Version 1.0
安装: GlassFish 安装和配置 - 有关 GlassFish 应用服务器的安装步骤,请参阅 GlassFish 安装文档。
- 有关 GlassFish 的使用方法,请参阅 GlassFish 快速入门指南。
- 在安装服务器时,请确保 GlassFish 的默认
http 端口为 1080。 LRWP 代理安装 - 将
LRWPAgent_bin.tar.gz (LRWP 代理二制文件)解压到系统目录($HOME_DIR 目录)。 - 部署 LRWP 代理:
2.1. 打开 Sun Web 应用服务器的管理控制台。 2.2. 指定待部署的 LRWPAgent.war 文件的路径($HOME_DIR/LRWPAgent/dist/LRWPAgent.war)。 2.3. 在 GlassFish 的根上下文 (root context)中部署该 war 文件。可以在部署 war 文件的过程中完成此操作。
- LRWP 代理已经部署完成。这时可以测试它与对等体之间的 LRWP 连接。
LRWP 代理配置 用户可以对 LRWP 代理模块的不同参数进行配置/调优。所有参数都定义在安装软件的 'web.xml' 文件中。下面介绍了参数名称及其作用: - Proxy Manager —— 定义实现 Proxy Manager 接口的类。Proxy Manager 类可以管理多个 LRWP 代理实例。配置文件 (web.xml) 中的参数名称为"ProxyManager"。
- Number of Agents —— 定义需要的 LRWP 代理实例的数量。默认值 为 '01'(一个实例)。但是,LRWP 模块可以同时支持 10 个 LRWP 代理实例。配置文件 (web.xml) 中的参数名称为"numAgents"。
- Starting Port —— 定义 LRWP 代理运行的端口号。默认端口为 1081。如果 "numAgents" 参数中定义的实例数量大于 1,则此参数将作为初始端口。比如说,如果
numAgents 为 '2',并且定义初始端口为 '1081',那么将运行两个 LRWP 代理,且第一个实例与端口 1081 绑定,第二个实例与端口 1082 绑定。配置文件 (web.xml) 中的参数名称为"startPort". - peer Per Agent —— 定义一个 LRWP 代理可以连接的 LRWP 对等体数量。此参数的作用是实现负载均衡。默认可处理的对等体数量为 '5'。一个代理最多可处理 15 个 LRWP 对等体。配置文件 (web.xml) 中的参数名称为"peerPerAgent"。
测试 C LRWP 对等体 LRWP 对等体是一个客户机,它与在 GlassFish 应用服务器上运行的 LRWP 代理连接。Xitami 站点 提供了一个示例程序。可以编译此示例程序并且生成的二进制可以作为 GlassFish 上 LRWP 代理的基本工具。 可以从命令行编译此程序,并且需要将 Imatix 公司的 SFL 库 包含在命令行中。 在编译示例代码之前,需要修改 lrwp_connect() 函数中的参数。比如说,localhost 和端口号可以替换为 LRWP 代理机器的主机名和 LRWP 代理运行的端口号。 lrwp_connect(&lrwp, "hello", "localhost", "81", "");
| 编译的标准命令行类似于以下格式: %cc -I<path to the SMT library> -I<Path to the SFL Library> lrwp_peer.c \ -llrwp_context -lsfl-32b-lrwp -lsfl-32b -lsmt-32b -lsocket -lnsl -o lrwp_peerlrwp_peer
| 完成编译之后,可以通过 LRWP 代理测试二进制代码。以下步骤可以测试 LRWP 代理的基本功能: - 从命令行运行 C LRWP 对等体二进制代码。
- 在浏览器中键入 GlassFish 应用服务器的 URL
http://localhost:1080,并附加 hello 作为上下文。 - 页面中将显示发送给 LRWP 代理的请求数量,同时计数器将记录该数据。
使用 LRWP 对等体的 Java 编程语言实现 Sokrates 可以执行更全面和更佳的测试 [下载地址为 http://www.dreamlandbbs.com/files/gfd/appjava/sokr_v17.zip ]。 测试 Java LRWP 对等体(Sokrates) Sokrates 的安装和运行 - 解压
sokr_v17.zip 文件 - 更改到 Sokrates 目录
% cd $HOME_DIR/Sokrates - 编辑 runner.ini 文件:
- 将主机定义为 'localhost'
- 将端口号定义为 1081
- 启动 Sokrates:
% cd $HOME_DIR/Sokrates % java net.conacom.servletrunner.main.Runner - 这样便可以启动 Sokrates 对等体。
- 在 Web 浏览器中,输入 URL:
http://localhost:1080/demo 浏览器将打开 Sokrates 默认页面。然后便可以运行该页面列出的各种操作。 使用 Sokrates 测试 LRWP 代理 针对 LRWP 代理,Sokrates servlet runner 可提供以下测试操作: - 列出参数(List Parameters)
- 列出报头(List Headers)
- 列出请求属性(List Request Attributes)
- 列出 servlet 属性(List servlet Attributes)
- 列出请求方法(List request Methods)
- 列出上下文方法(List Context Methods)
- 列出 Cookies(List Cookies)
- 列出会话数据(List Session data)
- 测试表单(Test Form)
- 测试 Cookies(Test Cookies)
- 测试会话(Test Sessions)
- 测试重定向(Test Redirect)
- 测试二进制(Test Binary)
- 测试选择(Test Choice)
- 测试大数据(Test Bigdata)
- 测试转发(Test Forwarding)
- 测试包含(Test Include)
上面列出了完整功能 LRWP 代理的标准测试操作,操作失败则表明代理不具备该功能的实现。 结束语 使用 Java 实现的 LRWP 代理(结合 GlassFish)可以很好地与基于不同语言的 LRWP 对等体协作。已测试的语言包括 C、C++ 和 Java 编程语言的 LRWP 对等体。LRWP 代理的性能相当好,并且 实际上超过了 4 核 x86 系统上的 Xitami 的实现。同时,LRWP 代理实现还是 java.net 上的一个开源的项目,可以从 java.net 下载获得。 致谢 感谢 Satyajit Tripathi 为我们提供了出色的项目管理,他使用时间线(time line)有效地跨越多个时区管理资源,从而实现了高效的通信。感谢 Bruce Chapman 为我们提供了一些有用的建议,使文章更具可读性。 参考资料 - LRWP 协议
- Xitami Web 服务器
- GlassFish
- 线程
- Xitami 特性
- Wikipedia
- imatix 杰出产品
|