微服务与SpringCloud

微服务架构与SpringCloud

什么是微服务

SpringCloud

服务注册与发现(eureka),服务调用,服务熔断,负载均衡,服务降级,服务消息队列,配置中心管理,服务网关,服务监控,全链路追踪,自动化构建部署,服务定时任务调度操作

分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,称为微服务全家桶

boot和colud的版本选型

https://spring.io/projects/spring-cloud#overview

https://spring.io/projects/spring-cloud#overview

Cloud升级

服务注册中心

(1)Eureka(停止更新,不停用)

(2)Zookeeper

(3)Consul(go语言写的,不建议使用)

(4)Nacos(几乎可以完美的替换Eureka)

服务调用

(1)Ribbon(半生不熟,进入维护状态,停止更新)

(2)LoadBalanc(会逐渐慢慢取代Ribbon,但也不成熟)

服务调用2

(1)Feign(挂了)

(2)OpenFeign

服务降级

(1)Hystrix(官网不建议使用,停更,国内使用的多)

(2)resilience4j(Java)(官网推荐,国内使用少)

(3)sentienl(强烈推荐)

服务网关

(1)Zuul(停用)

(2)Zuul2(没有出来,内部吵架,员工跳槽)

(3)gateWay(目前的主流,spring极度推荐的网关)

服务配置

(1)Config(不再使用)

(2)Nacos(主流)

(3)apolo(也是主流,但是不推荐)

服务总线

(1)Bus(停用)

(2)Nacos(主流)

订单支付模块的微服务

总父工程

POM

project

model

dependencyManagementdependencies的区别

dependencyManagement元素能让所有在子项目中引用一个依赖而不显示的列出版本号.maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用dependencyManagement元素中指定的版本号.只是声明依赖,并不实现引入依赖,因此子项目需要显示的声明需要用额依赖.

如果不再子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写入了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取字父pom

dependencies

微服务模块

1.健modul

2.改pom

3.写YML

4.主启动

5.业务类

自动热部署Devtools

httpClient

restTemplate

Eureka服务注册与发现

Eureka基础知识

什么是服务治理

在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用,负载均衡,容错等,实现服务发现与注册.

什么是服务注册

Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心,而系统中的其他微服务,使用Eureka的客户端链接到Eureka Server并维持心跳连接,这样系统的维护人员就可通过Eureka Server来监控系统中各个微服务是否正常运行.

在服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自己服务器的信息,比如 服务地址通讯地址等以别名方式注册到注册中心上,另一方(消费者|服务提供者),以该别名的方式区注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念),在任何RPC远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))

Eureka包含两个组件:Eureka Server和Eureka Client

Eureka Server提供服务注册服务

各个微服务结点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务结点的信息,服务结点的信息可以在界面中直观看到.

Eureka Client通过注册中心进行访问

是一java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的,使用轮询(round-robin)负载算法的负载均衡器.在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒).如果Eureka Server在多个心跳周期内没有接受到某个结点的心跳,Eureka Server将会从服务注册表中把这个服务结点移除(默认为90秒).

单机Eureka构建步骤

集群Eureka构建步骤

服务注册:将服务信息注册进注册中心.

服务发现,从注册中心上获取服务信息实质;存key服务名取value调用地址.

1.先启动eureka注册中心

2.启动服务提供者payment支付服务

3.支付服务启动后会将自身信息(比如服务地址以别名方式注册进eureka)

4.消费者order服务再需要调用接口时,使用服务别名去注册中心获取实际的RPC远程调用地址.

5.消费者获得调用地址后,底层实际是利用httpClient技术实现远程调用.

6.消费者获得服务地址后会缓存在本地JVM内存中,默认每间隔30秒更新一次服务调用地址.

微服务RPC远程服务调用最核心的是什么

高可用,试想你的注册只有一个only one,它出故障了那就呵呵了,会导致整个为服务环境不可用.所以,解决办法:搭建Eureka注册中心集群,实现负载均衡+故障容错

actuator微服务信息完善

服务发现Discovery

对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息.

Eureka自我保护

将会尝试保护其服务注册表中的信息,

某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存

为什么会产生Eureka自我保护机制?

为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通的情况下,EurekaServer不会立刻将EurekaClient服务剔除.

什么是自我保护模式

