Spring Cloud 自 2016 年 1 月发布第一个 Angel.SR5 版本,到目前 2020 年 3 月发布 Hoxton.SR3 版本,已经历经了 4 年时间。这 4 年时间里,Spring Cloud 一共发布了 46 个版本,支持的组件数从 5 个增加到 21 个。Spring Cloud 在 2019 年 12 月对外宣布后续 RoadMap:
这个 RoadMap 可以说是对 Spring Cloud 有着非常大的变化。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vCF9iohw-1616600000258)(images/1)]
Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。
Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。
Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
Eureka:服务注册与发现,用于服务管理。
Feign: web调用客户端,能够简化HTTP接口的调用。
Ribbon:基于客户端的负载均衡。
Hystrix:熔断降级,防止服务雪崩。
Zuul:网关路由,提供路由转发、请求过滤、限流降级等功能。
Config:配置中心,分布式配置管理。
Sleuth:服务链路追踪
Admin:健康管理
传统服务到微服务进化。
《传统到分布式演进》
单体应用-> SOA ->微服务(下面讲)
课外扩展:
持续集成,持续部署,持续交付。
集成:是指软件个人研发的部分向软件整体部分集成,以便尽早发现个人开发部分的问题;
部署: 是代码尽快向可运行的开发/测试节交付,以便尽早测试;
交付: 是指研发尽快向客户交付,以便尽早发现生产环境中存在的问题。
如果说等到所有东西都完成了才向下个环节交付,导致所有的问题只能在最后才爆发出来,解决成本巨大甚至无法解决。而所谓的持续,就是说每完成一个完整的部分,就向下个环节交付,发现问题可以马上调整。使问题不会放大到其他部分和后面的环节。
这种做法的核心思想在于:既然事实上难以做到事先完全了解完整的、正确的需求,那么就干脆一小块一小块的做,并且加快交付的速度和频率,使得交付物尽早在下个环节得到验证。早发现问题早返工。
上面的3个持续,也都随着微服务的发展而发展,当架构师的同学,可以参考这种方式。
持续集成的工具,向大家推荐:https://jenkins.io/doc/book/pipeline/
概念:所有功能全部打包在一起。应用大部分是一个war包或jar包。我参与网约车最开始架构是:一个乘客项目中有 用户、订单、消息、地图等功能。随着业务发展,功能增多,这个项目会越来越臃肿。
好处:容易开发、测试、部署,适合项目初期试错。
坏处:
随着项目越来越复杂,团队不断扩大。坏处就显现出来了。
对单体应用的改进:引入SOA(Service-Oriented Architecture)面向服务架构,拆分系统,用服务的流程化来实现业务的灵活性。服务间需要某些方法进行连接,面向接口等,它是一种设计方法,其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能。一个服务 通常以独立的形式存在于操作系统进程中。各个服务之间 通过网络调用。但是还是需要用些方法来进行服务组合,有可能还是个单体应用。
所以要引入微服务,是SOA思想的一种具体实践。
微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想
看这篇文章:
http://www.martinfowler.com/articles/microservices.html
小类比
合久必分。分开后通信,独立部署,独立存储。
分封制:
服从天子命令:服从服务管理。
有为天子镇守疆土的义务:各自完成各自的一块业务。
随从作战:服务调用。
交纳贡献:分担流量压力。
Q:大师大师,服务拆多了怎么办?
A:那就再合起来。
Q:那太没面子了。
A:那就说跨过了微服务初级阶段,在做中台(自助建站系统)。
独立运行在自己进程中。
一系列独立服务共同构建起整个系统。
一个服务只关注自己的独立业务。
轻量的通信机制RESTful API
使用不同语言开发
全自动部署机制
不局限与具体的微服务实现技术。
服务注册与发现:服务提供方将己方调用地址注册到服务注册中心,让服务调用方能够方便地找到自己;服务调用方从服务注册中心找到自己需要调用的服务的地址。
负载均衡:服务提供方一般以多实例的形式提供服务,负载均衡功能能够让服务调用方连接到合适的服务节点。并且,服务节点选择的过程对服务调用方来说是透明的。
服务网关:服务网关是服务调用的唯一入口,可以在这个组件中实现用户鉴权、动态路由、灰度发布、A/B测试、负载限流等功能。
灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
配置中心:将本地化的配置信息(Properties、XML、YAML等形式)注册到配置中心,实现程序包在开发、测试、生产环境中的无差别性,方便程序包的迁移,也是无状态特性。
集成框架:微服务组件都以职责单一的程序包对外提供服务,集成框架以配置的形式将所有微服务组件(特别是管理端组件)集成到统一的界面框架下,让用户能够在统一的界面中使用系统。Spring Cloud就是一个集成框架。
调用链监控:记录完成一次请求的先后衔接和调用关系,并将这种串行或并行的调用关系展示出来。在系统出错时,可以方便地找到出错点。
支撑平台:系统微服务化后,各个业务模块经过拆分变得更加细化,系统的部署、运维、监控等都比单体应用架构更加复杂,这就需要将大部分的工作自动化。现在,Docker等工具可以给微服务架构的部署带来较多的便利,例如持续集成、蓝绿发布、健康检查、性能监控等等。如果没有合适的支撑平台或工具,微服务架构就无法发挥它最大的功效。
1. 蓝绿部署是不停老版本,部署新版本然后进行测试,确认OK,将流量切到新版本,然后老版本同时也升级到新版本。
2. 灰度是选择部分部署新版本,将部分流量引入到新版本,新老版本同时提供服务。等待灰度的版本OK,可全量覆盖老版本。
灰度是不同版本共存,蓝绿是新旧版本切换,2种模式的出发点不一样。
分布式固有的复杂性:容错(某个服务宕机),网络延时,调用关系、分布式事务等,都会带来复杂。
分布式事务的挑战:每个服务有自己的数据库,有点在于不同服务可以选择适合自身业务的数据库。订单用MySQL,评论用Mongodb等。目前最理想解决方案是:柔性事务的最终一致性。
刚性事务:遵循ACID原则,强一致性。
柔性事务:遵循BASE理论,最终一致性;与刚性事务不同,柔性事务允许一定时间内,不同节点的数据不一致,但要求最终一致。
BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。BASE理论是对CAP中AP的一个扩展,通过牺牲强一致性来获得可用性,当出现故障允许部分不可用但要保证核心功能可用,允许数据在一段时间内是不一致的,但最终达到一致状态。满足BASE理论的事务,我们称之为“柔性事务”。
接口调整成本高:改一个接口,调用方都要改。
测试难度提升:一个接口改变,所有调用方都得测。自动化测试就变的重要了。API文档的管理也尤为重要。推荐:yapi。
运维要求高:需要维护 几十 上百个服务。监控变的复杂。并且还要关注多个集群,不像原来单体,一个应用正常运行即可。
重复工作:比如java的工具类可以在共享common.jar中,但在多语言下行不通,C++无法直接用java的jar包。
单一职责原则:关注整个系统功能中单独,有界限的一部分。
服务自治原则:可以独立开发,测试,构建,部署,运行,与其他服务解耦。
轻量级通信原则:轻,跨平台,跨语言。REST,AMQP 等。
粒度把控:与自己实际相结合。 不要追求完美,随业务进化而调整。《淘宝技术这10年》。
Spring Cloud和dubbo组件比较
dubbo:zookeeper+dubbo+springmvc/springboot
通信方式:rpc
注册中心:zookeeper,nacos
配置中心:diamond(淘宝开发)
spring cloud:spring+Netflix
通信方式:http restful
注册中心:eureka,consul,nacos
配置中心:config
断路器:hystrix
网关:zuul,gateway
分布式追踪系统:sleuth+zipkin
差别
dubbo | spring cloud | ||
---|---|---|---|
背景 | 国内影响大 | 国外影响大 | 平手 |
社区活跃度 | 低(现在又好了) | 高 | cloud胜出 |
架构完整度 | 不完善(dubbo有些不提供,需要用第三方,它只关注服务治理) | 比较完善,微服务组件应有尽有。 | cloud胜出 |
学习成本 | dubbo需要配套学习 | 无缝spring | cloud胜出 |
性能 | 高。(基于Netty) | 低。(基于http,每次都要创建)。 此性能的损耗对大部分应用是可以接受的。而HTTP风格的API,是很方便的。用小的性能损耗换来了方便。 | dubbo胜出 |
Spring Cloud是实现微服务架构的一系列框架的有机集合。
是在Spring Boot基础上构建的,用于简化分布式系统构建的工具集。是拥有众多子项目的项目集合。利用Spring Boot的开发便利性,巧妙地简化了分布式系统基础设施(服务注册与发现、熔断机制、网关路由、配置中心、消息总线、负载均衡、链路追踪等)的开发。
版本过程:版本名.版本号。
版本名:伦敦地铁字母顺序。
版本号:M(milestone):里程碑,
SR(Service Releases):稳定版,
RC(Release Candidate):稳定版的候选版,也就是稳定版的最后一个版本。
看官网:查询每个cloud版本下面的子模块的版本。
https://spring.io/projects/spring-cloud
此网页的最下面,目前最新的SpringCloud最新版本是:Greenwich.SR2
版本记录
https://github.com/spring-cloud/spring-cloud-release/releases
《Spring Cloud整体架构图》
组成:
服务注册与发现组件:Eureka,Zookeeper,Consul,Nacos等。Eureka基于REST风格的。
服务调用组件:Hystrix(熔断降级,在出现依赖服务失效的情况下,通过隔离 系统依赖服务 的方式,防止服务级联失败,同时提供失败回滚机制,使系统能够更快地从异常中恢复),Ribbon(客户端负载均衡,用于提供客户端的软件负载均衡算法,提供了一系列完善的配置项:连接超时、重试等),OpenFeign(优雅的封装Ribbon,是一个声明式RESTful网络请求客户端,它使编写Web服务客户端变得更加方便和快捷)。
网关:路由和过滤。Zuul,Gateway。
配置中心:提供了配置集中管理,动态刷新配置的功能;配置通过Git或者其他方式来存储。
消息组件:Spring Cloud Stream(对分布式消息进行抽象,包括发布订阅、分组消费等功能,实现了微服务之间的异步通信)和Spring Cloud Bus(主要提供服务间的事件通信,如刷新配置)
安全控制组件:Spring Cloud Security 基于OAuth2.0开放网络的安全标准,提供了单点登录、资源授权和令牌管理等功能。
链路追踪组件:Spring Cloud Sleuth(收集调用链路上的数据),Zipkin(对Sleuth收集的信息,进行存储,统计,展示)。
每个点中的内容,后面都会讲到。
STS
https://spring.io/tools
通过这个服务来看eureka注册中心的效果。
复习Spring Boot。
减少了大量配置。快速开发。
用Starter集成一个新框架。比如redis,web等。添加依赖,加配置文件。
嵌入式服务器,令开发和部署变的方便。
Spring Boot介绍:
https://docs.spring.io/spring-boot/docs/2.1.7.RELEASE/
看代码。
pom.xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
有的教程中还引入spring-boot-starter-web,其实不用。因为上面的依赖已经包含了它。在pom中点此依赖进去,一共点4次spring-cloud-netflix-eureka-server,发现web的依赖。
application.yml
eureka:
client:
#是否将自己注册到Eureka Server,默认为true,由于当前就是server,故而设置成false,表明该服务不会向eureka注册自己的信息
register-with-eureka: false
#是否从eureka server获取注册信息,由于单节点,不需要同步其他节点数据,用false
fetch-registry: false
#设置服务注册中心的URL,用于client和server端交流
service-url:
defaultZone: http://localhost:7900/eureka/
application.properties
#是否将自己注册到Eureka Server,默认为true,由于当前就是server,故而设置成false,表明该服务不会向eureka注册自己的信息
eureka.client.register-with-eureka=false
#是否从eureka server获取注册信息,由于单节点,不需要同步其他节点数据,用false
eureka.client.fetch-registry=false
#设置服务注册中心的URL,用于client和server端交流
eureka.client.service-url.defaultZone=http://localhost:7900/eureka/
代码
启动类上添加此注解标识该服务为配置中心
@EnableEurekaServer
PS:Eureka会暴露一些端点。端点用于Eureka Client注册自身,获取注册表,发送心跳。
简单看一下eureka server控制台,实例信息区,运行环境信息区,Eureka Server自身信息区。
注册中心相当于买票乘车,只看有没有票(有没有服务),有就去买票(获取注册列表),然后乘车(调用)。不必关心有多少火车在运行。
注册中心好处:不用关心有多少提供方。
注册中心有哪些:Eureka,Nacos,Consul,Zookeeper等。
服务注册与发现包括两部分,一个是服务器端,另一个是客户端。
Server是一个公共服务,为Client提供服务注册和发现的功能,维护注册到自身的Client的相关信息,同时提供接口给Client获取注册表中其他服务的信息,使得动态变化的Client能够进行服务间的相互调用。
Client将自己的服务信息通过一定的方式登记到Server上,并在正常范围内维护自己信息一致性,方便其他服务发现自己,同时可以通过Server获取到自己依赖的其他服务信息,完成服务调用,还内置了负载均衡器,用来进行基本的负载均衡。
我们课程的Spring Cloud是用Eureka作为服务注册中心。
Eureka:是一个RESTful风格的服务,是一个用于服务发现和注册的基础组件,是搭建Spring Cloud微服务的前提之一,它屏蔽了Server和client的交互细节,使得开发者将精力放到业务上。
serverA从serverB同步信息,则serverB是serverA的peer。
上面例子中如果service-url为空,且register-with-eureka,fetch-registry为true,则会报错,Cannot execute request on any known server,因为server同时也是一个client,他会尝试注册自己,所以要有一个注册中心url去注册。
Netflix开源的组件。包括server和client两部分。
https://github.com/Netflix/Eureka
《服务注册与发现关系图》
服务注册表:记录各个微服务信息,例如服务名称,ip,端口等。
注册表提供 查询API(查询可用的微服务实例)和管理API(用于服务的注册和注销)。
服务注册与发现:注册:将微服务信息注册到注册中心。发现:查询可用微服务列表及其网络地址。
服务检查:定时检测已注册的服务,如发现某实例长时间无法访问,就从注册表中移除。
组件:Eureka , Consul , ZooKeeper,nacos等。
例子:api-listen-order
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
#注册中心
eureka:
client:
#设置服务注册中心的URL
service-url:
defaultZone: http://root:root@localhost:7900/eureka/
ps:不想注册,设置成false即可,实例演示结果:注册中心没有实例信息。找控制台204信息也没有找到。
spring:
cloud:
service-registry:
auto-registration:
enabled: false
注册成功:
DiscoveryClient_API-LISTEN-ORDER/api-listen-order:30.136.133.9:port - registration status: 204
后面源码讲手动注册。
PS:
Eureka Server与Eureka Client之间的联系主要通过心跳的方式实现。心跳(Heartbeat)即Eureka Client定时向Eureka Server汇报本服务实例当前的状态,维护本服务实例在注册表中租约的有效性。
Eureka Client将定时从Eureka Server中拉取注册表中的信息,并将这些信息缓存到本地,用于服务发现。
高可用:可以通过运行多个Eureka server实例并相互注册的方式实现。Server节点之间会彼此增量地同步信息,从而确保节点中数据一致。
准备2个节点部署eureka,也可以单机部署
修改本机host文件,绑定一个主机名,单机部署时使用ip地址会有问题
节点 1:
#是否将自己注册到其他Eureka Server,默认为true 需要
eureka.client.register-with-eureka=true
#是否从eureka server获取注册信息, 需要
eureka.client.fetch-registry=true
#设置服务注册中心的URL,用于client和server端交流
#此节点应向其他节点发起请求
eureka.client.serviceUrl.defaultZone=http://ek2.com:7902/eureka/
#主机名,必填
eureka.instance.hostname=ek1.com
management.endpoint.shutdown.enabled=true
#web端口,服务是由这个端口处理rest请求的
server.port=7901
节点 2:
#是否将自己注册到其他Eureka Server,默认为true 需要
eureka.client.register-with-eureka=true
#是否从eureka server获取注册信息, 需要
eureka.client.fetch-registry=true
#设置服务注册中心的URL,用于client和server端交流
#此节点应向其他节点发起请求
eureka.client.serviceUrl.defaultZone=http://ek1.com:7902/eureka/
#主机名,必填
eureka.instance.hostname=ek2.com
management.endpoint.shutdown.enabled=true
#web端口,服务是由这个端口处理rest请求的
server.port=7902
节点 1:
如果有节点3,配置同上 改一下主机名和端口
略。。。
两个节点的话,如下图内容 就算成功了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGjulgRj-1616600000264)(images/image-20200403193147121.png)]
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
Spring Boot 2.0 的Actuator只暴露了health和info端点,提供的监控信息无法满足我们的需求
在1.x中有n多可供我们监控的节点,官方的回答是为了安全….
在application.yml中加入如下配置信息
*代表所有节点都加载
#开启所有端点
management.endpoints.web.exposure.include=*
所有端点都开启后的api列表
{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},"archaius":{"href":"http://localhost:8080/actuator/archaius","templated":false},"beans":{"href":"http://localhost:8080/actuator/beans","templated":false},"caches-cache":{"href":"http://localhost:8080/actuator/caches/{cache}","templated":true},"caches":{"href":"http://localhost:8080/actuator/caches","templated":false},"health":{"href":"http://localhost:8080/actuator/health","templated":false},"health-path":{"href":"http://localhost:8080/actuator/health/{*path}","templated":true},"info":{"href":"http://localhost:8080/actuator/info","templated":false},"conditions":{"href":"http://localhost:8080/actuator/conditions","templated":false},"configprops":{"href":"http://localhost:8080/actuator/configprops","templated":false},"env":{"href":"http://localhost:8080/actuator/env","templated":false},"env-toMatch":{"href":"http://localhost:8080/actuator/env/{toMatch}","templated":true},"loggers":{"href":"http://localhost:8080/actuator/loggers","templated":false},"loggers-name":{"href":"http://localhost:8080/actuator/loggers/{name}","templated":true},"heapdump":{"href":"http://localhost:8080/actuator/heapdump","templated":false},"threaddump":{"href":"http://localhost:8080/actuator/threaddump","templated":false},"metrics":{"href":"http://localhost:8080/actuator/metrics","templated":false},"metrics-requiredMetricName":{"href":"http://localhost:8080/actuator/metrics/{requiredMetricName}","templated":true},"scheduledtasks":{"href":"http://localhost:8080/actuator/scheduledtasks","templated":false},"mappings":{"href":"http://localhost:8080/actuator/mappings","templated":false},"refresh":{"href":"http://localhost:8080/actuator/refresh","templated":false},"features":{"href":"http://localhost:8080/actuator/features","templated":false},"service-registry":{"href":"http://localhost:8080/actuator/service-registry","templated":false}}}
会显示系统状态
{“status”:“UP”}
用来关闭节点
开启远程关闭功能
management.endpoint.shutdown.enabled=true
使用Post方式请求端点
{
“message”: “Shutting down, bye…”
}
autoconfig
获取应用的自动化配置报告
beans
获取应用上下文中创建的所有Bean
获取应用中配置的属性信息报告
获取应用所有可用的环境属性报告
获取应用所有Spring Web的控制器映射关系报告
获取应用自定义的信息
返回应用的各类重要度量指标信息
Metrics节点并没有返回全量信息,我们可以通过不同的key去加载我们想要的值
metrics/jvm.memory.max
1.x中为dump
返回程序运行中的线程信息