前言
在单机应用时代,换句话说,如果你的应用就部署一个实例,并没有伸缩性的概念。伸缩性是针对分布式系统的场景下,才有意义。而且现在的大型分布式系统,对于伸缩性是非常重视的,因为现在的系统运维都希望机器或容器能够动态扩容。比如,淘宝的双11、京东的618等大型促销活动,其流量和压力都是平时的很多倍,但是总不能要求平时就用这么多的部署资源,这会很浪费,所以动态扩容就显得很有必要了。老规矩,先来定义一下伸缩性。
定义
系统的性能能够随着应用实例数的加减获得相匹配的加减的能力。
性能
伸缩性重点描述的是系统性能的弹性,不是其他的特性,比如系统功能的弹性,比如说很方便增加一个新功能。实际上从功能角度描述系统弹性是架构决策中的另外一个特性 - 扩展性,我们博文会讨论到。
应用实例数
注:这个地方的应用实例不仅仅是表示业务应用的实例,也表示数据库实例,是一个比较宽泛的叫法。
当我们要增加一个大型分布式系统的整体性能的时候,我们一般是通过增加一台物理机、虚拟机或者容器(Docker),然后在其上部署一个或多个应用实例。所以伸缩性实际上从上层来看,说的是应用实例的增减;从下层来看,说的是部署资源的增减。
可能有些同学会有点疑问,难道增加一个实例不就自然会增加系统的性能吗?好像有点道理,但是不尽然。我们来看一个具体的实例,假设我们选择需要增加一个应用实例,首先我们需要确确认的是,分布式应用集群可以随便的增加实例数,如果这个业务应用无状态,那么这很容易,不会影响路由策略;如果这个业务有状态,那么就不能很容易的增减了,这个时候可能会影响路由策略,甚至会导致数据迁移。
我们在上例中说的无状态和有状态,实际上简单来说就是一个应用实例是否能够被另一个应用实例随意替换,而不影响业务逻辑并且无须额外付代价。如果可以,那我们称之为无状态;反之,称为有状态。比如一个路由代理就是无状态的,再比如一个自身管理Session的Web应用就是有状态的。所以,一般情况下,我们设计应用的目标就是使其无状态,这样能增强其伸缩性。
相匹配的
如果集群中有N个应用实例,当增加一个应用实例时,理想情况下,其性能应该是要增加1/N的,但有些时候不一定是一个线性的关系。
实例一:自管理Session的Web应用
一个Web应用如果自己管理Session,那么意味着他是有状态的,这个时候要提升集群性能,不能简单的增加一个实例了事。比如:
一个用户登录到A实例,这个时候其Session保存在A机器;
后续又增加了一个H实例;
这个用户短期内再次登录时,必须路由到A实例,不能路由到其他机器去,否则用户体验不好;
一般这个时候,我们通过特殊的路由策略来解决;或者通过集中化Session服务来处理。
因此,这样的自管理Session的Web应用其伸缩性是不好的。那么我们一般就是将有状态的部分分离出去,比如上边提到的集中化Session服务。但是,其实这样只是把伸缩性的难度从Web应用转移到了集中化Session服务,因为该服务本身为了满足高可用,也是分布式部署,也能可能会存在性能的伸缩要求。但这样的转移是有意义的,因为我们的业务应用数量远远大于这种专业服务(Session服务),其对伸缩性的要求更加强烈。
对于这种专业服务,像集中Session服务、数据层存储(MySQL)、服务总线等等这种,其存在的一个重要理由就是专业的事由专业的人来做,这样最大程度降低了业务应用的复杂性,提升了业务应用的某些特性,比如集中Session服务提升业务应用的伸缩性。至于其自身的伸缩性,一般是通过复杂的内部通信、路由策略以及数据冗余等等技术来实现的。在此,不详细展开,后续博文以后可能会有所涉及。