默认情况下,如果EurekaServer在一定时间内没有接受到某个微服务实例的心跳,EurekaServer将会注销该实例(默认为90秒).但是当网络分区故障发生(延时,卡顿,拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了-因为微服务本身是健康的,此时本不应该注销这个微服务.Eureka通过"自我保护模式"来解决这个问题-当EurekaServer结点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个结点就会进入自我保护模式.

属于CAP里面的AP分支

如何禁止自我保护

单点故障

Zookeeper服务注册与发现

配置稳健

tickTime心跳默认2000毫秒

initLimit=10 10*2s l和f通讯的时长

syncLimit=5 5*2s 集群正常启动后 l和f通讯的时长

clientPort=2181 客户端连接端口

Zookeeper(保持着最终一致性)

dubbo注册中心和配置中心

springcloud注册中心

elastic-job注册中心

solr管理集群

kafka管理集群

Curator分布式锁

Tinyld分布式id

seata配置中心

大数据领域

SpringCloud整合Zookeeper代替Eureka

1.Zookeeper原子广播协议(Zab)底层原理详解

2.Zab&Raft&Paxos的算法过程和异同点分析

3.快速领导者选举算法底层工作流程分析

4.过半机制与两阶段提交底层核心源码详解

5.云环境下Zookeeper集群会不会出现脑裂

6.高性能Zookeeper&Redis分布式锁原理分析

两个数据库为一个集群.用户将数据库A中的数据改为value=2,用户然后通过数据库B来读取value

强一致性:分布式锁

弱一致性:用户读取value可能永远读到的老数据,有可能不一致,

最终一致性:我在处理读取vlaue的时候,返回的是还是1,用户会隔一段时间在读取value是2.

Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目

Zookeeper从设计模式角度来理解,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册得到那些观察者作出相应的反应.

1.服务端启动时去注册信息(创建的都是临时结点).

2.获取到当前在线服务器列表,并注册监听.

3.服务器结点下线

4.服务器结点下线事件通知

5.process(){

重新获取服务器列表,并注册监听

}

Zookeeper=文件系统+通知机制

文件系统:Zookeeper中存放了一些数据

通知机制:Zookeeper上的结点变化,就会通知客户端

Zookeeper特点:

(1)Zookeeper:一个领导者,多个跟随者.

(2)集群中只要有半数以上结点存活,Zookeeper集群就能正常服务.

(3)全局数据一致,每个server保存一份相同的数据副本,Client无论连接到那个Server,数据都是一致的.

(4)更新请求顺序进行,来自同一个Client的更新请求按器发送顺序执行.

(5)数据更新原子性,一次数据更新要么成功要么失败

(6)实时性,在一定时间范围内,Client能读到最新的数据

Zookeeper数据结构

Zookeeper数据模型的结构与Unix文件系统很类似,整体上可以看做一棵树,每个结点称作一个ZNode.每一个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识,

应用场景

提供的服务

统一命名服务:统一域名下有多个Ip地址

统一配置管理:

1.分布式环境下,配置文件同步非常常见

(1)一般要求一个集群中,所有结点的配置信息时一致的,比如kafka集群,

(2)对配置文件修改后,希望能够快速同步到各个结点上.

2.配置管理可交由Zookeeper实现.

(1)可将配置信息写入Zookeeper上的以Znode.

(2)各个客户端服务器监听这个Znode.

(3)一旦Znode中的数据被修改,Zookeeper将通知各个客户端服务器

统一集群管理:

1.分布式环境下,实时掌握每个结点的状态是必要的

(1)可根据结点实时状态作出一些调整

2.Zookeeper可以实现实时监控结点状态变化,

(1)可将结点信息写入Zookeeper上的一个Znode.

(2)监听这个Znode可获取它的实时状态变化.

服务器动态上下线

客户端能实时洞察到服务器上下线的变化

软负载均衡

在Zookeeper中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求.

Zookeeper内部原理

选举机制

(1)半数机制,集群中半数以上的机器存活,集群可用,所以Zookeeper适合安装奇数台服务器.

(2)Zookeeper虽然在配置文件中并没有指定Master和Slave.但是,Zookeeper工作时,是有一个结点为Leader,其他则为Follower,Leader是通过内部的选举机制临时产生的.

(3)以一个简单的例子来说明整个选举过程:

假设有五台服务器组成的Zookeeper集群,他们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的.假设这些服务器依次启动,

(1)服务器1启动,此时只有一台服务器启动了,它发出去的报文没有任何响应,所以他的选举状态一直是LOOKING状态.

(2)服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己家的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的,依旧是KOOKING状态.

(3)服务器3启动,他与先前的两台服务器进行通讯,互相交换自己的选举结果,由于三者都没有历史数据,所以id值较大的服务器3胜出,超出了半数以上,所以算选举为Leader,一旦选举不可被服务器4和服务器5强走.

结点类型

持久(Persistent):客户端和服务器端断开连接后,创建的结点不删除.

(1)持久化目录结点(Persistent)

(2)持久化顺序编号目录结点(Persistent_sequential),创建znode时设置顺序标识,znode名称会附加一个值,顺序号是一个单调递增的计数器,由父节点维护

注意:在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序.

短暂(Ephemeral):客户端和服务器断开连接后,创建的结点自己删除.

(1)临时目录结点

(2)临时顺序编号目录结点

consul服务注册与发现

简介:是一套开源的分布式服务发现和配置管理系统,有HashiCorp公司用GO语言开发.

提供了微服务系统中的服务治理,配置中心,控制总线等功能,这些功能中的每一个都可以根据需要单独使用,也可以一起使用一构建全方位的服务网络,总之Consul提供了一种完整的网格解决方案.

它具有很多优点,包括:基于raft协议,比较简洁:支持健康检查,同时支持Http和DNS协议支持跨数据中心的WAN集群,提供图形界面,跨平台,支持Linux,Mac,Windows

使用:

1.服务发现:提供Http和DNS两种发现方式.

2.健康检测:支持多种方式,Http,Tcp,Docker,Shell脚本定制化

3.KV存储:Key,Value的存储方式

4.多数据中心:Consul支持多数据中心

5.可视化Web界面

Eureka,Consul,Zookeeper之间的异同点

微服务与SpringCloud_第1张图片

 微服务与SpringCloud_第2张图片

 

C:Consistency强一致性

A:Avaliability高可用

P:Partition tolerance分区容错性

CAP理论关注粒度是数据,而不是整体系统设计的策略

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性三个需求.因此根据CAP原理将NoSql数据库分成了满足CA原则,ZP原则和AP原则三大类.

CA-单点集群,满足一直性,可用性的系统,通常可扩展性不太强大.

CP(Zookeeper/Consul)-满足一致性,分区容错性的系统,通常性能不是特别高.

AP(Eureka)-满足可用性,分区容错性的系统,通常可能对一致性要求低一些.

AP架构:当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性,结论:违背了一致性C的要求,只满足可用性和分区容错,即AP

CP架构:当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证数据一致性,结论:违背了可用性A的要求,只满足一致性和分区容错,即CP

Ribbon负载均衡服务调用

ribbon是基于Netfilx Ribbon实现的一套客户端 负载均衡的工具.

主要功能时提供客户端软件负载均衡算法和服务调用,ribbon客户端组件提供一系列完善的配置项,如连接超时,重试等,简单来说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接,最大权限等)去连接这些机器,我们很容易使用Ribbon实现自定义的负载均衡算法.

