在构建 SaaS 应用程序时定义一个多线程阈值

COBOL 和 Java 在 SaaS 应用程序中交互时遭遇多线程挑战

在内部部署的 COBOL 程序成功地转化为基于 Java 的软件即服务 (SaaS) 应用程序时,当 COBOL 和 Java 在 SaaS 应用程序中进行交互时,开发人员应该小心提防多线程问题。作者会在本文中介绍在多线程 SaaS 故障场景中应该采取什么样的积极行动。

Judith M. Myerson, 系统工程师兼架构师

Judith M. Myerson 是一位系统工程师兼架构师。她感兴趣的领域包括中间件技术、企业级系统、数据库技术、应用程序开发、网络管理、安全性、 RFID 及时和项目管理。她是 RFID in the Supply Chain 的作者,也是 Enterprise Systems Integration, Second Edition Handbook 的编辑。



2013 年 8 月 08 日

回到云岛:所有 SaaS 用户都很高兴。因为他们能获得快速响应。因为这些用户惟一拥有的控制权就是对访问应用程序的控制,他们不担心应用程序是否有多线程例程;也不担心在云中有多少核心用于并行加速多线程的处理。问题应用程序被成功地从内部多线程 COBOL 遗留系统中迁移出来。

当然,有一天,SaaS 应用程序的速度会慢下来,而且越来越慢;直到用户无法忍受。他们这时才发现:

  • 只有一个核心在正常运行,其余核心都发生了故障。
  • SaaS 订阅仅限于两个核心,而不是所有四个核心。
  • SaaS 应用程序近来升级出现了多线程缺陷。
  • 故障转移计划失败。

同时,在岛上的功能部门,开发团队的人们聚在一起思考各种解决方案,想让系统再次恢复运转。

本文帮助您探索多线程的性能问题,文中介绍了我第一次遇到多线程时的遭遇(简言之,我会尽力将损失降至最低)。然后,本文查看了多线程控制模型云用户是否在 Java 和 COBOL 中进行访问,并创建一个简洁的内置多线程支持。本文旨在向您展示供应商能够采取哪些积极措施来停止伤害、解决问题、恢复系统和通知客户。

多线程性能

CPU 中的核心越多,在执行程序代码指令时,多线程的表现就会越好,但是使用的核心数量不是决定多线程软件执行情况的惟一因素。另一个因素是:对于某个任务或者进程,使用一个算法来完成完整的线程并行并不总是可行的。某些线程的计算已经在之前的步骤中并行化了,可能得到一个连续的结果。

考虑到应用程序分散在模块中,每个都被设计用于完成一个任务或者进程。在一个模块中,可以有 6 个几乎并行的单一线程。我们假设:

a 是线程 1,b 是线程 2,c 是线程 3,d 是线程 4,e 是线程 5,f 是线程 6

结果 r0、r1 和 r2 分别作为两个独立线程的组合并行线程进行计算,如下所示:

r0 = a + b
r1 = c + d
r2 = e + f

然而,添加所有三个并行线程结果(r0,r1 和 r2)会得到连续结果 g — 这并不是一个新并行线程,如下所示:

g = r0 + r1 + r2

所有连续的部分都必须等待上一步中并行化的线程发出准备好的信号。程序中的连续部分越多,从多核中获得的好处就越少。

其他影响多线程算法的因素包括:

  • COBOL 的 THREAD 编译器选项限制。
  • Java 的多线程程序的限制。
  • 将紧耦合 COBOL 程序中的缺陷分解到松耦合 SaaS 应用程序中。
  • 云用户控制。
  • 多线程阈值缺失。

我第一次遭遇线程

十几年前,在我第一次使用主机 COBOL 时,我考虑用非 COBOL 语言与其交互。我与一位教授进行了有关的讨论,计划将此作为有关 COBOL 界面性能的论文主题。我分享了关于在程序代码中并行化线程来获得子程序的想法。

