当前位置: 首页 > 科技观察

为什么会有微服务架构,原来是这些原因

时间:2023-03-13 07:41:06 科技观察

Web应用架构严重受系统用户数量和开发人员组织方式的影响。近二十年来,互联网飞速发展,Web架构也从单体发展到微服务,背后有MartinFowler等理论支撑。虽然大家都听说过微服务,但是很多人不知道为什么做,怎么做,怎么拆。要回答这个问题,我认为有必要从Web架构的演化历史的角度来理解这些架构设计中的取舍。首先,我们改进系统架构的目的是满足系统可靠性、并发性和快速开发的要求。所有的改进都是为了解决这些问题中的一个或多个。MonolithicstructureMonolithicstructure一开始,web服务器和数据库都部署在同一台服务器上。这也是最简单的应用架构,一般在公司早期的项目中都会采用。长期以来,单一的结构可以满足系统快速开发和并发的需求。当用户数量增加时,数据库性能通常成为系统的瓶颈。这时可以将web服务和数据库部署在不同的服务器上,加强数据库服务器的配置,做读写分离,提高系统的吞吐量和可用性。同时可以将业务系统平均部署在多台服务器上,提高系统吞吐量,但总体上还是单体应用。单体等效部署随着用户和数据量的进一步增加,单体应用的劣势将进一步显现,例如:耦合严重、复杂度高、可靠性差:越来越多的单体应用会将很多服务耦合在一起,一旦出现bug发生在某些模块,会影响整个系统的正常运行,业务代码的耦合也会对开发人员形成依赖,导致新业务难以推广,技术债务增加,部署困难。效率低下:越来越多的技术债很容易造成“不破不修”的尴尬,完成的代码很难修改以防止系统某处的意外调用。同因代码量大导致应用全量部署困难,系统吞吐量受限,技术进步受阻:单体应用的进一步扩展难以进一步扩展系统吞吐量,单体应用需要使用统一的技术平台或解决方案。如果要引入新的语言或框架,将很难拆分。应用规模越来越大。第一个瓶颈可能是数据库系统。面对数据库压力,我们通常可以通过拆分数据库,将负载分散到不同的服务器来解决问题。通常,数据库有两种拆分方案:垂直拆分:账户、搜索、推荐系统等不同的业务系统使用不同的数据库水平拆分:针对大表,比如百亿、百亿,多表拆分横向拆分与业务逻辑紧密耦合,需要具体问题具体分析,这通常是一个非常复杂的问题。后来人们又推出了NoSQL和NewSQL,利用分布式的概念在数据库层屏蔽了数据库的水平拆分,比如NoSQL的MongoDBSharding,NewSQL的TiDB。同样,在业务层,我们也可以通过纵向拆分和横向拆分,将单体业务拆分成不同的服务。服务之间通过约定的协议进行通信,提高人员开发效率,实现多机部署的冗余部署。提高系统可用性和吞吐量。微服务我们都知道,微服务是一种提倡将单个服务拆分成一组小服务,服务之间协调协作,提高开发效率,最终为用户提供价值的思想。说到微服务,这里最重要的问题就是如何拆解服务。作为SOA(ServiceOrientedArchitecture)思想的具体实践,微服务首先想到的是根据不同的业务系统进行垂直拆分,如下图:SOA垂直拆分单体应用按业务系统垂直拆分,不同业务线可以独立配备产品经验和工程师同步开发维护,不同业务线可以解耦由不同团队维护。不过,上图是理想情况。各个系统的分工比较强,系统之间不需要更详细的交流。如果拆解后的子系统之间有大量的数据交互和调用,网关模式不是一个好的做法。通常,各个业务子系统通过ESB(EnterpriseServiceBus)模式连接到一条数据总线上进行数据交互,各个子系统与数据总线之间的数据交互需要子系统统一管理。这就有了服务治理的概念,用一套统一的标准来处理各个子系统的注册、权限、监控等。,ESB开源或者闭源的解决方案很多,这里就不赘述了。垂直拆分解耦了各个业务子系统,但是每个请求在不同的阶段遇到的瓶颈和负载不同,所以我们可以使用水平拆分的思路来拆分服务:水平拆分首先用户请求通过http协议到达网关,然后gateway将json数据格式转成protobuf,通过tcp长链接与服务层和数据层通信,获取目标数据返回给用户。这样的拆分增加了用户请求的链路延迟,但是如果所有的服务都部署在同一个内网,并且以protobuf格式进行通信,那么这个延迟在几十毫秒内是完全可以接受的。业务层和数据层的完全解耦,可以方便的将不同类型的服务部署成冗余部署,同时在保持业务层不变的情况下修改其数据存储方式。如果我们把系统垂直拆分和水拆分,那么我们就会出现微服务的样子,水平拆分的每一层只能调用下层的服务。如果搜索服务层可以只drop账户接口层服务而不调用账户服务层接口,这样可以避免服务A调用服务B,服务B同时调用服务A的问题。然而,这样的分割粒度仍然不够。比如搜索系统和推荐系统都需要调用账户系统的一些基本的查询和修改逻辑,那么在搜索和推荐服务层需要实现相同的代码两次,这显然是不对的。讲道理,任何不能复用的设计,显然都是有问题的。如果通过编写SDK库提供Jar包来实现这个功能呢?显然,也存在问题。比如推荐系统是用Python实现的,而搜索系统是用Java实现的?所以这里我们将各个子系统的共享代码部分分离出来作为一个服务。水平拆分2拆分系统可以灵活部署,独立开发,各模块服务使用的技术栈相对独立,不受限制。但同时,拆分也使得系统的网络拓扑复杂化,增加了运维的负担,服务之间的依赖使得服务接口的调整成本非常高。随着服务的增多,对服务治理的要求也更高,需要对服务发现、注册、认证、监控等系统功能进行专门化处理。