LB负载均衡是什么

简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用).

常见的负载均衡有软件Nginx,LVS,硬件F5等.

Ribbon本地负载均衡客户端VSNginx服务端负载均衡区别.

Nginx是服务器负载均衡,客户端所有请求都会交给Nginx,然后由nginx实现转发请求,即负载均衡是有服务端实现的.

Ribbon本地负载均衡,在调用微服务接口时,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而本地实现RPC远程服务调用技术.

集中式LB

即在服务的消费方式和提供方之间使用独立的LB设施(可以是硬件,如F5,也可以是软件,如Nginx),由该设施方把访问请求通过某种策略转发至服务的提供方.

进程内LB

将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器,Ribbon就属于进程内LB,他只是一个类库,集成于消费进程,消费方通过它来获取到服务提供方的地址.

Ribbon就是负载均衡+RestTemplate调用

Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需求的客户端结合使用,和eureka结合只是其中的一个实例.

Ribbon在工作时分为两步:

1.先选择EurekaServer,它优先选择在同一个区域内负载较少的server.

2.在根据用户指定的策略,在从server取到服务注册列表中选择一个地址.

其中Ribbon提供了多种策略,比如轮询,随机和根据响应时间加权.

Ribbon核心组件IRule

IRule:根据特定算法中从服务列表中选取一个要访问的地址.

Ribbon原理

负载均衡算法:rest接口的第几次请求数%服务集群总数量=实际调用服务器位置下标,每次服务重启后rest接口技术从1开始

总计数:2台

list= 2 instance

1%2=1 -> index =1 list.get(index);

2%2=0 -> index =0 list.get(index);

整个系统重启后,重新计数.

OpenFeign服务接口调用

Feign 是一个WebService客户端,使用过Feign,让编写Web服务客户端变得非常容易,只需创建一个接口并在接口并在接口上添加注解即可.

前面在使用Ribbon+RestTemplate时.利用RestTenplate对http请求的封装处理.形成了一套模板化的调用方法,但是咋实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处处理,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用,所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式,来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务客户端的开发量

Feign集成了Ribbon

利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用

微服务与SpringCloud_第3张图片

 

微服务调用接口+@FeignClient

Hystrix服务降级

分布式系统面临的问题

复杂的分布式体系结构中应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败.

服务雪崩

