网络应用程序请求序列化

作者:Colin Wilson

网络应用程序服务器是基本 Web 服务器概念的极其有用的扩展。复杂的应用程序可以跨网络访问,而不是呈现相当简单的静态页面或数据库查询的结果。服务应用程序的一个问题是,后端处理可能需要大量时间和服务器资源——当多个用户同时提交请求时,会导致响应时间缓慢或因内存限制而失败。

对于无法立即满足的 Web 请求,基本上有三种基本策略:忽略问题;使用无缓冲无解析标头 (NPH) CGI 代码来发出“正在处理”消息,同时后端完成处理;或者发出立即响应,将用户定向到作业完成时创建的结果页面。根据我的经验,第一种选择无效。在没有反馈的情况下,用户总是会重新提交他们的请求,认为提交失败。如果冗余请求没有被消除,将会加剧问题。更糟糕的是,这些冗余请求的数量将在使用高峰期达到峰值。当处理时间较短且服务器可以处理应用程序的多个并发实例时,NPH CGI 最有用。它的缺点是用户必须坐着等待处理完成,并且不能快速返回页面。我首选的方法是定向到动态页面,并结合可靠的请求序列化方法。

描述

通用 NQS 的起源

作为一个例子,我将描述我如何使用通用 NQS (GNQS)(参见 http://www.shef.ac.uk/~nqs/ 和 http://www.gnqs.org)为华盛顿大学基因组中心的 一组 Web 应用程序服务器执行序列化和重复作业消除。GNQS 是一个开源队列软件包,适用于 Linux 以及许多其他 UNIX 平台。它的编写主要是为了优化超级计算机和大型服务器场的利用率,但它在单台机器上也很有用。目前由 Stuart Herbert (S.Herbert@Sheffield.ac.uk) 维护。

在基因组中心,我们开发了许多用于 DNA 序列分析的算法。其中一些算法是 CPU 和内存密集型的,并且需要访问大型序列数据库。除了分发代码外,我们还通过 Web 和电子邮件服务器向全球科学家提供了其中的几个程序。任何有浏览器访问权限的人都可以轻松分析他们的序列,而无需在现场拥有 UNIX 专业知识,最重要的是,对于我们的应用而言,无需维护数据库的本地副本。由于序列数据库很大并且不断修订,因此维护副本对于小型研究机构来说可能是一笔巨大的开销。

该站点最初是在一台 200MHz Pentium Pro,128MB 内存,运行 Red Hat 4.2 和 Apache 的机器上实现的,这对于大部分处理请求来说已经足够了。我们网站的大部分提交都可以在几秒钟内处理完毕,但是当同时发出几个大型请求时,响应时间变得无法接受。随着请求数量和数据大小的增加,服务器经常不堪重负。我们考虑过减少我们将接受的最大问题规模,但我们知道,随着人类基因组计划的推进,更大的数据集将变得越来越普遍。在分析使用日志后,很明显,在高峰期,当服务器没有快速返回结果时,人们会提交多个请求副本。在我们的网站上线后不久,我就面临着这个性能问题。

实施

列表 1. GNQS 示例命令

我没有增加 Web 服务器的规模,而是觉得强大的序列化可以解决这个问题。我在服务器上安装了 GNQS 3.50.2 版本,并编写了 CGI 脚本的小扩展来排队较大的请求,而不是立即运行它们。我没有求助于 NPH CGI 脚本,这些脚本会将用户的网页锁定几分钟,同时 Web 服务器进行处理,而是可以编写一个临时页面,其中包含服务器仍在处理的消息以及稍后重新加载页面的说明。通过从请求参数和数据的 md5 校验和中创建一个动态页面的名称,我能够彻底消除多个相同请求的问题。最后,所有 Web 请求都在单个作业队列中序列化,并且额外的低优先级队列用于电子邮件请求。允许提交到 Web 服务器的请求通过电子邮件回复只需排队到低优先级电子邮件队列中,这是一个小的增强功能。因此,处理器利用率提高了,作业争用减少了。

虽然这从机器利用率的角度来看非常有效,但在高峰期,作业队列会变得非常长,以至于用户变得不耐烦。另一个增强功能是在最初排队请求时报告队列长度。这让用户对完成时间有了更准确的预期。此外,当重新提交排队的作业时,现在将显示在队列中的当前位置。这些更改完全消除了关于 Web 服务器状态的错误查询。

经过一年多的运行,我们有了另一个应用程序要发布,并决定将服务器迁移到运行 Red Hat 5.0 的 Linux/Alpha 系统。切换到 glibc 暴露了 GNQS 中的一个错误,最初很难找到。但是,由于源代码是可用的,我自己能够找到并修复该问题。此后,我已将补丁提交给 Stuart,以便包含在 GNQS 的下一个版本中,并向 Red Hat FTP 站点贡献了一个源 RPM (ftp://ftp.redhat.com/pub/contrib/SRPMS/Generic-NQS-3.50.4-1.src.rpm)。

未来方向

使用 GNQS 排队请求允许另一个有趣的选择,随着我们的处理需求增加,我们将来可能会追求这个选择。我们可以保留现有的 Web 服务器作为前端服务器,而不是再次将服务器迁移到更强大的机器或更复杂的 Web 服务器阵列。在 Web 服务器上的 CGI 脚本没有任何更改的情况下,可以重新配置 GNQS 以在尽可能多的附加机器上分发排队的作业,以满足我们的响应时间要求。由于 GNQS 也可以进行负载均衡,因此可以轻松、高效且动态地进行扩展,而无需服务器停机。队列服务器的数量对于 Web 服务器来说是完全透明的。

评估

有很多方法可以处理需要大量后端处理时间的 Web 应用程序。优化应用程序服务器需要的技术与优化高点击率服务器不同。对于应用程序服务器,限制资源可能是 CPU、内存或磁盘 I/O,而不是网络带宽。给定请求的响应时间预计会相对较慢,并且告知等待用户其作业的状态非常重要。使用 GNQS 排队请求并将用户定向到结果页面已被证明是一种有效、易于实施且稳健的技术。

致谢

Colin C. Wilson 自 1985 年以来一直从事 UNIX 系统的编程和管理工作。过去四年,他一直在华盛顿大学愉快地玩 Linux,开发 DNA 分析软件并维护人类基因组中心的系统。当他不忙于从最新的灾难中恢复时,可以通过 colin@u.washington.edu 与他联系。

加载 Disqus 评论