服务器系统的扩展,【系统架构】服务的扩展性(上)

在编写一个应用时,我们常常考虑的是该应用应该如何实现特定的业务逻辑。但是在逐渐发展出越来越多的用户后,这些应用常常会暴露出一系列问题,如不容易增大容量,容错性差等等。这常常会导致这些应用在市场的拓展过程中无法快速地响应用户的需求,并最终失去商业上的先机。

我们先来理解两个名词功能性需求和非功能性需求:功能性需求用来提供对业务逻辑的支持;而非功能性需求则是一系列和业务逻辑无关,却可能影响到产品后续发展的一系列需求。这些需求常常包括:高可用性(High Avalibility),扩展性(Scalability),维护性(Maintainability),可测试性(Testability)等等。

而在这些非功能性需求中,扩展性可能是最有趣的一种了。因此在本文中,我们将对如何编写一个具有高可扩展性的应用进行讲解。

什么是扩展性

假设我们编写了一个Web应用,在短时间内就吸引了大量的用户。但是由于我们在编写该应用时并没有期望它来处理这么多用户的请求,因此它的运行速度越来越慢,甚至可能出现服务没有响应的情况。频繁发生这种事情的结果就是,用户将无法忍受该应用经常性地宕机,并将寻找其它类似应用来获得类似的服务。

该应用所缺少的能够根据负载来对处理能力进行适当扩展的能力便是应用的扩展性,而其衡量的标准则是处理能力扩展的简单程度。如果您的应用在添加了更多内存后就能运行得更好,或者通过添加一个额外的服务实例就能解决服务实例过载的问题,那么我们就可以说该应用的扩展性非常好。如果为了处理更多的负载而不得不重写整个应用,那么应用的开发者就需要在多多注意应用的扩展性了。

当然,一个成功的应用不应该仅仅拥有高扩展性,而是应该在一系列非功能性需求上都做得很好。例如您的应用不应该有太多的Bug,也不应该有特别严重的Bug,以避免由于这些Bug导致您的用户无法正常使用应用。同时您的应用需要拥有较好的用户体验,这样才能让这些用户非常容易地熟悉您的应用,并产生用户粘性。

应用的扩展方法

好的,让我们重新回到扩展性这个话题上来。导致一个软件需要扩展的最根本原因实际上还是其所需要面对的吞吐量。在用户的一个请求到达时,服务实例需要对它进行处理并将其转化为对数据的操作。在这个过程中,服务实例以及数据库都需要消耗一定的资源。如果用户的请求过多从而导致应用中的某个组成所无法应对,那么我们就需要想办法提高该组成的数据处理能力。

提高数据处理能力的方法主要分为两类,那就是纵向扩展及横向扩展。而这两种方法所对应的操作就是Scale Up以及Scale Out。

纵向扩展表示在需要处理更多负载时通过提高单个系统处理能力的方法来解决问题。最简单的情况就是为该系统提供更为强大的硬件。例如如果数据库所在的服务器实例只有2G内存,进而导致了数据库不能高效地运行,那么我们就可以通过将该服务器的内存扩展至8G来解决这个问题:

133164591_1_20180516124633441

上图所展示的就是通过添加内存进行纵向扩展,以解决数据库所在服务实例IO过高的情况:当运行数据库服务的服务器所包含的内存不能加载数据库中所存储的最为常见的数据时,其会不断地从硬盘中读取持久化到磁盘中的内存页面,从而导致数据库的性能大幅下降。而在将服务器的内存扩展到8G的情况下,那些常用数据就能够长时间地驻留在内存中,从而使得数据库所在服务实例的磁盘IO迅速回复正常。

除了通过硬件方法来提高单个服务实例的性能之外,我们还可以通过优化软件的执行效率来完成应用的纵向扩展。最简单的示例就是,如果原有的服务实现只能使用单线程来处理数据,而不能同时利用服务器实例中所包含的多个CPU核心,那么我们可以通过将算法更改为多线程来充分利用CPU的多核计算能力,成倍地提高服务的执行效率。

但是纵向扩展并非总是最正确的选择。影响我们选择的最常见因素就是硬件的成本。我们知道,硬件的价格通常与该硬件所处的定位有关。如果一个硬件是当前市场上的主流配置,那么由于它已经大量出货,因此平摊的研发成本在每件硬件中已经变得非常小。反过来,如果一个硬件是刚刚投入市场的高端产品,那么每件硬件所包含的研发成本将会非常多。因此纵向扩展的投入性能比曲线常常如下所示:

133164591_2_20180516124633488

也就是说,在单个实例优化到一定程度以后,再花费大量的时间和金钱来对单个实例的性能进行提高已经没有太多的意义了。在这个时候,我们就需要考虑横向扩展,也就是使用多个服务实例来一起提供服务。

就以一个在线的图像处理服务为例。由于图像处理是一个非常消耗资源的计算过程,因此单个服务器常常无法满足大量用户所发送的请求:

133164591_3_20180516124633816

