好的设计是实现高度可伸缩的应用程序的基础。在应用程序的生存周期中,设计阶段所做的决策对应用程序可伸缩性的影响最大。
可伸缩性金字塔
正如可伸缩性金字塔所显示的,速度更快的硬件、软件和优化调整只是可伸缩性等式的一小部分。金字塔的底部是设计,它对可伸缩性的影响最大。沿着金字塔向上,因素的重要性逐渐降低,影响可伸缩性的能力也相应地减小。从金字塔可以看出,与硬件相比,好的设计能够为应用程序带来更大的可伸缩性。
设计可伸缩性时,主要目标是确保有效的资源管理。可伸缩性设计不仅限于应用程序的任何特定的层或组件。应用程序结构设计者必须从用户界面到数据存储区等各个角度考虑可伸缩性。进行设计选择时,以下五条可伸缩性设计戒律可能很有用。
进程等待的时间不应超出必要的长度。每当某个进程在某个时间段内使用资源时,另一个进程将无法在该时间段内使用该资源。可将进程分为两个单独的类别:同步和异步。
有时应用程序必须同步执行操作。某些操作可能需要等待某个操作返回结果后才能继续执行,或者可能需要验证某个操作是否成功以确保原子性。也就是说,与该操作关联的所有操作必须全部失败或成功,才能执行另一个操作。然而,当应用程序被限制在此方式时,资源便成为了给可伸缩性带来负面影响的争用源。
实现可伸缩性的一个方法是以异步方式执行操作。以异步方式执行操作时,长期运行的操作将排队等待以后由单独的进程完成。
例如,某些电子商务站点在结帐过程中执行信用卡验证。如果验证服务存在困难,则这可能成为高访问量电子商务站点上的瓶颈。对于必须以物理方式提供产品以完成订单的电子商务站点,该过程很适合用异步操作来完成。由于产品的所有权不是在在线交易期间从卖方转移到买方,零售商可以脱机完成信用卡验证。然后,应用程序可以在验证信用卡交易后向客户发送确认订单的电子邮件。
争用资源是所有可伸缩性问题的根本原因。不能满足需求的不充足的内存、处理器周期、带宽或数据库连接将导致应用程序无法伸缩,这并没有什么可奇怪的。
不论如何设计,所有分布式应用程序都占有一定数量的资源。除了通过不等待长期运行的操作来加速进程外,还可以采取其他措施避免资源争用。
应安排从充足到缺乏的资源使用。例如,如果执行的事务所涉及的资源缺乏并因此受争用的限制,则应尽量晚些使用这些资源。这样一来,早先中止的事务将不会阻止或延迟成功的进程使用这些资源。
尽量晚些获取资源,然后尽早释放它们。一个进程占用资源的时间越短,另一个进程就可以更快地获取资源。例如,应尽快将数据库连接返回到池。
如果可能,甚至不要使用争用的资源。有时,进程使用的事务在执行功能时不需要资源。例如,需要事务的方法与不需要事务的方法应分开放在不同的组件中,这样可避免在不需要时创建事务。
可交换性设计通常是最容易被忽略的减少资源争用的方法之一。如果两个或更多的操作可以任何顺序应用并且仍获得同样的结果,这样的操作就称为是可交换的。通常,可在缺少事务的情况下执行的操作适合这样的情况。
例如,一个繁忙的电子商务站点不断更新产品库存,可能会因产品的进出经历记录锁定争用。为避免这种情况,每个库存增减可以成为单独的库存交易表中的一个记录。数据库定期合计该表中的每种产品,然后用净库存变动更新产品记录。
每当可以一般化资源时,便使它成为了可互换的。相反,每当向资源添加详细状态时,就降低了它的可互换性。
资源池方案利用了可互换资源。COM+ 组件池和 ODBC 连接池都是可互换资源的资源池示例。
例如,如果数据库连接对特定用户是唯一的,则无法为其他用户汇集该连接。相反,要汇集的数据库连接应使用基于角色的安全性,后者将连接与通用凭据集关联。要使连接池运行,连接字符串中的所有详细信息必须相同。此外,应显式关闭数据库连接以确保它们尽快返回到池中。依赖自动断开连接功能将连接返回到池中是不好的编程做法。
可互换性概念支持参数将状态移出组件。要求组件在方法调用间维护状态会破坏可互换性,并最终给可伸缩性带来负面影响。相反,每个方法调用都应是独立的。当方法调用间需要状态时将状态存储在组件的外部。数据库是保存状态的最佳位置。当调用无状态组件的方法时,该方法需要的任何状态既可以参数形式传递,也可从数据库中读取。在方法调用的最后,通过将状态返回到方法调用方或将其写回数据库来保留状态。
可交换性超出了资源池的范围。Web 应用程序的服务器端页缓存很有可能增加它的可伸缩性。尽管个性化可以为用户提供独特的经历,但这样做的代价是创建的自定义表示形式对其他用户是无法重用的。
最后应对资源和活动进行分割。通过最小化资源间和活动间的关系,可以将因关系的一方占用的时间超过另一方而导致瓶颈的风险降至最低。相互依赖的两个资源将共存亡。
对活动进行分割可有助于减轻放置在高开销资源上的负载。例如,使用 SSL 将消耗大量的系统开销以提供安全连接。因而,明智的作法是仅将 SSL 用于真正需要高度安全性的页。此外,专用于该任务的 Web 服务器可处理 SSL 会话。
事务为分割活动提供了另一个机会。通过将不需要事务的方法与需要事务的方法分开,避免了将事务所需的系统开销不必要地强加给不需要事务的方法。
然而,分割并不总是一个好办法。分割可使系统更复杂。分割具有依赖项的资源可向操作添加大量昂贵的系统开销。
原文:http://msdn.microsoft.com/zh-cn/library/aa291873(VS.71).aspx