AOLserver 简介
Apache,作为广为人知的 HTTP 服务器,堪称开源软件的典范:它普及、稳定、灵活、安全、便携、可扩展,并符合互联网标准。 自从 Apache 首次发布以来,我便开始使用它,并且乐在其中。
鉴于存在多种开源操作系统、编辑器、数据库和编程语言,听到 Apache 不是唯一的开源 HTTP 服务器也不足为奇。 令人惊讶的是,其中一个替代方案来自美国在线 (America Online),这家公司同时也是开源 Web 浏览器 Mozilla 的赞助商。
AOLserver 提供了许多与 Apache 相同的功能:它以开源许可证发布,易于配置且灵活,并提供用于编写插件模块的 API。 然而,AOLserver 的架构与 Apache 的架构从根本上不同,这通常使其成为更高效的选择。 此外,AOLserver 还包括内置的 Tcl 解释器、多线程、数据库 API 和数据库连接池。 如果您的网站大量使用数据库连接,那么值得考虑将 AOLserver 作为 Apache 的替代方案。
本月,我们将探讨 AOLserver,作为介绍有关开源 OpenACS (开放架构社区系统) Web 应用程序框架的几篇文章的引言。 虽然 AOLserver 不是 OpenACS 的绝对要求,但它是配置和安装该系统的标准且预期的方式。
AOLserver 最初名为 NaviServer,由一家名为 NaviSoft 的先锋公司编写和销售,该公司为 Web 发布商提供高质量的客户端和服务器端工具。 美国在线经常收购开发出有趣技术的公司;就 NaviSoft 而言,美国在线购买他们是为了他们的服务器端工具,而不是客户端工具。
如果不是一系列事件的巧合,AOLserver 可能会仍然相对不为人知:美国在线通过互联网免费提供该程序的二进制副本,并且 Philip Greenspun 开始开发 ArsDigita 社区系统。 AOLserver 可以轻松创建高性能、数据库驱动的网站;ACS 大量使用关系数据库这一事实意味着 AOLserver 是一个完美的选择。
但是,虽然 AOLserver 是免费的,但源代码仍然不对公众开放。 1999 年,Greenspun 帮助谈判达成了一项协议,该协议导致 AOLserver 3.0 在 AOLserver 公共许可证下发布,该许可证与 Mozilla 公共许可证基本相同。
ArsDigita 本身实际上已于今年早些时候倒闭,其剩余员工和资产成为红帽软件 (Red Hat Software) 的一部分。 但是,最初的 ACS 软件以 OpenACS 项目的形式继续存在,该项目基于 ACS 的原始 Tcl 版本,使用 AOLserver 和 PostgreSQL 或 Oracle。
AOLserver 向开源模式的转变并非没有问题。 虽然细节仍然有些模糊,但许多 OpenACS 开发人员曾短暂地致力于他们自己的 AOLserver 分支,他们称之为 OpenNSD,理由是 AOLserver 开发人员需要对社区参与更加开放。 OpenNSD 现在似乎已经消亡,OpenACS 社区再次鼓励人们使用 AOLserver。
与此同时,ArsDigita 向 AOLserver 添加了许多增强功能,这些功能尚未添加到服务器最新稳定版或开发版的源代码中。 因为我对 AOLserver 的使用几乎总是与 OpenACS 相关联,所以我将使用 AOLserver 3.3ad13,可从 www.openacs.org/software.adp 获取。 更高级的版本,包括即将推出的 4.0 版本的开发快照,可从 www.aolserver.com 获取。 但目前,这些官方版本不能保证支持 OpenACS。
在今年早些时候 2.0 版本首次向公众发布之前,Apache 一直是一个多进程服务器。 也就是说,在任何给定时间都会运行多个 Apache 进程,每个进程都能够在给定时间处理单个 HTTP 事务。 支持 10 个并发事务意味着并行运行 10 个 Apache 进程,而支持 100 个并发连接意味着拥有 100 个此类可用连接。
Apache 2.0 在某种程度上改变了这一点,允许每个进程拥有多个线程。 每个线程都可以处理一个 HTTP 连接,这意味着每个进程中的五个线程可以接受最多 25 个并发连接。 由于线程通常比进程消耗更少的资源,因此这实际上意味着典型的 PC 将从性能提升中受益。
相比之下,AOLserver 始终是多线程的,并在单个进程中运行。 在任何给定时间,您的计算机都将只运行 nsd 的一个副本,其名称反映了它曾经是 NaviServer 守护程序的事实。 但是,这一个进程可以处理大量并发 HTTP 连接。 事实上,美国在线继续推动 AOLserver 开发正是因为它能够处理如此大量的并发连接。 它在自己的高流量网站上使用 AOLserver,包括 netscape.com、aol.com 和 digitalcity.com。
多线程解决方案的一个优点(也是潜在的陷阱)是线程可以轻松地相互共享数据结构。 AOLserver 利用这一点来创建数据库连接池。 因为此池中的连接始终保持打开状态,所以您的 Web 应用程序无需花费时间打开(或关闭)它们。 此外,由于服务器当前的所有 HTTP 连接很少需要同时访问数据库,因此池可以包含比最大线程数更少的连接——从而减少 Web 服务器和数据库服务器使用的内存量。 您可以将其视为数据包交换的数据库等效物,其中电话线在众多方之间共享,利用的是没有人 100% 的时间都需要该线路这一事实。
AOLserver 支持插件模块,就像 Apache 一样。 有许多可用的模块,从 XML 解析器 (nsxml) 到嵌入式版本的 Python (PyWx)。 还有用于执行 CGI 程序、通过 SSL 进行安全连接以及用于各个关系数据库(如 MySQL、PostgreSQL 和 Oracle)的模块。 因为 OpenACS 可以与 PostgreSQL 或 Oracle 一起使用,所以可从 openacs.org 下载的 AOLserver 版本同时包含这两个模块以及 nsxml。
正如 mod_perl 允许 Web 开发人员自定义 Apache 的配置和响应而无需使用 C 一样,AOLserver 提供了一个集成的 API,允许您使用 Tcl 语言创建自定义功能。 说实话,我个人更喜欢使用 Perl 或 Python 进行开发,但正如许多 AOLserver 和 OpenACS 开发人员多年来告诉我的那样,Tcl“并没有那么糟糕”,而且我确实在非常短的时间内使用 Tcl 和 AOLserver 创建了许多有趣且可维护的应用程序。 (我还没有尝试过嵌入式 Python 模块,部分原因是 OpenACS 需要使用 Tcl。)而且,AOLserver 提供的 API 使处理 HTTP 标头和 HTML 表单值等内容相对容易。
编译 AOLserver 相对简单。 与 Apache 不同,Apache 通过 apxs 程序提供在安装服务器后编译模块的支持,AOLserver 要求所有模块一起编译和安装。
虽然创建此用户和组不是强制性的,但出于安全原因,AOLserver 将拒绝以 root 用户身份运行。 因此,在开始编译和安装 AOLserver 之前,您应该在系统上创建一个新的用户和组,传统上称为 nsadmin。 在我的 Red Hat 7.2 系统上,我只需说
/usr/sbin/adduser nsadmin
在仍以 root 用户身份登录的情况下,我现在创建 /usr/local/aolserver 目录,AOLserver 默认安装到该目录中。 然后,我将此目录的所有权授予 nsadmin
mkdir /usr/local/aolserver chown nsadmin.nsadmin /usr/local/aolserver完成此操作后,我切换到 nsadmin 用户,打开我从 openacs.org 下载的源代码,然后开始编译过程
su - nsadmin cd /tmp tar -zxvf aolserver3.3ad13-oacs1-beta-src.tar.gz cd aolserver ./conf这将根据您的系统参数自动配置、编译和安装 AOLserver,并将文件放置在 /usr/local/aolserver 目录下。 AOLserver 将自动尝试编译它可以编译的任何模块,忽略(并排除)任何其他模块。 在我的桌面机器上,它具有 PostgreSQL 的开发库,但没有 Oracle 的开发库,以这种方式配置和安装 AOLserver 会导致包含 PostgreSQL 驱动程序,但完全忽略 Oracle 驱动程序。
构建过程可能需要一段时间,并且不会在屏幕上产生大量输出。 如果您担心该过程在某种程度上已冻结,您可以查看 log/aolserver.log 文件;所有编译输出都可以在那里找到。
构建过程完成后,您将在 /usr/local/aolserver 中获得 AOLserver 的副本。 /usr/local/aolserver 下最重要的目录是 bin,其中包含 AOLserver (nsd) 程序,以及编译到服务器中的每个模块的共享库 (.so)。 log 目录包含服务器的访问日志和错误日志,lib 目录包含内置的 Tcl 解释器。
AOLserver 的配置文件是用 Tcl 编写的;一个简单的配置文件默认放置在 /usr/local/aolserver/sample-config.tcl 中。 如果您检查它,您将看到每个配置指令实际上都是一个 Tcl 变量赋值。 这些变量赋值分为多个部分,其中每个部分通常代表编译到服务器中的模块。
正如您从示例配置文件中看到的那样,您可以为变量分配文字值。 例如,您可以使用以下命令将 AOLserver 侦听的 HTTP 端口设置为 8000
set httpport 8000
由于配置文件是用 Tcl 编写的,您还可以通过询问 AOLserver 而不是硬编码值来设置 homedir 变量,默认情况下为 /usr/local/aolserver
set homedir [file dirname [ns_info config]]当然,您也可以根据其他变量的值设置变量,使用简单的插值
set servername "server1" set pageroot ${homedir}/servers/${servername}/pages示例配置文件中的这两行配置了静态 URL 的根目录为 /usr/local/aolserver/servers/server1/pages。
其他配置设置是通过 ns_param 命令进行的,该命令通常接受两个参数:名称和值。 每个参数都必须在一个部分中,该部分以调用 ns_section 开始。 例如,我们可以通过打开 (global) ns/parameters 部分中的 debug 参数来激活服务器调试
ns_section "ns/parameters" ns_param debug false
遗憾的是,与在线 Apache 文档相比,AOLserver 参数的文档非常缺乏。 aolserver.com/docs/admin/config-reference.tcl.txt 上几乎提供了完整的参数列表,其中演示了设置几乎所有内容的服务器配置。
完成系统配置后(默认配置对于简单站点来说是一个不错的起点),您可以通过调用 nsd 程序并指定要使用的配置文件的名称来启动 AOLserver
cd /usr/local/aolserver bin/nsd -f -t sample-config.tcl
-f 选项在前台运行 AOLserver,并将错误日志发送到您的屏幕。 一旦您对正在发生的事情感到满意,您可以删除 -f,并在日志目录中查找服务器的错误日志。
如果您希望 AOLserver 侦听端口 80,则必须以 root 用户身份启动它。 否则,Linux 将拒绝接受该请求,并告诉您只有超级用户才能启动侦听“特权”端口(即小于 1024)的服务器。 如果只有 root 用户可以侦听端口 80,但 AOLserver 拒绝以 root 用户身份运行,您如何才能服务端口 80? 通过以 root 用户身份启动 AOLserver 并传递选项来指示它应该切换到的用户和组
su root cd /usr/local/aolserver bin/nsd -f -u nsadmin -g nsadmin -t \ sample-config.tcl
您现在应该能够将浏览器指向 http://yourhost.yourdomain.com:8000/ 并看到介绍性的 AOLserver 文档,欢迎您使用这个新服务器。 请注意,AOLserver 的配置文件会查找您计算机的名称及其 IP 地址,因此如果您连接到网络,您将无法将浏览器指向 localhost,而是需要使用其全名。
虽然 AOLserver 无疑是一个出色的静态文档 HTTP 服务器,但您不太可能将其用于此目的。 更常见的是使用 Tcl 创建动态页面。
最简单的方法是创建一个返回 HTML 的 Tcl 程序。 为此,在 pageroot 中创建一个以 .tcl 扩展名结尾的文件。 它可以创建您想要的任何 Tcl;然而,最重要的是,它以 ns_return 结尾——一个由 AOLserver 定义的 Tcl 过程,它接受三个参数:1) 一个数字 HTTP 响应代码(例如 200 或 404),指示程序执行的成功或失败,2) 一个“Content-type”标头,描述要返回的内容类型,以及 3) 要返回给用户的实际内容。
例如,这是一个简单的“Hello, world”程序
ns_return 200 text/html "<html> <head> <title>Testing</title> </head> <body> <p>Hello, world</p> </body> </html>"
如果您将上述程序以 hello.tcl 形式粘贴到 pageroot 目录中并将其加载到浏览器中,您将获得返回给您的文件的文字内容。 这是因为我们需要重新配置 AOLserver 以允许 pageroot 中的 .tcl 页面。 我们通过在 ns/server/${servername} 部分中将 enabletclpages 参数设置为 true 来完成此操作
ns_section "ns/server/${servername}" ns_param enabletclpages true完成此更改后,您可以重新启动 AOLserver 并再次检索 hello.tcl。 这次,您应该看到 HTML 输出,而不是逐字的 text/plain 输出。
.tcl 页面可以执行各种不同的操作:连接到数据库、从 XML 文件检索信息、从网络检索信息或从 HTML 表单接收信息。 由于 Tcl 附带了各种字符串操作命令,因此您可以解析输入并将变量插入到各种输出中。
请注意,Tcl 是在 AOLserver 中解释的,而不是作为外部进程。 这意味着此类 .tcl 文件的执行速度比 CGI 程序快得多;在许多方面,它们的运行方式类似于 mod_perl 中的 Perl 程序。
当程序员创建传出的 HTML 时,.tcl 文件确实很棒。 但是,正如我(和其他人)从痛苦的经历中学到的那样,图形设计师通常没有准备好修改出现在源代码文件中的 HTML。 因此,许多 Web 开发人员已切换到模板——无论是 ASP、JSP、HTML::Mason、DTML 还是各种其他类似技术。 AOLserver 配备了自己的内置模板系统,称为 ADP(AOLserver 动态页面),其语法与 Microsoft 的 ASP 非常相似。 您想要执行的代码放在 <% 和 %> 之间,而将值输出到周围 HTML 中的代码放在 <%= 和 %> 之间。 例如
<% set foobar "abcdef" %> <head> <title>Testing</title> </head> <body> <p>Hello, world</p> <p>Hello, <%= $foobar %></p> </body> </html>
大于几个页面的站点可能希望共享一些 Tcl 代码。 最简单的方法是创建一个或多个 .tcl 文件,这些文件定义 AOLserver 在启动时将加载的过程。 然后,这些过程将可用于您的所有 .tcl 和 .adp 页面。 为了启用此功能,我们必须将以下内容添加到我们的 sample-config.tcl 文件中
ns_section ns/server/${servername}/tcl ns_param library \ ${homedir}/servers/${servername}/tcl ns_param autoclose on ns_param debug true由于我们的服务器名称是 server1,因此当 AOLserver 启动时,我们将放置在 /usr/local/aolserver/servers/server1/tcl 中的任何 .tcl 文件都将被加载。 例如,我将文件 foo.tcl 添加到该目录,其内容包括
proc return_hello {} { return "hello" }我重新启动了 AOLserver(这是为了让它读取 Tcl 库文件所必需的),并将 hello.adp 修改为读取
<% set foobar "abcdef" %> <% set hello [return_hello] %> <head> <title>Testing</title> </head> <body> <p>Hello, world</p> <p>Hello, <%= $foobar %></p> <p>Hello, <%= $hello %></p> </body> </html>现在,“hello”变量的值设置为我的 return_hello proc 的输出,在本例中,该输出仅仅是单词 hello。
由于您必须重新启动 AOLserver 才能使其加载库 Tcl 过程,因此我经常发现最简单的方法是在我的 ADP 页面中的 <% %> 部分中定义新过程。 一旦我看到该过程运行正常,我就将其定义移动到库目录,并且只重新启动 AOLserver 一次。
ADP 和 .tcl 页面对于包含一些动态内容的文档来说很好。 但有时您希望将程序与 URL 关联,而不必在磁盘上创建文档。 我们可以通过在我们的库文件中定义一个 Tcl 过程,然后使用 AOLserver ns_register_proc 命令将该过程注册到特定的 URL 来轻松解决这个问题
proc http_hello {} { ns_return 200 text/html "<html> <head><title>Hello! </title></head> <body><p>Hello! </p></body> </html>" } ns_register_proc GET /hello http_hello
如果您将此 Tcl 代码放在我们之前定义的库目录中的文件中,重新启动服务器并将浏览器指向 /hello,您将看到 http_hello 过程的输出。
我一直在 mod_perl 中编程多年,仍然对使用 AOLserver 和 ns_register_proc 创建新的动态页面的简易性印象深刻。 此外,您可以为 GET 和 POST 请求注册不同的过程。 您甚至可以注册过滤器过程,这些过程可以监视或更改另一个页面生成的输出。
如果您计划使用 OpenACS 进行在线社区,那么您几乎肯定必须学习如何使用 AOLserver。 但即使您对 OpenACS 不感兴趣,AOLserver 的灵活性、速度和多线程功能也非常值得您为您的动态网站进行研究。
电子邮件:reuven@lerner.co.il
Reuven M. Lerner 是一位顾问,专门从事 Web/数据库应用程序和开源软件。 他的著作《Core Perl》于 2002 年 1 月由 Prentice Hall 出版。 Reuven 与他的妻子和女儿住在以色列的莫迪因。