Spring Cloud微服务平台搭建之技术选型思考
一、前言
随着IT技术发展和推进,传统的单体应用程序模式已不满足大多数企业IT平台构建,尤其是大型互联网网站或企业级应用。单体应用随着项目持续集成,代码库越来越大,在系统复杂度、测试、代码冲突解决、可扩展性、多环境支持、需求变更容易造成系统整体影响等方面面临各种严峻挑战。此时微服务架构应运而生。
微服务从2014的1.0技术元年开始,随着微服务社区的推进,微服务技术体系生态产生极大变化,微服务进入2.0时代。微服务架构体系经过多年的大规模生产验证,已成为构建互联网网站、大型企业级应用的首选分布式技术架构。
2020年随着容器化、K8S技术的发展状态,将微服务架构推向了更高的地位,甚至许多大厂都在喊着一些都是服务化的口号。现在后端工程师除了搞算法、嵌入式的外,简历上不写着会微服务,大概也不好找工作了吧...
相对于单体应用,微服务更具有优势:
- 易于理解:微服务将应用按照功能分解为独立开发和部署的微型应用,每个服务与应用程序的其他微服务之间有一个很小且有限的契约。微服务更加专注目标,作为一个功能模块的单元,微服务更容易理解。
- 微服务易于测试:每个微服务都是独立开发部署的微型应用,易于测试。在集成测试和验收测试方面也更易于验证。
- 较少遇到库不兼容问题:每个微服务都有自己独立的项目构建依赖项的集合,而这些集合不会与其他微服务共享。
- 微服务能够独立扩展:微服务之间独立部署,因此指定微服务的内存和实例扩展不会影响整体应用其他微服务的内存和实例数量。
- 微服务可以独立选择不同的技术栈:微服务可以选择不同的语言、平台、框架和库。特别是如果微服务采用HTTP协议这样的跨平台协议,实际上java微服务可以和C#、Python等编写的微服务协作是完全合理的。
- 微服务更易于发布:微服务是独立部署的,因此不需要等待其他微服务部署就绪。同时随着docker容器化、k8s服务编排、自动化CI/CD工具的出现,让微服务的发布更加简单。
当然微服务架构作为分布式架构,同样面临网络延迟、多服务运维、分布式复杂性等问题的挑战。因此合理合适的技术选型是微服务项目的构建的重中之中。
选型准则
生产级
我们使用微服务架构是要解决实际业务场景和生产抗流量的,而不是做简单的demo,如果选择不慎可能出现生产级事故。因此,生产级(Production Ready)、可运维(Ops Ready)、可治理、技术成熟的微服务技术才是我们的首选。
使用已经在多个一线互联网或大型企业落地并经过生产挑战的
我们应该尽量选择使用已经在多个一线互联网或大型企业落地并经过生产挑战并且开源的,且在社区有良好口碑的技术栈。
开源社区活跃
社区活跃、stars数量越多、代码和文档更新频率高的技术栈是优选选择的,开源社区活跃可以直接反应技术的生命力。同时闭源或者停止更新的技术框架应该慎重选择。
结合项目实际情况
不是所有项目都适用于微服务架构体系,应该结合项目实际情况选择合适的技术架构。
二、微服务基础架构关键
架构基础微服务总统架构
微服务框架选型
微服务框架经过多年发展是一个比较成熟的领域,有比较多选择,以下为市场主流微服务架构对比:
微服务框架 | Spring Boot/Cloud | Dubbo/DubboXg | gRpc | Thirft | Motan |
---|---|---|---|---|---|
功能点位 | 完整微服务框架方案 | 服务框架 | RPC | RPC | RPC |
是否支持REST | 是,基于Ribbon支持多种可插拔的序列化选择 | 否 | 否 | 否 | 否 |
是否支持RPC | 否 | 是 | 是 | 是 | 是 |
是否支持多语言 | 是 | 否 | 是 | 是 | 否 |
典型案例 | Netflix、阿里 | 阿里、当当 | 谷歌 | Sina | |
社区活跃 | 高 | 高 | 高 | 一般 | 一般 |
文档丰富度 | 高 | 高 | 一般 | 一般 | 一般 |
-
Spring Cloud由于其Spring社区影响和Netflix的背书,以及其提供的完整一套微服务框架实现方案,目前可以认为Spring Cloud是基于java构建微服务的标准方案。其对于新兴团队或未形成自己微服务体系的团队有较大吸引力。Spring Cloud由于其社区活跃度、完善的生态,目前国内外众多大厂都加入其生态家族(aws、alibaba、huawei、Azure等),甚至阿里将其微服务框架Dubbo也加入到Spring Cloud生态,成为其毕业项目。
Spring Cloud框架本身基于HTTP协议,是一种典型的RESTfull框架而不是RPC框架,序列化协议主要基于文本的JSON。
RESTfull天然支持跨语言平台,任何支持HTTP协议的应用都可以接入调用,但是客户端需要自己解析payload。TESTfull框架接口文档管理随着版本迭代,维护越发困难,如果没有统一标准的接口文档管理机制,更新不及时或缺乏注释等接口文档对于接口调用者和继续集成开发者来说是一个灾难。目前Spring框架也支持Swagger 契约编程模型,可以基于Swagger 契约生成各语言的强类型客户端,极大方便不同语言栈的接入。 -
Dubbo是阿里多年构建生产级分布式微服务的技术结晶,服务治理能力丰富,在国内社区非常活跃。Dubbo其本质是一套基于java的RPC框架。当当DubboX在Dubbo基础上进行了扩展,支持了RESTfull接口暴露的能力。
-
Dubbo主要面向Java技术栈,跨语言支持能力先天不足,同时由于丰富的治理能力,框架整体比较重,想要完整使用好Dubbo门槛比较高。但是如果企业基本都是基于java技术栈进行项目构建,选择Dubbo可以使项目站在比较高的起点上,Dubbo在企业级性能和服务治理能力都非常优秀。Sina的Motan和Dubbo功能类似,可以认为是Dubbo的轻量级剪裁版。前面已说到Dubbo已加入Spring Cloud生态,通过Apache Dubbo RPC扩展Spring Cloud服务间调用的通信协议,因此一定程度可以不用纠结Spring Cloud还是Dubbo了 O(∩_∩)O。
-
gRpc是谷歌推出的一套RPC框架,基于protobuf的强契约编程模型,能够自动生成各类语言的客户端且保证互操作。gRpc适用于内部互相调用的场景,对外暴露RESTfull API实现比较麻烦,需要引入第二套RESTfull 框架作为辅助。
运行时服务支撑服务选型
服务注册与发现
服务治理实现微服务架构体系下各个微服务实例的自动化注册和发现。大部分分布式项目在构建之初,由于微服务实例较少,基本是采用传统静态配置的方式管理服务实例清单,在项目扩展或变更时需要手工维护静态配置。随着业务发展,系统功能越来越复杂、微服务实例数量也极具增加,手工方式维护静态配置需要花费大量人力,同时还极易发生错误。服务治理组件就是为了解决微服务架构实例维护问题。
CAP原则
谈到服务注册就必须先说CAP原则,指的是分布式系统中的一致性(Consistency)、可用性(Availability)、分区容错性(Patitiontolerence),三者不可全得。
- 一致性:指的是分布式所有节点在同一时间的数据完全一致,对于一致性,一致的程度可以分为强、弱、最终一致性:
- 强一致性:对于关系数据库,要求更新数据能够被后续的访问都能看到。如A更新了V0到V1,其他线程后续读取的时候必须是V1。
- 弱一致性:能够容忍后续读取部分或者全部访问不到。如A更新V0到V1,可以容忍其他线程读取的时候仍是V0;
- 最终一致性:弱一致性的特例,保证在没有后续更新的前提下,系统经过一段时间要求返回最近一次更新后的数据。
- 可用性:分布式集群一部分节点故障后,集群整体是否还能响应客户请求。
- 分区容错:某节点故障或网络分区延迟,集群整理仍能对外提供设计好的一致性和可用性的服务。
主流注册中心对比
特点/注册服务组件 | Eureka | Zookeeper | Nacos | Cousul |
---|---|---|---|---|
服务健康检查 | 可配支持 | (弱)长连接,keepalive | 服务状态、内存、硬盘等 | 连接心跳 |
多数据中心 | 支持 | - | 支持 | 支持 |
kv存储服务 | - | 支持 | - | 支持 |
一致性算法 | - | paxos | Raft(CP)Distro(AP) | raft |
数据一致性 | AP | CP | AP、CP | CA |
多语言支持 | http(Sidecar模式) | 客户端 | http(Sidecar模式) | 支持http和DNS |
Watch支持 | 支持long polling/大部分增量 | 支持 | 支持long polling/大部分增量 | 全量/支持long polling |
自身监控 | metrics | - | metrics | metrics |
安全 | - | acl | - | acl/https |
Spring Cloud集成 | 已支持 | 已支持 | 已支持 | 已支持 |
数据模型 | 实例级别 | 无 | 服务-集群-实例 | 实例级别 |
Eureka:是SpringCloud生态核心,通过对Netfiix Eureka的二次封装提供服务注册和发现功能。Eureka 与SpringCloud生态深度结合,获得大量用户。Eureka集群数据是AP,集群每个节点具有相同地位,最大程度保证集群节点故障,注册中心的可用性。
Zookeeper:是应用于分布式应用程序的高性能分布式协调服务,它暴露了一组简单的公共服务(提供java和C接口),如命名、配置管理、集群服务、分布式锁等,分布式应用程序可以基于此实现更高级别的服务进行同步、组合命名。是RPC框架首选注册中心。
Nacos:致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
对于Spring Cloud微服务,目前只要还是在Eureka和Nacos上进行选择:
- Eureka由于其闭源,基本生产级微服务搭建不要考虑Eureka。
- Nacos目前社区活跃,其在集群扩展上表现优秀。同时其注册中心、配置中心统一集成,以及其支持命名空间的隔离,使得项目在微服务服务治理和配置集中化管理上大大减小投入,可以说目前Nacos应该是Spring Cloud首选注册中心。Nacos集成
API网关
为什么需要使用API网关
传统单体应用,客户端访问服务器采用访问ip+端口+服务接口前缀,客户端程序需要维护服务实例列表,如果后续系统扩展,对于客户端开发来说是一个灾难。又如目前有些分布式架构采用F5+Nginx等设施的路由和负载,然后转发到各个不同的服务实例,此模式下需要专业运维人员进行服务实例列表清单和路由规则进行维护,当有服务实例增减和IP地址变更,运维人员需要手工更新路由规则和实例清单信息以保证实例信息和中间配置的一致性。如果系统规模不大的情况,手工维护Nginx路由规则和实例清单不算复杂,如果系统规模达到一定程度,有几十、上百、上千的服务实例需要维护,那么对于运维人员来说也是极大的挑战,同时也容易提高配置错误的概率。
单体服务
基于Nginx进行路由配置管理
服务网关是微服务系统唯一入口,采用类似外观模式封装了系统内部架构,为客户端提供定制化API服务,同时提供登录鉴权、监控、负载均衡、请求分片与管理、静态响应处理、多协议支持、限流、熔断等高级功能。服务网关能够通过框架集成实现自动发现和管理实例,并且提供如验签、登录校验、监控等通过功能,使得微服务开发更加专注业务逻辑的实现。
服务网关模式
目前Spring Cloud 生态,可供我们选择的网关主要还是Spring Cloud Zuul和Spring Cloud Gateway。
- Spring Cloud Zuul 是集成Netflix Zuul组件,与Spring Cloud有很好的集成,缺点是1.x 异步性能不足。
- Spring Cloud Gateway 是Spring Cloud 生态全新项目,基于Spring 5、Spring Boot 2.X、Project Reactor实现的API网关,旨在为微服务提供简单高效的API路由管理方法。
Spring Cloud Gateway 作为Spring Cloud 生态中的网关,目标是代替Zuul 1.X。Spring Cloud 2.X版本目前仍未对Zuul 2.X高性能版本进行集成,仍使用的是非Reactor的老版本Zuul网关。
- 目前Spring Cloud dependencies 最新版本Hoxton.SR8 仍使用的是Zuul 1.3.1
- Zuul 2.x 高性能Reactor版本本身与18年5月开源,目前最新版本2.1.9
Spring Cloud Gateway集成