多个微服务调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C有调用其他的微服务,这就是所谓的"扇出".如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的"雪崩效应".

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和,比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统,所以,通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接受流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩.

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性.

"断路器"本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间,不必要地占用,从而避免了故障在分布式系统中蔓延,乃至雪崩个.

服务降级,服务熔断,接近实时的监控

服务降级(fallback)

对方系统不可用,你需要给我一个兜底的解决方法.

比如说:服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示.

那些情况会发生降级:

1.程序运行异常

2.超时

3.服务熔断触发服务降级

4.线程池/信号量打满也会导致服务降级

服务熔断(break)

类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方式并返回友好提示.

服务降级->进而熔断->恢复调用链路

服务限流(flowlimit)

秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行.

hystrix案例

问题:每个业务方法对应一个兜底的方法,代码膨胀,

统一和自定义分开

服务熔断

熔断机制:是应对雪崩效应的一种微服务链路保护机制.当扇出链路的某个微服务出错不可用或者响应时间太长时.

会进行过服务的降级,进而熔断该结点读物得到调用,快速返回错误的响应信息,

当检测到该结点微服务调用响应正常后,恢复调用链路.

在spring cloud框架里,熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制,熔断机制的注解是@HystrixCommand

断路器开启或者关闭的条件:

当满足一定的阈值的时候(默认10秒内超过20个请求次数)

当失败率达到一定的时候(默认10秒内超过50%的请求失败)

到达以上阈值,断路器将会开启

当开启的时候,所有请求都不会进行转发,

一段时间之后(默认为5秒),这个时候断路器是半开状态,会让其中一个请求进行转发,如果成功,断路器会关闭,若失败继续开启,重复4和5.

断路器打开之后:

1.再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback,通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果.

2.原来的主逻辑要如何恢复?

hystrix为我们实现了自动恢复功能.

当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑.当休眠时间窗到期,断路器将会进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间重新计时.

服务限流

hystrix工作流程

服务监控HystrixDashboard:

服务网关

zuul

zuul2

gateway:

简介:

旨在提供一种简单而有效的方式来对api进行过路由,以及提供一些强大的过滤器功能,例如熔断,限流,重试等等

springCloud Gateway作为Spring Cloud生态系统中的网关,目标是代替Zuul,在Spring Cloud2.0以上的版本中,没有对新版Zuul2.0以上最新高性能的版本进行集成,任然使用的Zuul1.x非Reactor模式的老版本,而为了提升网关性能,在Spring Cloud Gareway是基于WebFlux框架实现的,而WebFlux框架则使用了高性能的Reactor模式通讯框架Netty.

Spring Cloud Gateway的目标提供同一的路由方式且基于Filter链的方式提供了网关的基本功能,例如:安全,监控/指标,和限流.

能干什么

反向代理

鉴权

流量控制

熔断

日志监控

..............

微服务架构中网关在哪里

在nginx之后,所有微服务的入口

Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心,虽然Netflix早就发布了最新的Zuul 2.x,但Spring Cloud貌似没有整合计划,而且NetFlix相关组件都宣布进入维护期,不值前景如何?

Spring Cloud Gateway特性

基于Spring Framework ,Project Reactor 和 Spring Boot

进行搭建.

动态路由:能够匹配任何请求属性

可以对路由指定Predicate(断言)和Filter(过滤器)

集成Hystrix的断路器功能;

集成Spring Cloud服务发现功能;

易于编写的Predicate(断言)和Filter(过滤器)

请求限流功能;

支持路径重写

传统的web框架,比如说:struts

,SpringMVC等都是基于Servlet API与Servlet容器基础上运行的.但是,在Servlet之后有了异步非阻塞的支持,而WebFlux是一个典型得非阻塞异步的框架,它的核心是基于Reactor的相关API实现的,相对于传统的web框架来说,他可以运行在诸如Netty,Undertow及支持Servlet的容器上,非阻塞式+函数式编程(Spring必须让你使用Java8)

Spring WebFlux是spring 5.0引入的新的响应式编程,区别于Spring MVC,它不需要依赖Servlet API,它是全部异步非阻塞的,并且基于Reactor来实现响应式流规范.

gateway的三大狠心概念

Route(路由):路由是构建网关的基本模块,它由ID,目标URL,一系列的断言和过滤器组成,如果断言为true则匹配该路由.

Predicate(断言):参考的是Java8的java.util.function.Predicate.开发人员可以匹配Http请求中的所有内容(例如请求头或请求参数)如果请求与断言相匹配则进行路由

Filter(过滤):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改.

总体:

Gateway网关路由的两种方式

1.配置文件中yml中配置

2.代码中注入RouteLocator的Bean

使用微服务名实现动态路由

默认情况下,Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能.

Predicate

After,Befor,between