为了弄清楚什么会影响性能,我根据 “Fortran 界面适用于 CODASYL 数据库任务组规范”(参阅 参考资料)对迷你 COBOL/Fortran 界面进行了实验。Fortran 是当时的流行语言。那个时候,COBOL 还不像我们现在这样拥有 THREAD 选项。与如今我们见到的大型处理器相比,当时最大容量的处理器也非常小。

在我的实验中,我发现部分 COBOL 数据类型没有 Fortran 等同物。当应用程序不再需要的数据或者对象存在于磁盘上时,我根据需要调用子程序绕开了内存限制,然后在不需要数据或者对象时释放它们并自动删除不再需要的数据。

每个子程序执行一个或者多个任务。在某些任务中,几个线程作为一个并行线程进行计算(r0 = 线程 a + 线程 b)。所有连续部分都在等待上一步中的并行化线程发出准备好的信号。等待很短暂。

如果当时我们有云,就可以使用运行在多核虚拟机上的平台即服务 (PaaS) 上的多线程例程来开发一个 SaaS 应用程序。


多线程控制的模型云用户

多线程阈值的用途就是设置某个任务可以并行执行的线程数限制。在达到阈值时,完成自己工作的线程可以从其他线程队列中获取工作。

模型用户对多线程阈值的控制取决于:当他们进行以下操作时,可以从云供应商获得多少控制:

  • 按需访问 SaaS。
  • 使用 PaaS 构建应用程序。
  • 使用基础架构即服务 (IaaS) 虚拟机

我们会详细说明以上每一项。

按需访问 SaaS

用户拥有最少的控制,而供应商拥有最大控制。

  • 最终用户控制:最终用户拥有的惟一控制就是从移动设备或虚拟台式计算机访问 SaaS 应用程序,无论它是私人的、企业的(中小型)还是政府机构的。SaaS 应用程序示例包括船只到达和离开的时间表、客户关系管理、人力资源以及电子数据表。
  • SaaS 供应商控制:至少,供应商可以通过限制授权用户的数量来管理访问控制,正如用户阈值策略中所述,授权用户能够同时访问多线程应用程序。供应商控制运行 SaaS 应用程序所需的核心、操作系统、服务器和网络基础架构。
  • 多线程阈值控制:SaaS 最终用户没有多线程阈值的控制。供应商可能会将多线程的阈值限制为最大核心数,应用程序可用于并行处理线程。供应商设置的最大值取决于 SaaS 最终用户选择的订阅率。

使用 PaaS 构建应用程序

PaaS 开发人员拥有更多的控制,而供应商只有较少的控制。

  • 开发人员控制:开发人员控制并保护整个业务生命周期内的所有应用程序,这些应用程序是使用 PaaS 创建的。开发人员将多线程阈值设置为在构建应用程序时可用于并行处理线程的核心数。开发人员可能会设置用户和虚拟桌面线程阈值的级别。
  • PaaS 供应商控制:供应商至少可以控制运行 SaaS 应用程序、开发新应用程序或测试在云中运行多线程所需的核心、操作系统、服务器和网络基础架构,以及应用程序的可扩展性。供应商可以设置资源、数据请求、社交媒体和负载平衡的阈值级别。
  • 多线程阈值控制:开发人员可以根据应用程序中线程算法的复杂程度设置多线程的阈值。供应商将开发人员设置的阈值限制为开发人员执行线程时可能使用的最大核心数。

使用 IaaS 虚拟机

IaaS 基础架构或者网络专家拥有最多的控制。

  • 网络专家控制:基础架构或者网络专家在虚拟级别控制核心、操作系统、网络设备和部署的多线程应用程序。基础架构专家能够扩大或者缩小虚拟服务器或者存储区域块,他们利用社交媒体工具与其他 IaaS 专家、PaaS 专家和供应商进行通信。基础架构专家可能会设置用户、负载平衡和虚拟桌面阈值级别。
  • IaaS 供应商控制:供应商至少可以控制位于虚拟机底层的传统计算资源的基础架构、分配给基础架构或者网络专家的最多核心数,以及应用程序访问 IaaS 所需的应用程序。供应商可以设置用户、资源、数据请求、社交媒体和负载平衡的阈值级别。
  • 多线程阈值控制:基础架构专家可能会设置多线程阈值。供应商可能会就各个虚拟服务器上的最大核心数与基础架构专家进行磋商。

