【IT168 技术文档】
本文通过介绍在当前 SaaS 应用中的特点和存在的问题,阐述如何运用最新的 IBM DB2 V9.5 中的 Q 复制、LBAC、工作负载管理等功能解决遇到问题。并且介绍如何运用 Nginx HTTP Server+Apache Http Server+TOMCAT+DB2 的组合构建出一个高性能、高伸缩性、低成本、高安全性的 SaaS 应用或者大规模网站应用解决方案。
SaaS 现在算得上 SOA 之外的另一个热门名词,SaaS 是 Software-as-a-Service(软件即服务)的简称,是随着互联网技术的发展和应用软件的成熟,而在 21 世纪开始兴起的一种完全创新的软件应用模式。
它是一种通过 Internet 提供软件的模式,厂商将应用软件统一部署在自己的服务器上,客户可以根据自己实际需求,通过互联网向厂商定购所需的应用软件服务,按定购的服务多少和时间长短向厂商支付费用,并通过互联网获得厂商提供的服务。用户不用再购买软件,而改用向提供商租用基于 Web 的软件,来管理企业经营活动,且无需对软件进行维护,服务提供商会全权管理和维护软件,软件厂商在向客户提供互联网应用的同时,也提供软件的离线操作和本地数据存储,让用户随时随地都可以使用其定购的软件和服务。对于许多小型企业来说,SaaS 是采用先进技术的最好途径,它消除了企业购买、构建和维护基础设施和应用程序的需要。
在这种模式下,客户不再象传统模式那样花费大量投资用于硬件、软件、人员,而只需要支出一定的租赁服务费用,通过互联网便可以享受到相应的硬件、软件和维护服务,享有软件使用权和不断升级,这是网络应用最具效益的营运模式。
SaaS 的“多重租赁”概念就是,多个公司将其数据和业务流程托管存放在 SaaS 服务商的同一服务器组上,相当于服务商将一套在线软件同时出租给多个公司,每个公司只能看到自己的数据,由服务商来维护这些数据和软件。也就是说,多个公司登录到同一网站,但登录后看到的界面和数据,每个公司都不相同。
“跨界混搭”这个术语起源于流行音乐,编曲者把两张唱片混编以后重新制作出一首新歌。这个概念应用在 SaaS 上,就是指把多个不同的在线应用软件服务搭建成为一种新型的整合服务。用户通常只需要登录一次就可以使用集成好的组合应用软件。
SaaS 解决方案具有的扩展性让用户能够在已存在的软件结构上,按需增加额外的工具或功能。还有一些扩展性例如可以扩展数据模型,提供个性化的用户界面以及其他更多自定制的扩展服务。
“垂直应用”不是 SaaS 的专用术语,它也应用于其他领域,通常是指为某一个领域(例如银行,医药等)建立一个专门的平台。虽然它已经在传统行业应用很多年了,但是相对来讲应用在 SaaS 中还是一个比较新的概念。
参数应用 (Parametric applications)
在传统软件模式下,如果软件的服务功能需要改变,那么相应的代码也需要重新编写。但是在 SaaS 模式下,用户可以通过输入新的参数变量,或者制定一些数据关联规则来开启一种新的应用。这种新式服务模式也被称为“参数应用”,“宏”或“自定制对象”,主要是因为这种应用程序可以让用户自己定制新的应用,而不需要懂软件编程。
SaaS 中模块的功能主要用于关闭或开启服务。在聚集了丰富功能的强大应用平台中,IT 经理可以像选择菜单那样任意地选择功能,关闭某些不需要用到的功能,也可以根据需求增加新的功能。 SaaS 服务商基于网络架构建立了自己的应用平台,模块的灵活性使得他们可以根据客户的不同需求,将功能复杂繁多的系统配置成适合客户的系统。
与传统软件模式相比,SaaS 具有低建设成本、低维护成本、低投入风险和低应用门槛等四大特点。
SaaS 给软件开发商打开了一个新的市场领域,就是软件应用可以像电信运营商提供给客户电信服务一样提供相应地企业管理软件服务;软件开发商可以成为软件运营服务提供商,而软件运营服务具有以下三个特点:
- 软件的功能为多个组织所重用和共享。在传统的软件中,一个软件的功能为单个个人或组织所拥有,每个软件实例只管理这个个人或组织内用户的数据。在软件服务的模式下,同一个软件的功能为多个组织所重用和共享,同一个软件实例同时管理多个用户或组织的数据。如何将不同用户和组织的数据进行有效管理将是一个具有挑战性的课题。
- 所有软件活动统一管理。传统的软件维护困难的主要原因之一是软件活动分散于用户端,软件版本不统一,软件维护工作需要根据不同的版本进行不同的操作。软件服务的模式把分散的软件集中起来统一管理,这样既提高了工作效率,同时也降低了成本。
- 基于互联网访问和管理应用软件。在当今时代,把软件转变成服务的一个有利且必备的条件是互联网技术。通过网络来配置管理提供给用户的服务,软件服务提供商能够把这种服务提供给全球范围内的任何用户;分散在各地的用户都可以享受同一种优质的服务,而不受时间和地域的限制。毫不夸张地说,互联网的发展促成了软件服务这种软件发布的模式,大大改变了人们的生活和工作方式。
SaaS 应用还面临着很多挑战,这其中包括技术上存在的难点、缺乏杀手级的应用、商业模式的不清晰以及对于传统营销模式的颠覆。我们在这里主要阐述的是 SaaS 应用所面临技术上的挑战。
当一个应用系统在初期运行阶段的时候,由于用户少、数据量少;所以应用系统能够提供非常好的服务质量(如响应速度相当快),给用户的感觉就是应用系统很快。当随着用户数的上升、数据量的增大,应用系统的性能急剧下降,具体的反应就是应用系统很慢并且老是出错、甚至系统经常没有响应。而对于面对互联网的应用系统 Saas 应用出现这样的情况将更加的频繁,然而出现这个问题的症结在哪呢?我们怎么样来避免它呢?
一个现代的应用系统基本上都是建立在 B/S 架构的基础上,通过具体的层次来划分看基本上分为以下几层:
- 界面展现层
Ajax 技术在这方面带来了创新,通过 JavaScript+HTML+XML( 或者 JSON),在浏览器里实现了与桌面应用等同的界面效果 , 带来了极好地交互体验,以及很容易与后台的业务逻辑层模块进行交互;并且很容易避免由于采用 J2EE 架构中的 JSP 技术而给后台的应用服务器带来多余的压力等问题,让应用服务器专注于处理业务逻辑而不关心产生具体的页面;以及避免了界面交互性不友好的弊病。
- 业务逻辑层
在 J2EE 架构中,我们一般采用 Servlet 或者 EJB 来操作具体的企业信息系统(如数据库)或者消息系统(如 JMS)来实现具体的业务逻辑。由于 EJB 的缺陷以及 Spring 技术的兴起 , 业务逻辑层基本上都采用 Servlet+Spring 来实现。
- 数据层
比如说是关系型数据库。有些架构中可能会是指相应访问数据库的逻辑封装层(如采用 Hibernate/ibitas 技术来访问数据库封装层)。
从上面三层就能很容易演化出下图所示的软件系统架构:
由于界面表现层的代码运行在用户端机器上的浏览器中,并且通过这个软件系统架构图我们可以看到要使一个 SaaS 应用成为一个能够承载高并发、高数据量的应用系统,关键就是使 SaaS 应用所依赖的底层系统具有非常高的性能和伸缩性,即需要有高性能、高伸缩性的数据库系统,高性能、高伸缩性的中间件 ( 如 J2EE 应用服务器 )。我们如何去解决这个问题呢?请详细参考:如何实现高性能、高伸缩性的架构
SaaS 用户很多都是中小企业,他们采用 SaaS 应用后对于安全的最担心的地方可以分成以下几个部分:
- 数据传输的安全性
由于用户采用浏览器并且通过互联网访问部署在软件运营商端的 SaaS 应用,用户需要 SaaS 应用的软件提供商保证在互联网上传输的数据的是安全的、是可靠的,因为这些传输数据(如客户资料、财务资料等)对他们来说非常的重要。
众所周知,我们可以采用 CA 证书以及 SSL v3 技术来保障这一点,并且在 HTTP SERVER 以及 J2EE 应用服务器都支持 HTTP SSL 功能,从而可以保障客户的数据传输安全性。但是通过 HTTP SERVER 来实现 SSL 功能的效率太低,如果我们采用组建 VPN 网络的话对运营商来说成本太高,我们需要采取什么样的措施来解决这个问题呢?请详细参考:如何实现高性能、高伸缩性的架构
- 数据存储的安全性
在软件运营商端的 SaaS 应用是给不同客户来使用的,也就是说是给不同的企业来使用的。对用户来说他就非常担心其它企业是否可以看到他们企业的数据。
并且这里还存在一个非常大的挑战就是,由于数据是存放在软件运营商端的数据库系统中,在数据库系统中都存在一个超级用户,而这个数据库超级用户都是软件运营商的所拥有,由于数据对用户来说非常重要,用户对此就会产生这样的一个需求,就是不希望软件运营商的数据库管理员也能够查看和访问他们的数据。我们需要采取什么样的措施来解决这个问题呢?详细请见:DB2 V9.5 的安全控制功能
- 系统是否很容易被攻击?
请详细参考:如何实现高性能、高伸缩性的架构
由于非常大量的用户都会使用软件运营商提供的 SaaS 应用,用户就会有以下几个担心:
软件运营商提供的 SaaS 应用是否经常很容易崩溃以及无法提供服务?
软件运营商提供的 SaaS 应用的崩溃以及无法提供服务的主要原因是以下几个:
- 一是应用代码有问题;
- 二是数据库服务器在高并发用户的情况经常崩溃;
- 三是应用服务器经常崩溃或者一个应用服务器无法承受如此大的压力。
我们需要采取什么样的措施来解决这个问题呢?请详细参考:如何实现高性能、高伸缩性的架构
数据是否能够可靠的存储?
由于数据是保存在数据库系统中,数据库系统是否能够提供一个很好的数据备份 / 恢复、数据卸载 / 挂接的功能。我们需要采取什么样的措施来解决这个问题呢?请详见参考资料中 DB2 的表分区以及备份 / 恢复功能的相应文档。
就像中国移动公司它划分了三个品牌全球通、神州行、动感地带,这三个品牌提供了不同的服务质量。而对于提供 SaaS 应用的软件提供商来说它也面临这样一个问题,就是不同的客户需要不同的服务质量从而付出不同的资费,如不同的客户需要不同的响应时间,形象一点来说就好比有这样的一个场景,有 5 个用户同时发起 5 个请求到数据库端,而这个 5 个用户具有不同的服务等级,对于数据库端来说它就应该以更多的资源服务服务等级最高的用户,以较少的资源服务服务等级较低的客户,从而使不同服务等级的客户具有不同的服务质量。这样能够使软件运营商的 SaaS 应用更具有适应性、更具有竞争力、更能创造价值。我们需要采取什么样的措施来解决这个问题呢?详细的解决方式请见:DB2 V9.5 的工作负载管理功能的阐述。DB2 V9.5 的工作负载管理功能
对于 系统如何提供不同的服务质量 的相应的需求,可以概述成以下的叙述:一个 SaaS 应用程序可能由三个不同用户使用。一个用户可能希望响应时间平均值小于 2 秒,而其他两个用户可能对 5 秒的响应时间就感到满意了。并且对于达到响应时间平均值小于 2 秒的用户收取较多的资费,而对于达到 5 秒的响应时间的用户收取较低的资费。
并且由于 SaaS 应用的特点(如高并发),导致它所依赖的数据库活动量非常大,系统资源(如 CPU、I/O 和内存)的争用情况非常的普遍,如果要达到上面所述的服务质量将非常的困难,为了实现上面所述按需提供 SaaS 用户所需要的服务质量功能,我们将需要利用 DB2 V9.5 中提供的工作负载管理引擎。通过利用 DB2 V9.5 中的工作负载管理引擎将轻松的达到我们所需要的功能即针对不同等级的用户按需提供不同的服务质量。
DB2 V9.5 的工作负载管理功能使您可以更深入地洞察系统的运行情况并更好地控制资源和性能。DB2 V9.5 的这项功能执行以下任务:
- 通过使用工作负载定义自动标识工作、将工作负载分配给服务类并将资源分配到每个服务类,可以将工作划分为易管理的逻辑组。您可以捕获详细的工作负载概要文件和性能信息,以帮助优化您的工作负载定义和服务类定义。
- 您可以通过成本、时间和并行性阈值来控制执行情况,这使您可以控制流氓查询并有助于达到服务级别协议(SLA)目标。通过使用阈值,系统可以自动对不良情况作出反应或在它发生前进行预测。当您控制了长时间运行且复杂的查询的影响后,您就可以使事务保持平稳运行。
- 您可以跟踪处理的每个阶段,以便可以为用户提供最新的状态信息。
下图显示如何评估发送至数据服务器的多个请求、如何将它们分配到特定的工作负载以及如何在适用的服务类中执行这些请求。不能与您定义的工作负载匹配的请求将分配到缺省工作负载,然后在缺省服务类中执行此工作负载。
SLA 是组之间的一个正式协议,它定义组之间的期望值并包含服务、优先级和职责等各项的目标。SLA 目标通常使用响应时间目标来表示。例如,特定的“人力资源”报表可能需要在平均 5 分钟内运行完成。
增强的 DB2 工作负载管理功能可以帮助您标识一组已定义的数据库活动并将它们隔离在自己的执行环境中,您可以对这些活动分配达到您的目标所需要的适当资源。在环境或服务类中,您可以显式管理系统资源,以便较重要的资源可供较高优先级的工作使用,并可以控制或消除与较低优先级工作的争用情况。
您通过对每种不同类型的客户使用服务类来隔离数据服务器上的活动。例如,您可以按组来设置工作负载,然后对该组分配一个具有较少资源的不同服务类。在您设置服务类后,您可以轻松地收集并监视聚集活动统计信息,以确保满足每个客户的 SLA 目标。从而使您可以根据接收到的服务级别对每个客户进行收费。
示例如下:我们假设一个 SaaS 应用程序可能由三个不同用户使用。用户 1 可能希望响应时间平均值小于 2 秒,而用户 2 和用户 3 可能希望 5 秒之内的平均响应时间;从这可以看出这里有两个服务等级,服务等级 1 需要的服务质量是使服务的响应时间在 2 秒之内,服务等级 2 需要的服务质量是使服务的响应时间在 5 秒之内。于是我们在 DB2 V9.5 中定义两个服务类:
ServiceClass1(这个服务类具有更多的系统资源)和ServiceClass2(这个服务类具有较少的系统资源);然后把 ServiceClass1 赋给用户 1,ServiceClass2 赋给用户 2 和用户 3。通过这样的配置,我们就能够实现所需要的功能。
在现今最常见的采用 J2EE 架构的三层架构应用系统中,我们经常会运用 J2EE 应用服务器提供的安全控制功能,来控制不同用户具有访问不同业务逻辑模块(如用户 1 只能访问某个 Servlet、用户 2 只能访问某个 EJB 或者某个 EJB 提供的方法),从而实现了相应的权限控制;然后在访问数据库的时候,我们通常会利用 Spring 框架或者 J2EE 应用服务器提供的连接池来访问数据库,从而可以实现连接的复用而降低了经常建立物理连接的开销。相应的架构图如下图所示:
但是在使用系统提供的连接池功能的时候我们都是使用数据库系统提供的某个用户名、密码来访问数据库,这样就失去了在数据库系统这一级提供的丰富的安全控制功能;如在数据库系统中我们建立了 DBUSER1 具有相应的特权,而 DBUSER2 具有其它相应的特权;然而采用上图所示的架构功能,这样对数据库系统来说仅仅只有一个 DBUSER1 这个用户来访问自己;然而对于整个系统来说有 USER1 、USER2、 USER3 这三个用户需要在数据库系统这一级进行详细的安全控制。这样的架构就导致整个系统失去了强大的数据库安全能力来控制对数据的访问。
很多软件开发商为了避免这样的问题,一般都会在数据库系统中建立相应的表结构来控制相应的访问权限或者通过 J2EE 应用服务器提供的一些功能来进行用户上下文的切换,但是这样的方法带来的代价就是性能的开销以及控制的粒度不够,特别是无法实现对表中数据访问进行行一级的控制,如用户 1 只能查看表 A 中的某些行,而用户 2 只能查看表 A 中其它的一些行。
特别针对 SaaS 应用来说,它是给不同客户来使用的,也就是说是给不同的企业来使用的。就必须实现针对行一级访问的安全控制,即客户 A 和客户 B 运行同样的一条 SQL 语句,然后数据库系统必须返回符合相应的权限的数据给不同的客户即客户 A 和客户 B 看到的数据是不一样;并且 SaaS 应用必须还要实现 SaaS 应用的软件运营商的数据库管理员也不能够查看数据库系统中的数据,这样才能够让用户放心,让用户感受到只有它自己才能够查看到专属它自己的数据而其它任何人是看不到的即使是软件运营商的数据库管理员。
为了实现这样的两个主要功能,以及避免图3 所示架构的系统所带来的缺陷,我们需要利用 DB2 V9.5 中提供的基于标号的访问控制 (LBAC) 和可信上下文增强这两个功能来实现相应的解决方案 . 通过利用 DB2 V9.5 提供的这两个功能我们稍微修改下架构就可以解决 SaaS 应用以及其它应用所面临的问题。如下图所示:
改进后的架构图与原有的架构图的区别仅仅就是在数据库系统采用了 DB2 V9.5,并且启用了 DB2 V9.5 的 LBAC 和可信上下文功能;然后简单的修改在 J2EE 应用服务器上相应的代码就可以实现充分利用 DB2 V9.5 提供的完整的安全控制功能。当利用了 DB2 V9.5 这两个功能后,相应的流程就改变成这样:
- 我们在 DB2 V9.5 中,针对企业 1、企业 2、企业 3 建立相应的用户名 DBUSER1、DBUSER2、DBUSER3。并针对这些用户建立相应的 LBAC 控制信息,从而可以实现这些用户能够应用同一条 SQL 就能访问出符合不同用户权限的不同的数据。
- 我们确定在 J2EE 应用服务器连接池中连接 DB2 V9.5 的用户名 (user) 和密码 (password),并在 DB2 V9.5 建立此用户名和密码。并且利用 DB2 V9.5 提供的 TRUSTED CONTEXT 语句建立相应的可信上下文。
- 在 J2EE 应用服务器配置相应的用户名 (DBUSER1、DBUSER2、DBUSER3),并且在 J2EE 应用服务器上实现这三个用户的认证来自于 DB2 V9.5 的对应的 DBUSER1、DBUSER2、DBUSER3 这三个用户。
- 对 J2EE 应用服务器的 DBUSER1、DBUSER2、DBUSER3 这三个用户在应用服务器中的不同权限,如依照 J2EE 安全标准实现这三个用户具有访问不同 SERVLET 或者 EJB 的权限机制。
- 利用开源的连接池模块(或者利用 Spring 框架),实现一个连接池。
包装以下两块代码:
// Create a DB2ConnectionPoolDataSource instance
com.ibm.db2.jcc.DB2ConnectionPoolDataSource dataSource =
new com.ibm.db2.jcc.DB2ConnectionPoolDataSource();
// Set properties for this instance
dataSource.setDatabaseName ("STLEC1");
dataSource.setServerName ("v7ec167.svl.ibm.com");
dataSource.setDriverType (4);
dataSource.setPortNumber(446);
java.util.Properties properties = new java.util.Properties();
// Set other properties using
// properties.put("property", "value");
// Supply the user ID and password for the connection
String user = "user";
String password = "password";
// Call getDB2TrustedPooledConnection to get the trusted connection
// instance and the cookie for the connection
Object[] objects = dataSource.getDB2TrustedPooledConnection(
user,password, properties);
|
清单 2. 重用已经存在的信任连接
// The first item that was obtained from the previous getDB2TrustedPooledConnection
// call is a connection object. Cast it to a PooledConnection object.
javax.sql.PooledConnection pooledCon =
(javax.sql.PooledConnection)objects[0];
properties = new java.util.Properties();
// Set new properties for the reused object using
// properties.put("property", "value");
// The second item that was obtained from the previous getDB2TrustedPooledConnection
// call is the cookie for the connection. Cast it as a byte array.
byte[] cookie = ((byte[])(objects[1]);
// Supply the user ID for the new connection.
String newuser = "newuser";
// Supply the name of a mapping service that maps a workstation user
// ID to a z/OS RACF ID
String userRegistry = "registry";
// Do not supply any security token data to be traced.
byte[] userSecTkn = null;
// Do not supply a previous user ID.
String originalUser = null;
// Call getDB2Connection to get the connection object for the new
// user.
java.sql.Connection con =
((com.ibm.db2.jcc.DB2PooledConnection)pooledCon).getDB2Connection(
cookie,newuser,password,userRegistry,userSecTkn,originalUser,properties);
|
- 用户通过浏览器访问 SaaS 应用,将通过 J2EE 应用服务器提供的安全功能,访问相应的模块;当需要访问数据库的时候,应用服务器从连接池取得一个连接,然后切换到用户访问 J2EE 应用服务器输入的用户;如用户 DBUSER1 访问 J2EE 应用服务器的服务,当访问应用服务器的连接池模块的时候,将利用连接池中用 USER 用户取得的物理数据库连接,然后调用相应的方法把连接的标识名从 USER 用户切换到 DBUSER1 用户。
- 用户(如对应的数据库用户名为 DBUSER1)访问 DB2 V9.5 中的数据的时候,DB2 V9.5 将运用 LBAC 功能,使此用户运行的 SQL 语句只会返回符合它所具有权限的数据。
上面所述的步骤解决了相应的权限控制问题,但是如何避免 SaaS 应用的软件运营商的数据库管理员能够查看相应客户数据的问题以及 DB2 V9.5 这些机制的原理到底是如何的呢?请阅读下面两个小节的简要阐述。
可以在 DB2 V9.5 数据库服务器上创建一个可信上下文对象,该对象允许中间层服务器建立与数据库的显式可信连接。在建立显式可信连接后,中间层服务器可以将该连接的当前用户标识切换至新的用户标识,而不需要在数据库服务器中认证新的用户标识。
在建立与 DB2 V9.5 的连接时,通过在应用程序内发出显式请求可以建立显式可信连接。为了成功建立连接,安全管理员必须使用 CREATE TRUSTED CONTEXT SQL 语句以及与要建立的连接的属性匹配的那些属性来定义可信上下文。
- 安全管理员通过使用 CREATE TRUSTED CONTEXT 语句在服务器中定义可信上下文。例如清单 3 中所示代码:
清单 3. CREATE TRUSTED CONTEXT 语句示例
CREATE TRUSTED CONTEXT MYTCX
BASED UPON CONNECTION USING SYSTEM AUTHID NEWTON
ATTRIBUTES (ADDRESS '192.0.2.1')
WITH USE FOR PUBLIC WITHOUT AUTHENTICATION ENABLE;
|
- 要建立可信连接,请使用下面的 API:getDB2TrustedPooledConnection() 和 getDB2TrustedXAConnection();
- 切换至另一个经过认证或未经过认证的用户,请使用下面的 API:getDB2Connection() 和 reuseDB2Connection()。
LBAC 是一种基于标号的访问控制的安全特性,从而可以实现基于行、基于列、基于表的访问控制 ; 基于行和基于列的访问控制可以单独使用也可以混合使用。LBAC 是一种极具伸缩性的数据访问控制解决方案。
LBAC 基于一个新的安全管理员角色,在 DB2 V9.5 中增加了 SECADM 这个权限,它包含了相应的安全相关的特权,SECADM 权限仅仅能够被具有 SYSADM 权限的用户即系统管理员赋予。SECADM 权限是具有相应的能力实现 LABC 解决方案的能力,具有以下的能力:
清单 4. Create and drop security label components
Create and drop security policies
Create and drop security labels
|
清单 5. Grant and revoke security labels
Grant and revoke LBAC rule exemptions
|
一个具有 SYSADM 权限的用户(即系统管理员)缺省不具有 SECADM 权限,也就意味着具有 SYSADM 权限的用户如果没有被赋于相应地安全标号权限或者 SECADM,系统管理员是不能够查看相应的敏感数据的和进行相应的访问控制权限的赋值,DB2 V9.5 这个特性就实现了在 SaaS 应用中即使是 SaaS 应用的软件运营商的系统管理员也不能够查看用户数据的功能。
为了能够充分理解 DB2 V9.5 这种功能,这里将用一个例子阐述基于行访问控制的实现。
详细的例子请点击这个链接:DB2 基于标号的访问控制实用指南
我们要实现了高性能、高伸缩性的架构特别需要考虑成本因素,即要考虑硬件成本,也要考虑软件成本。由于数据对整个应用来说是至关重要的,所以我们需要选用一个高性能、高靠性的硬件(如小型机),数据库也要选用一个高性能、高可靠性、易维护的 DB2 数据库。而对于应用服务器这一块我们选用开源技术的组合,选用 Tomcat 和 Intel 芯片的刀片服务器。通过相应的组合实现一个性价比很高的系统。
注:各个服务器的网络连接建议采用千兆网络进行连接,采用单独的交换机进行网络交换。
我们在设计 J2EE B/S 应用系统的架构时,最喜欢采用 2 台服务器做为具体的部署架构;一台服务器做为应用服务器,一台服务器做为数据库服务器;并且由于数据的重要性,我们基本上会把一台具有较高价格、较高性能、高稳定性的服务器做为数据库服务器,并且数据库服务器安装 AIX 操作系统;一台配置较低、价格较低的服务器做为应用服务器,并且应用服务器安装 LINUX 操作系统。我们假设数据库服务器具有 8G 内存、4 颗 CPU(IBM Power 5 芯片小型机);应用服务器具有 4G 内存、2 颗 CPU(Intel 芯片的刀片服务器 )。
相应的架构简图如下所示:
注:Tomcat 服务器所依赖的 JDK,安装 JDK 1.6 64 bit,并且应用的 SQL 语句和程序以及 DB2 V9.5 和 Tomcat 都进行了较好的优化。
当用户数比较少的时候整个系统的运行效率非常高,但是随着用户数的上升,性能急剧下降。通过分析会发现 DB2 V9.5 的性能较好负载并不大,瓶颈在于 Tomcat 应用服务器负载很大 , 并且机器的利用率也很高。为了提高性能,我们马上就想到需要对应用服务器做均衡负载,于是我们就得到下面所示的架构:5 台服务器架构。
我们再购买 3 台新的 Intel 芯片的刀片服务器,每个新的机器配置为 4G 内存、2 颗 CPU;每个机器都安装 Linux 操作系统。我们选用一台机器做均衡负载器,并且在这台机器上安装 Apache Http Server 做为均衡负载软件,并且我们在应用上把相应的静态页面(如 HTML、JS、图片、Flash 放到这台 Apache Http Server 这台机器上),以提升系统的响应时间;另外两台新的机器还是安装 Tomcat 应用服务器。如何使用 Apache Http Server 和 Tomcat 做集群和均衡负载请参考:Apache HTTP Server 与 Tomcat 的三种连接方式介绍。并且采用 Apache Http Server 后,使我们的系统更加能够抵御非法攻击。
相应的架构图如下:
这样的架构在一定量的高并发情况下,表现出良好的性能;但是随着并发数的继续增加,通过分析发现,DB2 V9.5 的机器的压力很大、性能表现不好;而 Apache Http Server 服务器的压力并不是特别大;并且 Tomcat 应用服务器的压力也不大,并且内存也消耗不高;为了提高整个系统的性能和 DB2 数据库的可靠性和让 DB2 数据库提供一个可靠的、持续的服务;于是我们需要优化系统,在 J2EE 应用这一块增加 memcache(内存缓冲技术)并且对 DB2 数据库 HA(新增加一台配置较低的数据库服务器,配置为 4G 内存,2 颗 CPU),防止数据库出现单点失效问题。于是就出现了下面所示的架构:改进型 5 台服务器架构
采用此种架构后,性能得到的一定的提升,但是随着并发数目的进一步的提升,系统又开始变慢,通过分析发现 DB2 V9.5 的压力降了下来,并且性能较好;但是 Tomcat 应用服务器的性能较低,经过技术分析我们可以看到每台 Tomcat 应用服务器的所采用内存缓存技术在极端情况下都是缓冲了同样的数据,这样就导致所消耗的内存太大,导致给每个 Tomcat 应用服务器所用的内存过少,并且被消耗了多余的 CPU;于是我们需要更新内存缓存技术,最好有一个单点让我们来进行缓存数据。于是我们需要采用专门的机器来做为内存缓存。于是演化成下面所示的架构:7 台服务器架构。
于是我们购买了新的一台机器(4CPU,8G 内存),在这台机器上安装 Linux 操作系统,并部署相应定制开发的内存缓冲软件。
采用此种架构后,性能得到了提高,但是并发量继续上升的话,Tomcat 应用服务器的性能降低,于是我们需要继续购买与原有 Tomcat 应用服务器等同配置的硬件 (4G 内存,2 颗 CPU). 进行进一步的集群,当我们把 Tomcat 应用服务器的集群规模做大后,发现 Apache Http Server 瓶颈和数据内存缓冲服务器瓶颈出现,于是我们需要对 Apache Http Server 服务器做集群,并且对内存缓冲技术进行进一步的升级即能够把数据的缓冲根据相应的请求信息(如根据不同的客户群进行 HASH 算法),把客户群 1 的内存缓冲数据缓冲分布到内存缓冲服务器 1 上,把客户群 2 的内存缓冲数据分布到内存缓冲服务器 2 上。并且 DB2 V9.5 数据库也将承受不了相应的压力,我们需要对 DB2 V9.5 进行进一步的优化,把数据库分成两种,一种是专门做只读的数据库,一种是专门做只写的数据库。于是就出现了下面图 9 所示的架构。
Apache Http Server 群集和内存缓冲数据服务器群集架构
于是我们需要购买一台机器安装 Nginx Http Server (4G 内存、2 颗 CPU,安装 Linux 操作系统)做更高层次的集群,Nginx Http Server 是一种更加轻量级的 HTTP SERVER,它能够承受比 Apache Http Server 更高的并发压力,举个形象的例子来说 Apache Http Server 能够承受 3000 并发压力的话,Nginx Http Server 就能够承受 30000 个并发压力。
此架构具有多个数据库,并且一个主数据库专门做写操作,然后发生变化的数据通过 Q 复制功能,把日志复制到相应的从数据库上进行数据的更新,这些从数据库专门做数据库的读操作;并且主数据库最好对应 3 个左右的从数据库;如果随着并发用户数继续上升的话,发现数据库的压力很大,我们就需要引入多个主 - 从配置数据库,并且根据相应的信息(如用户群 1 的数据分布在主数据库 1 上,用户群 2 的数据分布在主数据库 2 上)。相应的架构如下所示:最终的架构
Nginx Http Server 的均衡负载配置请参考:安装 Nginx 做为均衡负载器
相应的思路如下:
- 我们把我们应用的用户群体划分成几大类,如我们把来自用户 1(即企业 1)到用户 n(即企业 N)的数据全部存储在数据区 1,把来自用户 n+1( 即企业 N+1) 到用户 2*n( 即企业 2*n) 的数据全部存储在数据库 2。每个数据区配置 4 个数据库 DB2 V9.5 数据库服务器,一个数据库做为主数据库(做为只写数据库),其它 3 个做从数据库(做为只读数据库),主数据库的数据发生变化的话通过 Q 复制把日志复制到其它三个数据库并重做日志,在从数据库更新变化的数据;并且每个数据区配置一个内存数据缓冲服务器群集,做数据缓冲。并且对用户的 ID 号,产生相应的 HASH 值,从而使用户能够对应到唯一一个数据区;
- 当某个用户通过在最外面的硬件均衡负载器(如 F5),并且此硬件均衡负载器能够做一层抵制攻击的防犯。硬件均衡负载器把这个用户的负载转发到某个 Nginx Http Server 负载器上。Nginx Http Server 这个均衡负载器把这个请求转发到某个 Apache Http Server 上;
- Apache Http Server 再把这个请求转发某个 Tomcat J2EE 应用服务器上,Tomcat J2EE 应用服务器得到此用户的 ID 信息,并得到相应的 HASH 值,就知道了此用户将需要操作哪个数据库,从而得到相应的数据区号;
- 如果此请求是只读请求信息,并且如果这个请求所需要的数据从内存缓存得到即可,则应用将先从内存缓存器服务器得到相应的数据信息如果内存缓冲不存在则去操作某个从数据库查询出相应的数据信息并更新内存缓冲;如果这个请求所需要的数据必须从数据库中获取,则去操作某个从数据库查询出相应的数据信息。
- 如果此请求是做事务的请求,则应用操作主数据库进行数据的更新。并根据需要来判断是否需要更新内存缓冲。
此种架构,存在大量的 Tomcat 应用服务器,可以根据需要增加相应的应用服务器进行性能的提升,但是由于存在大量的 Tomcat 应用服务器就会带来大量的管理问题,我们需要自己利用 JMX 来开发相应的模块来管理如此众多的 Tomcat 服务器或者可以把 Tomcat 应用服务器替换成 Webspher Application Server v6.1,来利用 WAS 强大的管理功能。
并且这个架构还带来了一个这样的好处就是能够把负载请求均匀的分发到不同的 Apache Http Server 服务器和 Tomcat 服务器,所以我们可以轻松的启用 SSL 机制来实现用户的数据在网络上的安全传输而不用考虑一台服务器是否能够承受的住。