1.jmeter

2.postman

3.curl + 服务地址

总结:说白了,predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理

Filter的使用:

路由过滤器可用于修改进入的HTTP请求,和返回的HTTP响应,路由过滤器只能指定路由来进行使用.

Spring Cloud GateWay内置了多种路由过滤器,他们都由GateWayFilter的工厂类来产生.

声明周期(两个):pro/post

种类(两个):GateWayFilter(31)/GlobalFilter(10)

SpringCloudConfig分布式配置中心

分布式系统面临的配置问题?

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必要的配置信息才能运行,所以一套集中式的,动态的配置管理设施是必不可少的.

Spring Cloud提供了ConfigServer来解决这个问题,我们每一个微服务自己带着一个application.yml,上百个配置文件的管理.

是什么:SpringCloudConfig为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置.

怎么玩:分为服务端和客户端两部分

服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口.

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容.

能干什么:

1.集中管理配置文件

2.不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod/beta/release

3.运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己家的信息.

4.当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置.

5.将配置信息以REST接口的形式暴露,(post,curl访问刷新均可)

与GItHub整合配置.

application.yml是用户级的资源配置项

bootstrap.yml是系统级的,优先级更高

SpringCloud会创建一个"Bootstrap Context",作为Spring应用的"Application Context"的父上下文,"Bootstrap Context"负责从外部源加载配置属性并解析配置,这两个上下文共享一个从外部获取的"Environment".

"Bootstrap"属性有高优先级,默认情况下,他们不会被本地配置覆盖,"Bootstrap Context"和"Application Context"有着不同约定,所以新增了一个"bootstrap.yml"文件,保证"Bootstrap Context"和"Application Context"配置的分离

要将Client模块下的application.yml文件改为bootstrap.yml,这是很关键的.

因为bootstrap.yml是必application.yml先加载的,优先级更高

SpringCloudBus消息总线

分布式自动刷新配置功能

是什么?

两种消息代理,RabbitMQ和Kafka

Spring Cloud Bus配合Spring Cloud Config使用可以实现配置的动态刷新.

Spring Cloud Bus是用来将分布式系统的结点与轻量级消息系统连接起来的框架,它整合了Java的事件处理机制和消息中间件的功能.Spring Club Bus目前支持RabbitMQ和Kafka.

Spring Cloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改,事件推送等,也可当做微服务间的通信通道.

什么是总线?

在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来,由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线,在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息.

基本原理:

ConfigClient实例都监听MQ中同一个topic(默认是SpringCloudBus).当一个微服务刷新数据的时候,它会把这个信息放入到Topic中,这样其他监听同一Topic的服务就能得到通知,然后去更新自身的配置.

SpringCloud Stream消息驱动

为什么引入Cloud Stream

是什么?

屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型.

是一个构建消息驱动微服务框架

应用程序通过inputs和outputs来与Spring Cloud Stream中的binder对象交互/

通过我们配置来birding(绑定),而Spring Cloud Stream的binder对象负责与消息中间件交互.

所以,我们只需要搞清楚如何与Spring Cloud Stream交互就可以方便使用消息驱动的方式.

通过使用spring Intergration来连接消息代理中间件以实现消息事件驱动,Spring Cloud Stream为一些供应商的消息中间件提供了个性化的自动化配置实现,引用了发布-订阅,消费组,分区的三个核心概念,目前仅支持RabbitMQ和Kafka

解决的痛点

MQ(消息中间件)

ActiveMQ

RabbitMQ

RocketMQ

KafkaMQ

有没有一种新的技术诞生,让我们不再关注具体MQ的细节,我们只需要用一种适配绑定的方式,自动的给我们在各种MQ内切换

Spring Cloud Stream 设计思想

生产者/消费者之间靠消息媒介传递信息内容. Message

消息必须走特定的通道. 消息通道MessageChannel

消息通道里的消息如何被消费呢?谁负责收发处理.消息通道中的子接口SubscribableChannel,由MessageHandler消息处理器所订阅.

比方说我们用到了RabbitMQ和Kafka,由于这两个消息中间件的架构上的不同,像RabbitMQ有exchange,Kafka有Topic和Partitions分区

Stream为什么可以屏蔽底层

通过定义绑定器作为中间层,完美的实现了应用程序与消息中间件细节之间的隔离.

通过向应用程序暴露统一的Channel通道,使得应用程序不需要再考虑各种不同的消息中间件实现

通过定义绑定器,Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离

标准流程套路

编码API和常用注解

分组消费和持久化

运行后两个问题:

1.有重复消费问题:目前是8802/8003同时收到了,存在重复消费问题.

导致原因:

默认分组group是不同的,组流水号不一样,被人为不同组,可以消费.