Java 编程语言拥有内置的多线程支持。我们一起来了解一下。


Java 的内置多线程支持

现在,对于使用 COBOL 的界面,Java 是最流行的语言,其次是 C/C++。Fortran 目前是科学家喜爱的一种语言,但对于一般开发人员已不再流行。

Java 在语言级别上支持多线程;这一支持大部分集中在协调多线程之间的数据共享访问。

Java 虚拟机 (JVM) 将一个运行 Java 应用程序的数据组织到几个运行时数据区域中:

  • 一个或多个 Java 栈
  • 一个堆
  • 一个方法区域

在 JVM 中,每个线程都分配到一个 Java 栈,这个栈包含其他线程无法访问的数据。数据包括本地变量、参数和线程调用的各个方法的返回值。

所有线程共享一个堆。方法区域包含程序使用的所有类(或者静态)变量。然而,与栈不同的是方法区域的类变量所有线程共享的。

I/O 和 GUI 编程就是一个需要多线程提供无缝用户体验的示例。在编写多线程程序时,必须保证任何线程不会停止其他线程的工作。

JVM 可以管理从准备队列到多核处理器的线程移动;线程可以开始执行其程序代码。这可通过协作和抢占模型 (preemptive model) 完成:

  • 协作的线程允许线程决定它们何时将处理器让给其他等待的线程。所有正在运行的线程共享执行时间。
  • 一段时间后,抢占式线程允许操作系统在任意时间中断线程。所有正在与运行的线程共享资源。

为了使用 Java 语言创建线程,可以实例化一个 Thread 类型(或者一个子类)对象,然后向它发送一个 start() 指令。线程将继续运行,直至 run() 返回主程序。这时线程将终止。

大多数应用程序需要使用线程与其他进行通信,并同步其行为。要在 Java 程序中完成这项任务,至少需要使用锁。为了避免多次访问同一个线程,在使用资源前,线程可以获得和释放锁。

试图获取某个正在使用中的锁的线程会陷入休眠状态,直到占用这个锁的线程将其释放。释放锁后,休眠线程就会移到准备运行的队列中。

锁的使用也会带来多线程的问题,包括死锁(两个或者多个相互竞争的操作等待其中一个完成工作,却导致无论哪个操作都无法完成。在计算机科学中,涉及两个相互竞争操作的死锁称为僵局 (deadly embrace))。工作无法完成,因为很多线程都在等待永远无法释放的锁。

局部引用无法在线程间传递,只在用来创造它们的线程中有效。如果传递局部引用,则无法在不再需要它们时将其释放。您应该经常将局部引用转化为全局引用,因为多线程有可能用到同一个引用。

另一个问题是,如果被调用的 COBOL 程序在执行中遇到 THREAD 编译器选项问题,那么使用设计良好的多线程程序调用 Java 程序将会失败。


COBOL 的 THREAD 编译器选项

另一个黑色年代故事:十几年前,当我第一次使用 COBOL 时,THREAD 编译器选项尚不存在。现在,如果在多线程中运行 COBOL 程序,则需要使用 THREAD 编译器选项来编译所有 COBOL 程序。同一个程序会有单独的线程,例如,第一个线程用于程序的一个任务,第二个线程用于同一个程序的第二个任务,依此类推。

在使用这个编译器选项编写 COBOL 程序时,需要选择适当的连接语句和语言元素(包括声明,专用寄存器和子句),它们构成了 COBOL 程序的逻辑(参阅 参考资料)。请注意那些无法不能和编译器选项共用的语言元素。如果您编译的程序包含编译器选项不想要的元素,那么请将它们标出来。请注意,某些 COBOL 应用程序的使用取决于可能包含不想要的语言元素的子系统或者其他应用程序。