就像上图中所展示的那样,虽然我们的服务器已经安装了4个CPU,但是在单个服务器实例提供服务的情况下,CPU使用率还是一直处于警戒线之上。如果我们再在应用中添加一个相同的服务器来共同处理用户的请求,那么每台服务器的负载将会降到原有负载的一半左右,从而使得CPU使用率保持在警戒线之下。

在这种情况下,该服务所提供的一系列其它功能也随之得到了扩充。例如对处理结果进行保存的功能的性能也将变成原来的两倍。只是由于我们暂时并不需要这种扩充,因此该部分性能的增强实际上是毫无用处的,甚至造成了服务资源的浪费:

133164591_4_20180516124634332

从上图中可以看到,在没有横向扩展之前,橙色组成的负载已经达到了90%,接近单个服务实例的极限。为了解决这个问题,我们再引入一个服务器实例来分担工作。但是这样会导致其它几个本来资源利用率就已经不高的组成的利用率降得更低。而更为正确的扩展方式则是只扩展橙色组成:

133164591_5_20180516124634394

从上面的讲解中可以看出,横向扩展实际上包含了很多种方式。相应地,《The Art of Scalability》一书则介绍了一个横向扩展所需要遵守的AKF扩展模型。根据AKF扩展模型,横向扩展实际上包含了三个维度,而横向扩展解决方案则是这三个维度上所做工作的结合:

133164591_6_20180516124634425

上图中展示了AKF扩展模型的最通用的表示形式。在该图中,原点O表示的是应用实例并没有能力执行任何横向扩展,而只能通过纵向扩展来提高它的服务能力。如果您的系统朝着某个坐标轴的方向前进,那么它就将得到一定程度的横向扩展能力。当然,这三个坐标轴并不互斥,因此您的应用可能同时拥有XYZ三个轴向的扩展能力:

133164591_7_20180516124634472

现在就让我们来看一下AKF扩展模型中各个坐标轴的意义。首先要讲解的就是X轴。在AKF扩展模型中,X轴表示的是应用可以通过部署更多的服务实例来解决扩展性的问题。在这种情况下,原本需要少量服务实例处理的大量负载就可以通过新添加的其它服务实例分担,从而扩大了系统容量,降低了单个服务实例的压力。

我们刚刚提到过,一个服务的扩展性可以同时由多个轴向的扩展性共同组成,因此在该服务中,这种X轴方向的扩展性不仅仅存在于服务这个层次上,更可以由子服务,甚至服务组成的扩展性来共同完成:

133164591_8_20180516124634519

请注意上图中的橙色方块。在该服务中,橙色方块作为一个子服务来向整个服务提供特定功能。在需要扩展时,我们可以通过添加一个新的橙色子服务实例来解决橙色服务负载过大的问题。因此就整个服务而言,其X轴的横向扩展能力并不是通过重新部署整套服务来完成的,而是对独立的子服务进行扩容。

相信您会问:既然只通过添加新的服务或子服务实例就能够完成对服务容量的扩充,那么我们还需要其它两个轴向的横向扩展能力么?

答案是肯定的。首先,最为现实的问题就是服务运行场景的约束。例如在对服务进行X轴横向扩展的时候,我们常常需要一个负载平衡服务。负载平衡服务器常常具有一定的性能限制。因此横向扩展并非全无止境。除此之外,我们也看到了横向扩展有时是使用在子服务上的,而将一个大的服务分割为多个子服务,本身也是沿着其它轴向的横向扩展。

Y轴横向扩展的意义则在于将所有的工作根据数据的类型或业务逻辑进行划分。而就一个Web服务而言,Y轴横向扩展所做的最主要工作就是将一个Monolith服务划分为一系列子服务,从而使不同的子服务独立工作并拥有独立地进行横向扩展的能力。这一方面可以将原本一个服务所处理的所有请求分担给一系列子服务实例来运行,更可以让您根据应用的实际运行情况来对某个成为系统瓶颈的子服务进行X轴横向扩展,避免由于对整个服务进行X轴横向扩展所造成的资源浪费:

133164591_9_20180516124634550

这种组织各个子服务的方式被称为Microservice。使用Microservice组织子服务还可以帮助您实现一系列其它非功能性需求,如高可用性,可测试性等等。

相较而言,执行Y轴扩展要比执行X轴扩展困难一些。但是其常常会使得其它一系列非功能性需求具有更高的质量。

而在Z轴上的横向扩展可能是大家所最不熟悉的情况。其表示需要根据用户的某些特性对用户的请求进行划分。例如使用基于DNS的负载平衡。

当然,到底您的服务需要实现什么程度的X,Y,Z轴扩展能力则需要根据服务的实际情况来决定。如果一个应用的最终规模并不大,那么只拥有X轴扩展能力,或者有部分Y轴扩展能力即可。如果一个应用的增长非常迅速,并最终演变为对吞吐量有极高要求的应用,那么我们就需要从一开始就考虑这个应用在X,Y,Z轴的扩展能力。

本文暂时先总结这么多,在下篇文章将分别介绍服务扩展和数据库扩展实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值