自定义配置分组

自定义配置分成同一个组,解决重复消费问题

如何解决:分组和group

在Stream中处于同一个group中的多个消费者是竞争关系,就能够保证消息只会被其中一个应用消费一次,不同组是可以全面消费的(重复消费)

同一个组内会发生竞争关系,只有其中一个可以消费

2.消息持久化问题

分组

SpringCLoudSleuth分布式请求链路跟踪

是什么?

在分布式系统中提供了追踪解决方案并且兼容支持了zipkin()

zipkin

一条链路通过Trace Id唯一标识,Span标识发起的请求信息,个span通过parent id关联起来.

微服务与SpringCloud_第4张图片

 

Trance:类似于树结构的span集合,标识一条调用链路,存在唯一标识.

span:标识调用链路来源,通俗的理解span就是一次请求信息.

SpringCLoud Alibaba入门简介

为什么会出现SpringCLoud Alibaba

SpringCloudAlibaba带来了什么

SpringCloudAlibaba

官网:spring-cloud-alibaba/README-zh.md at 2.2.x · alibaba/spring-cloud-alibaba · GitHub

能干嘛?

服务限流降级:默认支持Servlet,Feign,RestTemplate,DUbbo,RocketMQ限流降级功能的接入.可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级Metrics监控.

服务注册与发现:适配Spring Cloud服务注册与发现标准,默认集成了Ribbon的支持.

分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新.

消息驱动能力:基于Spring Cloud Stream为微服务应用构建消息驱动能力.

阿里云对象存储:阿里云提供的海量,安全,低成本,高可靠的云存储服务,支持在任何应用,任何时间,任何地点存储和访问任意类型的数据.

分布式任务调度:提供秒级,精准,高可靠,高可用的定时(基于Cron表达式)任务调度服务,同时提供分布式的任务执行模型,如网格任务.网格任务支持海量字任务均匀分配到所有Worker(schedulex-client)上执行.

SpringCloud Alibaba Nacos服务注册和配置中心

Nacos简介:

前四个字母分别为Naming和Configuration的前两个字母最后的s为Service.

是什么?

一个更易于云原生应用的动态服务发现,配置管理和服务管理平台.

Nacos:Dynamic Naming and Configuration Service

Nacos就是注册中心+配置中心的组合

Nacos=Eureka+Config+Bus

能干嘛?

替代Eureka做服务注册中心

替代Config做服务配置中心

去哪下

http://github.com/alibaba/Nacos

Nacos支持AP和CP的切换

C是所有结点在同一时间看到的数据是一致的;而Ade定义时所有的请求都会收到响应.

何时选择使用何种模式?

一般来说:

如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式,当前主流的服务如Spring Cloud和Dubbo服务,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例.

如果需要在服务级别编辑或存储配置信息,那么CP是必须的,K8S和DNS服务则适用于CP模式.

CP模式下则支持注册持久化实例,此时则是以Raft协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误.

Nacos同Springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后才能保证项目的正常启动.

Spring Boot中配置文件的加载存在优先级顺序的,bootstrap优先级高于application

nacos中的匹配规则

理论:Nacos的dataid的组成格式及与SpringBoot配置文件中的匹配规则

Nacos作为配置中心-分类配置

问题:多环境多项目管理

1.通常一个系统会准备:

dev开发环境

test测试环境

prod生产环境

如何保证指定环境启动时服务能正确读到Nacos上相应环境的配置文件呢?

2.一个大型分布式微服务会有很多微服务子项目,

每个微服务项目又都会有相应的开发环境,测试环境,预发环境,正式环境,

那么怎么对这些微服务配置进行管理呢?

Namespace(命名空间)+group+DateId三者关系,为什么这么设计

1.是什么

类似java中的package名和类名.

最外层的namespace是可以用于区分部署环境的,Group和Dataid逻辑上区分两个目标对象.

2.三者情况

微服务与SpringCloud_第5张图片

 

默认情况:

Namespance=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT

Nacos默认的命名空间是public,Namespace主要用来实现隔离.

比方说我们现在有三个环境,开发,测试,生产环境,我们就可以创建三个Namespance,不同的Namespance之间是隔离的.

Group默认是DEFAULT_GROUP,group可以把不同的微服务划分到同一个分组里面去.

Service就是微服务,一个Service可以包含多个Cluster(集群),Nacos默认是Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分.

比方说为了容灾,将Service微服务分别部署在了杭州机房和广州机房

这时就可以给杭州机房的Service微服务器一个集群名称(HZ),

给广州机房的一个Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用.

最后是Instance,就是微服务的实例.

Case:

三种方案加配置:

DataID:指定spring.profile.active和配置文件的DataID来使不同环境下读取不同的配置.