在多线程上处理限制的另一方法是,在(允许的)语言元素范围内工作。因为您的 COBOL 程序可以作为单独的线程在进程中运行,所以语言元素可以分析到两个不同的范围:运行单元范围或者程序调用实例范围。这两种类型的范围对决定在何处引用条目、该条目在存储中保存多久都非常重要。

在多线程的环境中,COBOL 运行单元是进程的一部分,该进程包含正在积极执行 COBOL 程序的线程。当 COBOL 运行单元运行时,语言元素存在于该线程中,并且对其他程序 (Java) 可用。它会继续存在,直到所有线程的执行栈都没有 COBOL 程序处于活动状态。

在线程中,可在单独的 COBOL 和非 COBOL 程序间传递控制权。例如,一个 COBOL 程序可以调用另一个 COBOL 程序或者 Java 程序。每个被单独调用的程序就是程序调用实例。特定程序的这些实例能够存在于给定的进程的多个线程中。语言元素只存在于特定程序调用中。

一个问题是,如果调用的 COBOL 程序在执行中遭遇到多线程程序有关的问题,使用 THREAD 选项调用 COBOL 程序将会失败。


多线程 SaaS 故障场景

一个公司成功构建了内部协作应用程序,没有出现多线程(死锁)问题,然后该公司将这些应用程序迁移到一个位于美国的外部 SaaS/供应商的主机数据中心。前几个月,程序运行顺畅,直到数据中心出现了一个小错误,系统崩溃了几天。

大量投诉蜂拥而至(您也可以想象到)。

供应商也在抱怨,因为公司没能够在错误出现后的两分钟内让 SaaS 协同应用程序恢复服务,公司与 SaaS 用户商定好的 SLA 中有这方面的保证。所有应用程序线程都处于死锁模式。

供应商让 SaaS 应用程序恢复工作需要花费几天的时间。他们无法提供解锁线程死锁的有效故障恢复。

如果供应商采取了以下积极措施,他们可以中止损害,解决问题,恢复系统,并告知客户。

中止损害

为了中止损害,供应商应该提前计划,准备采用 SaaS 应用程序作为自动故障恢复的实例。根据 SaaS 订购者和供应商之间的协议,SLA 应该准备就绪。

通知 SaaS 客户,在供应商解决问题时,应该同时在另一数据中心继续进行服务。

请记住,将客户置于混乱的情况下往往会导致对您的不利。

解决问题

供应商可以对故障进行提前计划:

  • 测试 SaaS 应用程序是否存在死锁和其他多线程问题。
  • 设置各个语言界面(COBOL 和 Java)的多线程阈值。
  • 安装多线程 SaaS 应用程序实例,允许将故障从一个数据中心转移到另一个数据中心。
  • 定期检查备用磁盘是否工作正常,并且没有错误。

恢复系统

下一个步骤就是进行恢复:

  • 下线数据中心已崩溃的系统。
  • 将多线程 SaaS 应用程序迁移到恢复系统。

然后测试恢复后的系统恢复力,确保将故障相对顺畅地转移到另一数据中心。在将它移动到生产环境中之前,应备份一个已恢复系统的副本。

通知客户

只要在故障数据中心恢复 SaaS 应用程序,供应商就应该通知客户以下信息:

  • 恢复已经完成。
  • SaaS 应用程序已经移动到生产环境。
  • SLA 条款(无条件信用、退款和一个终止机会)正如与 SaaS 订阅者协商的那样在继续执行。

结束语

在构建一个 SaaS 应用程序的计划中,应考虑解决多线程问题的最佳实践。还应该考虑使用多线程阈值来解决多线程问题。您需要组建一个由开发人员、管理人员、业务分析员和系统工程师组成的开发团队,在构建 SaaS 应用程序时,使他们能够轻松地解决多线程问题。

参考资料

学习

获得产品和技术

讨论

  • 加入 developerWorks 中文社区。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Cloud computing, Java technology
ArticleID=940192
ArticleTitle=在构建 SaaS 应用程序时定义一个多线程阈值
publish-date=08082013