SpringCloud概述
1.SpringCloud是什么?
官方解释:
官网: https://spring.io/projects/spring-cloud/
SpringCloud是一系列框架的有序集合。它利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot的开发风格做到一键启动和部署。SpringCloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
2.SpringCloud和SpringBoot什么关系?
SpringBoot专注于快速方便的开发单个个体微服务。
SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,SpringBoot可以离开SpringCloud独立开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系。
3.SpringCloud优缺点
1)SpringCloud来源于Spring,质量、稳定性、持续性都可以得到保证。
SpirngCloud以SpringBoot为基础开发框架,可以给开发者大量的微服务开发经验,例如,只要极少量的标签,你就可以创建一个配置服务器,再加一些标签,你就可以得到一个客户端库来配置你的服务,更加便于业务落地。
2)SpringCloud 是Java领域最适合做微服务的框架,对Java开发者来说就很容易开发。
3)耦合度低,不影响其他模块
4)多个开发团队可以并行开发项目,提高开发效率
5)直接写自己的代码即可,然后暴露接口,通过组件进行服务通信。
缺点:
只能针对Java开发
部署麻烦、组件多
每个微服务都可以用一个数据库,导致数据管理复杂
一套完整的微服务包括自动化部署,调度,资源管理,进程隔离,自愈,构建流水线等功能,单靠SpringCloud是无法实现的,所以SpringCloud+k8s才是最好的方案
4.为何要将SpringCloud项目部署到k8s平台?
SpringCloud只能用在 SpringBoot的java环境中,而kubernetes可以适用于任何开发语言,只要能被放进docker的应用,都可以在kubernetes上运行,而且更轻量,更简单。
每个微服务可以部署多个,没有多少依赖,并且有负载均衡能力,比如一个服务部署一个副本或5个副本,通过k8s可以更好的去扩展我们的应用。
Spring提供应用的打包,Docker和Kubernetes提供部署和调度。Spring通过Hystrix线程池提供应用内的隔离,而Kubernetes通过资源,进程和命名空间来提供隔离。Spring为每个微服务提供健康终端,而Kubernetes执行健康检查,且把流量导到健康服务。Spring外部化配置并更新它们,而Kubernetes分发配置到每个微服务。
SpringCloud很多功能都跟kubernetes重合,比如服务发现,负载均衡,配置管理,所以如果把SpringCloud部署到k8s,那么很多功能可以直接使用k8s原生的,减少复杂度。
SpringCloud容易上手,是对开发者比较友好的平台;Kubernetes是可以实现DevOps流程的,SpringCloud和kubernetes各有优点,只有结合起来,才能发挥更大的作用,达到最佳的效果。
5.SpringCloud项目部署到k8s的流程
制作镜像--->控制管理pod--->暴露应用--->对外发布应用--->数据持久化---à日志/监控
1.制作镜像: 应用程序、运行环境、文件系统
2.控制器管理pod:deployment无状态部署、statefulset 有状态部署、Daemonset 守护进程部署、job & cronjob批处理
3.暴露应用:服务发现、负载均衡
4.对外发布应用:service、Ingress HTTP/HTTPS访问
5.pod数据持久化:分布式存储-ceph和gluster
6.日志/监控:efk、prometheus、pinpoint等
SpringCloud组件介绍
1. 服务发现与注册组件Eureka
Eureka是Netflix开发的服务发现框架, SpringCloud将它集成在自己的子项目spring-cloud-netflix中,以实现SpringCloud中服务发现和注册功能。Eureka包含两个组件:Eureka Server和Eureka Client。
互动:Netflix是什么?
Netflix在SpringCloud项目中占着重要的作用,Netflix公司提供了包括Eureka、Hystrix、Zuul、Archaius等在内的很多组件,在微服务架构中至关重要。
互动: 举个例子服务发现与注册
我们在买车的时候,需要找中介,如果不找中介,我们自己去找厂商或者个人车主,这是很麻烦的,也很浪费时间,所以为了方便,我们一般去找中介公司,把我们的需求说出来,他们就会按需给我们推荐车型,我们相当于微服务架构中的消费者Consumer,中介相当于微服务架构中的提供者Provider,Consumer需要调用Provider提供的一些服务,就像是我们要买的车一样。
1.1 Eureka组件
Eureka Server
Eureka Server提供服务注册中心,各个节点启动后,会将自己的IP和端口等网络信息注册到Eureka Server中,这样Eureka Server服务注册表中将会存储所有可用服务节点的信息,在Eureka的图形化界面可以看到所有注册的节点信息。
Eureka Client
Eureka Client是一个java客户端,在应用启动后,Eureka客户端将会向Eureka Server端发送心跳,默认周期是30s,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Client分为两个角色,分别是Application Service和Application Client
Application Service是服务提供方,是注册到Eureka Server中的服务。
Application Client是服务消费方,通过Eureka Server发现其他服务并消费。
1.2 Eureka架构原理
Register(服务注册):当Eureka客户端向Eureka Server注册时,会把自己的IP、端口、运行状况等信息注册给Eureka Server。
Renew(服务续约):Eureka客户端会每隔30s发送一次心跳来续约,通过续约来告诉Eureka Server自己正常,没有出现问题。正常情况下,如果 Eureka Server 在90秒没有收到 Eureka 客户的续约,它会将实例从其注册表中删除。
Cancel(服务下线):Eureka客户端在程序关闭时向Eureka服务器发送取消请求。 发送请求后,该客户端实例信息将从服务器的实例注册表中删除,防止consumer调用到不存在的服务。该下线请求不会自动完成,它需要调用以下内容:DiscoveryManager.getInstance().shutdownComponent();
Get Registry(获取服务注册列表):获取其他服务列表。
Replicate(集群中数据同步):eureka集群中的数据复制与同步。
Make Remote Call(远程调用):完成服务的远程调用。
2. 客户端负载均衡之Ribbon
2.1 Ribbon简介
Ribbon是一个基于HTTP和TCP的客户端负载均衡器,主要提供客户侧的软件负载均衡算法,运行在消费者端。客户端负载均衡是当浏览器向后台发出请求的时候,客户端会向Eureka Server读取注册到服务器的可用服务信息列表,然后根据设定的负载均衡策略,抉择出向哪台服务器发送请求。在客户端就进行负载均衡算法分配。Ribbon客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。下面是用到的
一些负载均衡策略:
随机策略---随机选择server
轮询策略---轮询选择, 轮询index,选择index对应位置的Server
重试策略--在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server
最低并发策略--逐个考察server,如果server断路器打开,则忽略,再选择其中并发链接最低的server
可用过滤策略--过滤掉一直失败并被标记为circuit tripped的server,过滤掉那些高并发链接的server(active connections超过配置的阈值)或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个Server的运行状态;
响应时间加权重策略--根据server的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io等,都直接影响响应时间;
区域权重策略--综合判断server所在区域的性能,和server的可用性,轮询选择server并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server。
互动: 举个列子说明ribbon
比如我们设计了一个秒杀系统,但是为了整个系统的 高可用 ,我们需要将这个系统做一个集群,而这个时候我们消费者就可以拥有多个秒杀系统的调用途径了,如下图。
如果这个时候我们没有进行一些 均衡操作 ,如果我们对 秒杀系统1 进行大量的调用,而另外两个基本不请求,就会导致 秒杀系统1 崩溃,而另外两个就变成了傀儡,那么我们为什么还要做集群,我们高可用体现的意义又在哪呢?
所以 Ribbon 出现了,注意我们上面加粗的几个字——运行在消费者端 。指的是,Ribbon 是运行在消费者端的负载均衡器,如下图。
其工作原理就是 Consumer
端获取到了所有的服务列表之后,在其内部 使用负载均衡算法 ,进行对多个系统的调用。
2.2 Ribbon的功能
易于与服务发现组件(比如Eureka)集成
使用Archaius完成运行时配置
使用JMX暴露运维指标,使用Servo发布
多种可插拔的序列化选择
异步和批处理操作
自动SLA框架
系统管理/指标控制台
2.3 Ribbon和nginx对比分析
区别:
Ribbon实现的是客户端负载均衡,它可以在客户端经过一系列算法来均衡调用服务。Ribbon 工作时分两步:
第一步:从Eureka Server中获取服务注册信息列表,它优先选择在同一个 Zone 且负载较少的 Server。
第二步:根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址,其中Ribbon提供了多种策略,例如轮询、随机等。
Nginx是服务器端负载均衡,所有请求统一交给nginx,由nginx实现负载均衡请求转发,属于服务器端负载均衡。
3. 服务网关Zuul
Zuul是SpringCloud中的微服务网关,首先是一个微服务。也是会在Eureka注册中心中进行服务的注册和发现。也是一个网关,请求应该通过Zuul来进行路由。Zuul网关不是必要的,是推荐使用的。
互动:网关是什么?
是一个网络整体系统中的前置门户入口。请求首先通过网关,进行路径的路由,定位到具体的服务节点上。
Zuul网关的作用:
统一入口:为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性。
鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。
动态路由:动态的将请求路由到不同的后端集群中。
减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射。
4. 熔断器Hystrix
Hystrix的中文名字是“豪猪”,豪猪是满身长满了刺,能够保护自己不受天敌的伤害,代表了一种防御机制,Hystrix在SpringCloud中负责服务熔断和服务降级的作用。
什么是服务熔断?(熔断可以保护服务):
在讲熔断之前先看个概念: 服务雪崩
假设有A、B、C三个服务,服务A调用服务B和C,链路关系如下:
假设服务C因为请求量大,扛不住请求,变得不可用,这样就是积累大量的请求,服务B的请求也会阻塞,会逐渐耗尽线程资源,使得服务B变得不可用,那么服务A在调用服务B就会出现问题,导致服务A也不可用,那么整条链路的服务调用都失败了,我们称之为雪崩。
接下来看下服务熔断:
互动:举个生活中的例子
当电路发生故障或异常时,伴随着电流不断升高,并且升高的电流有可能能损坏电路中的某些重要器件,也有可能烧毁电路甚至造成火灾。若电路中正确地安置了保险丝,那么保险丝就会在电流异常升高到一定的高度和热度的时候,自身熔断切断电流,从而起到保护电路安全运行的作用。
在微服务架构中,在高并发情况下,如果请求数量达到一定极限(可以自己设置阈值),超出了设置的阈值,Hystrix会自动开启服务保护功能,然后通过服务降级的方式返回一个友好的提示给客户端。假设当10个请求中,有10%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到10s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。
服务降级(提高用户体验效果):
在高并发的场景下,当服务器的压力剧增时,根据当前业务以及流量的情况,对一些服务和页面进行策略控制,对这些请求做简单的处理或者不处理,来释放服务器资源用以保证核心业务不受影响,确保业务可以正常对外提供服务,比如电商平台,在针对618、双11的时候会有一些秒杀场景,秒杀的时候请求量大,可能会返回报错标志“当前请求人数多,请稍后重试”等,如果使用服务降级,无法提供服务的时候,消费者会调用降级的操作,返回服务不可用等信息,或者返回提前准备好的静态页面写好的信息。
5. API网关Springcloud Gateway
互动: 为什么学习了网关Zuul,又要讲Spring Cloud Gateway呢?
原因很简单,就是Spring Cloud已经放弃Zuul了。现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是基于过滤器的,是阻塞IO,不支持长连接,spring官网上也已经没有zuul的组件了,所以给大家讲下SpringCloud原生的网关产品Gateway。
Spring Cloud Gateway是Spring Cloud新推出的网关框架,之前是 Netflix Zuul,由spring官方基于Spring5.0,Spring Boot2.0,Project Reactor等技术开发的网关,该项目提供了一个构建在Spring Ecosystem之上的API网关,旨在提供一种简单而有效的途径来发送API,并向他们提供交叉关注点,例如:安全性,监控/指标和弹性.
SpringCloud Gateway 特征:
SpringCloud官方对SpringCloud Gateway 特征介绍如下:
(1)集成 Hystrix 断路器
(2)集成 Spring Cloud DiscoveryClient
(3)Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
(4)具备一些网关的高级功能:动态路由、限流、路径重写
从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。
简单说明一下上文中的三个术语:
1)Filter(过滤器):
和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。
2)Route(路由):
网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。
3)Predicate(断言):
这是一个Java8的Predicate,可以使用它来匹配来自HTTP请求的任何内容,例如headers或参数。断言的输入类型是一个ServerWebExchange。
Zuul和GateWay区别
5. API网关Springcloud Gateway 互动: 为什么学习了网关Zuul,又要讲Spring Cloud Gateway呢? 原因很简单,就是Spring Cloud已经放弃Zuul了。现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是基于过滤器的,是阻塞IO,不支持长连接,spring官网上也已经没有zuul的组件了,所以给大家讲下SpringCloud原生的网关产品Gateway。 Spring Cloud Gateway是Spring Cloud新推出的网关框架,之前是 Netflix Zuul,由spring官方基于Spring5.0,Spring Boot2.0,Project Reactor等技术开发的网关,该项目提供了一个构建在Spring Ecosystem之上的API网关,旨在提供一种简单而有效的途径来发送API,并向他们提供交叉关注点,例如:安全性,监控/指标和弹性. SpringCloud Gateway 特征: SpringCloud官方对SpringCloud Gateway 特征介绍如下: (1)集成 Hystrix 断路器 (2)集成 Spring Cloud DiscoveryClient (3)Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters (4)具备一些网关的高级功能:动态路由、限流、路径重写 从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。 简单说明一下上文中的三个术语: 1)Filter(过滤器): 和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。 2)Route(路由): 网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。 3)Predicate(断言): 这是一个Java8的Predicate,可以使用它来匹配来自HTTP请求的任何内容,例如headers或参数。断言的输入类型是一个ServerWebExchange。
6. 配置中心SpringCloud Config
SpringCloud Config是一个解决分布式系统的配置管理方案,它包含了server和client 两个部分。 server 用来获取远程的配置信息(默认为 Git 仓库),并且以接口的形式提供出去,client 根据 server 提供的接口读取配置文件,以便于初始化自己的应用。如果配置中心出现了问题,将导致灾难性的后果,因此在生产环境下配置中心都会做集群,来保证高可用。此处配置高可用实际就是把多个配置中心(指定同一个 Git 远程仓库)注册到注册中心。
将SpringCloud项目部署到K8S平台的注意事项
- 1.如何进行服务发现?
- 2.如何进行配置管理?
- 3.如何进行负载均衡?
- 4.如何访问k8s中的服务?
- 5.如何通过k8s进行服务编排?
- 6.k8s部署Spring Cloud项目的整体发布流程
1.如何进行服务发现?
可以通过springcloud的Eureka,也可以通过k8s自身的coredns。如果是把Springcloud项目迁移到k8s,可以使用原来的Eureka,这样可以避免开发人员对原来的代码进行大量的修改。通常情况下,我们的线上的服务在迁移到k8s环境下的时候,都是采用平滑迁移的方案。服务治理与注册中心等都是采用原先的组件。比如springcloud应用,在k8s环境下还是用原来的一套注册中心(如eureka),服务治理(hystrix,ribbon)等
使用Kubernetes service发现pod:
Kubernetes中的pod是有生命周期的,可以被创建、也可以被销毁,k8s中的pod可以有多组,每组pod可以称为一个微服务,那么怎么能让这些微服务相互访问呢?需要在每组pod前端有一个固定的接入层,叫做service,service解决了对后端pod进行负载均衡和自动发现的能力,但是我们怎么还需要知道service的ip,这样才能被其他服务访问,那么怎么解决这一问题呢?
使用coredns发现service(服务):
coredns可以解决Service的发现问题,k8s将Service的名称当做域名注册到coredns中,通过Service的名称就可以访问其提供的服务。Coredns支持的域名格式:
<service_name>.<namespace>.svc.<cluster_domain>。
默认的域名是<service_name>.<namespace>.svc.cluster.local
2.如何进行配置管理?
通过在k8s中部署SpringCloud Config,也可以通过k8s自带的的configmap。还可以使用spring-cloud-kubernetes进行配置管理。
如果微服务架构中没有使用统一配置中心时,所存在的问题:
配置文件分散在各个项目里,不方便维护
配置内容安全与权限,实际开发中,开发人员是不知道线上环境的配置的
更新配置后,项目需要重启
k8s中自带的configmap怎么存配置?
ConfigMap用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。ConfigMap跟secret很类似,但它可以更方便地处理不包含敏感信息的字符串。
怎么通过ConfigMap达到配置中心的作用?
创建一个configmap资源,对应着一份配置文件,可以将该资源通过数据卷的形式映射到Pod上,这样Pod就能用上这个配置文件了 ,以管理mysql配置文件为例用下图演示:
spring-cloud-starter-kubernetes-config
spring-cloud-starter-kubernetes-config是spring-cloud-starter-kubernetes框架下的一个库,作用是将kubernetes的configmap与SpringCloud Config结合起来,通过spring-cloud-starter-kubernetes-config,我们的应用就像在通过SpringCloud Config取得配置信息,只不过这里的配置信息来自kubernetes的configmap,而不是SpringCloud Config server,SpringCloud Config来配置的应用几乎不用修改代码,仅仅调整了配置和依赖,就能顺利迁移到kubernetes之上,直接使用原生的配置服务,并且SpringCloud Config Server也可以不用在kubernetes上部署了。
3.如何进行负载均衡?
通过springcloud的Ribbon,也可通过k8s的service、Ingress Controller
4.如何对外发布应用?
通过Ingress
如何通过k8s进行服务编排?
通过编写yaml文件,对每个微服务进行发布
5.k8s部署Spring Cloud项目的整体发布流程
开发代码->提交代码到代码仓库->Jenkins调k8s API->动态生成Jenkins Slave Pod->Slave Pod拉取git上的代码->编译代码->打包镜像->推送镜像到镜像仓库harbor或者docker hub->Slave Pod工作完成之后自动删除->通过k8s编排服务发布到测试、生产平台->通过Ingress发布服务
6.如何通过k8s进行服务编排?
事先写好资源清单文件,然后放到gitlab,我们在调用jenkins的时候,通过pipeline里写上kubectl apply 更新yaml文件,就可以实现自动编排了。