默认空间+默认分组+新建dev和test两个DataID.

通过spring.profile.active属性就能进行多环境下配置文件的读取

Group方案

Nacos集群和持久化配置

linux版Nacos+Mysql生产环境配置

1.预计需要1个Nginx+3个nacos注册中心+1个mysql

一个nacos:startup 8848

三个nacos: 3333 4444 5555

startup:---> linux里面的nacos脚本

startup -p 3333

springCloud Sentinel Alibaba Sentinel

Sentinle:分布式系统的流量防卫兵

Hystrix

1.需要我们程序员自己手工搭建监控平台

2.没有一套web界面可以给我们进行更加细粒度化的配置,流控,速率控制,服务熔断,服务降级.......

Sentinel:

1.单独一个组件可以独立出来.

2.直接界面化的细粒度同一配置.

约定>配置>编码

都可以写在代码中,但是本次还是大规模的学习使用配置和注解的方式.

是什么:就是Hystrix

Sentinel分为两个部分:

核心库(java客户端):不依赖于任何框架/库,能够运行于所有java运行环境,同时对Dubbo/Spring Cloud等框架也有较好的支持.

控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外而定Tomact等应用容器.

流控规则:

资源名:唯一名称,默认请求路径

针对来源:sentinel可以针对调用者进行限流,填写微服务名,默认为default(不区分来源)

阈值类型/单击阈值:

1.QPS(每秒钟的请求数量):当调用api的QPS达到阈值时,进行限流

2.线程数:当调用该api的线程数达到阈值的时候,进行限流

是否集群:不需要集群

流控模式:

1.直接:api达到限流条件时,直接限流

2.关联:当关联的资源达到阈值时,就限流自己

3.链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)[api级别的针对来源].

流控效果:

1.快速失败:直接失败抛出异常

2.Warm Up:根据codeFator(冷加载因子,默认3)的值,从阈值/codeFator,经过预热时长,才达到的QPS阈值.

3.排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效.

直接调用默认报错信息,技术方面OK,but是否应该有我们自己的后续处理,类似fallback方法

降级规则:

1.RT(平均响应时间,秒级)

平均响应时间,超出阈值且在时间窗口内通过的请求>=5,两个条件同时满足后触发降级

窗口期过后关闭断路器

RT最大4900(更大的需要通过 -Dcsp.sentinel.statistic.max.rt=xxxx才能生效)

2.异常比例(秒级)

QPS>=5且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级.

3.异常数(分钟级)

异常数(分钟统计)超过阈值时,触发降级,时间窗口结束后,关闭降级

Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联错误.

当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException)

异常比例:当资源的美秒请求量>=5,并且每秒异常总数占通过量的比值超过阈值,之后资源进入降级状态,即在接下的时间窗口(以秒为单位)之内,对这个方法的调用都会自动地返回,异常比率的阈值范围是[0.0,1.0],代表0%~100%

热点key限流:

兜底方法:

分为系统默认和客户自定义,两种

之前case,限流出问题后,都是用sentinel系统默认的提示:Blocked by sentinel(flow limiting)

我们能不能自定义类似于hystrix某个方法出问题了,就找对应的兜底降级方法?

结论:

从hystrixCommand到@SentinelResource

系统自适应限流:

sentinel系统自适应限流从整体维度对应用入口流量进行控制,结合应用的Load,CPU使用率,总体平均RT,入口QPS和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能尽可能跑在最大吞吐量的同时保证系统整体的稳定性.

Load自适应(仅对Linux/Unix-like机器生效):系统的load1作为启发指标,进行自适应系统保护.当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段).系统容量由系统的maxQpsminRt估算得出.设定参考值一般是CPU cores2.5.

CPU usage(1.5.0+ 版本):当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0),比较灵敏.

平均RT:当单台机器上所有入口流量的平均Rt达到阈值即触发系统保护,单位是毫秒.

并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护.

入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护.

@SentinelResource:

1.按资源名限流+后续处理

执行自己的限流方法

2.按URL限流+后续处理

返回sentinel自带的限流模式

上面兜底方案面临的问题:

1.系统默认的,没有体现我们自己的业务要求

2.依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观

3.每个业务方法都添加一个兜底的,那代码膨胀加剧.

4.全局同一的处理方法没有体现

客户自定义限流处理逻辑:

创建一个CustomerBlockHandle类用于自定义限流处理逻辑

服务熔断功能:

sentinel整合ribbon+openFeign+Fallback

服务消费者84端口

Feign组件一般是消费侧

熔断框架

1.Sentinel:

隔离策略:信号量隔离(并发线程数限流)

熔断降级策略:基于响应时间,异常比率,异常数

实时统计实现:滑动窗口(LeapArray)

动态规则配置:支持多种数据源

扩展性:多个扩展点

基于注解的支持:支持

限流:基于QPS,支持基于调用关系的限流

控制台:提供开箱即用的控制台,可配置规则,查看秒级监控,机器发现等

2.Hystrix

隔离策略:线程池隔离/信号量隔离

熔断降级策略:基于异常比率,

实时统计实现:滑动窗口(基于RxJava)

动态规则配置:支持多种数据源

扩展性:插件的形式

基于注解的支持:支持

限流:有限的支持

控制台:简单的监控查看

sentine持久化

一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化.

将限流配置和规则持久化进Nacos保存,只要刷新某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8041上sentinel的流控规则持续有效.

"resource":"资源名称,
"limitApp":来源应用,
"grade":阀值类型,0表示线程数,1表示QPS
"count":单击阈值,
"stategy":流控模式,0表示直接,1表示关联,2表示链路
"controlBehavior":流控效果,0快速失败,1表示Warm up,2表示排队等待
"clusterMode":是否集群 false

SpringCloudAlibaba Seata处理分布式事务

分布式事务问题:

分布式之前:单机单库这个没问题.

1:1

1:N:比如说卖家库和卖家库,下订单和库存

N:N:订单模块连的订单库,物流库存库,减库存,做支付

分布式之后

用户购买商品的业务逻辑,整个业务逻辑由三个微服务提供支持.

仓库服务:对给定的商品扣除仓库数量.

订单服务:根据采购需求创建订单.

账户服务:从根用户账户中扣除余额.

单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,业务操作需要调用三个服务来完成,此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题没法保证

一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题.

分布式事务(XA的二段式提交,三段式提交,TCC协议)

Seata简介:

是什么:Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务.

一个典型的分布式事务过程:分布式事务处理过程的--ID+三组件模型.

Transaction ID XID 全局唯一的事物ID

三组件:

Transaction Coordinator(TC):事务协调者

事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚.

Transaction Manger(TM):事务管理器

控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议

Resource Manager(RM):资源管理器

控制分支事务,负责分支注册,状态汇报,并接受事务协调器的指令,驱动分支(本地)事务的提交和回滚.

1.TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID.

2.XID在微服务调用链路的上下文中传播.

3.RM向TC注册分支事务,将其纳入XID对应全局事务的管辖.

4.TM向TC发起针对XID的全局提交或回滚决议.

5.TC调度XID下管辖的全部分支事务完成提交或回滚事务.

分布式事务业务说明

创建三个微服务,一个订单服务,一个库存服务,一个账户服务.

当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存,在通过远程调用账户服务来扣减用户账户里面的余额.

最后在订单服务中修改订单状态为已完成,

该操作跨越三个数据库,有两次远程调用,很明显会有分布式事务问题.

下订单--->扣库存--->减账户(余额)

按照三个库分别建对应的回滚日志表

业务需求

下订单-->减库存-->扣余额-->改订单状态

故障情况:

当库存和账户金额扣减后,订单状态并没有设置为已完成,没有从零改为1.

而且由于feign的重试机制,账户余额还有可能被多次扣减.

Seata

2019年1月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案.

Simple Extensible Automous Transaction Architecture,简单可扩展自治事务框架.

再看TC/TM/RM三大组件

TC:全局协调管理者(Seata服务器)

TM:标记了@GlobalTransaction的方法,事务的发起方.

RM:一个数据库就是一个RM,事务的参与方

分布式事务的执行流程:

1.TM开启分布式事务(TM和TC注册全局事务记录)

2.按业务场景,编排数据库,服务等事务内资源(RM向TC汇报资源准备状态)

3.TM结束分布式事务,事务一阶段结束(TM通知TC提交/回滚分布式事务)

4.TC汇总事务信息,决定分布式事务是提交还是回滚.

5.TC通知所有RM提交/回滚资源,事务二阶段结束

AT--阿里云 GTS

AT模式如何做到对业务的无侵入:

是什么:

整体机制:

一阶段加载:

1.解析sql语义,找到业务sql要更新的业务数据,在业务数据被更新前,将其保存成"before image"

2.执行"业务sql"更新业务数据,在业务数据更新之后.

3.将其保存成"after image"最后生成行锁.

以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性.

二阶段提交:

因为"业务sql"在一阶段已经提交到数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可.

二阶段回滚:

二阶段如果是回滚的话,Seata就需要回滚一阶段已经执行的"业务SQL",还原业务数据.

回滚方式便是用"before image"还原业务数据,但在还原前要首先要校验脏写,对比"数据库当前业务数据"和"after image",如果两份数据完全一致的就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理.

你可能感兴趣的:(spring,cloud,java,微服务)