Eureka 包含两个组件 Eureka Server和Eureka Client
Eureka Server 提供服务 注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中
将会存储所有可用服务节点的信息,服务节点的信息可用在界面直观看到
EurekaClient 通过注册中心进行访问
EurekaClient是一个java客户端,用于简化Eurrka Server的交互,客户端同时也具备一个内置的,
使用轮训(round-robin)负载算法的均衡器,在应用启动后,姜维想Eureka Server发送心跳
默认周期是30秒,如果Eurela Server在多个心跳周期内没有接胡搜啊到某个节点的心跳,
EurekaServer将会从服务注册表中吧这个服务节点移除 默认90秒
什么是服务治理
springcloud 封装了Netflix公司开的Eureka模块来实现服务治理
在传统的rpc远程调用中,管理么个服务与服务之间依赖关系比较复杂,管理比较服务在,所以需要使用
服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务与注册。
什么是服务注册与发现
Eureka 采用了cs的设计架构,Eureka server作为服务注册功能的服务器,他是服务注册中心,而系统中的其他
微服务,使用Eureka的客户端连接到Eureka server并维持心跳连接,这样系统的维护人员就可以同Eureka server
来监视系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务启动的时候,会吧自己当前的服务器的信息,比如服务地址、通讯地址
等一别名方式注册到注册中心上,另一方 消费者|服务提供者,以该别名的方式去注册中心上获取到实际的服务通讯
地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在注册中心,因为使用注册中心管理每个服务与服务之间
的一个依赖关系(服务治理概念)。在任何rpc远程框架中国,都会有一个注册中心(存放服务地址相关信息 接口地址)
集群构建eurake
问题:微服务RPC远程调用服务最核心的是什么
高可用,试想你的注册中心只有一个only one,他出故障了那就呵呵了,会导致整
个服务环境不可用,所以
解决办法:搭建Eureka注册中心集群,实现负载均衡+故障容错
保护模式
故障现象
概述
保护欧式主要用于一组客户端和Eureka server之间存在网络分区场景下的保护,一旦进行
保护模式
Eureka Server将会尝试保护其服务注册表中的信息,不在删除服务注册表中的数据
也就是不会注销任何微服务
如果Eureka Server的首页看到一下这段提示,则说明Eureka进入了保护模式
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT.
RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE
为什么会出现Eureka 自我保护机制
为了防止EurekaClient 可以正常运行,但是与EurekaServer网络不通情况下
EurekaServer不会立刻将EurekaClient服务删除
什么是自我保护模式
默认情况下,如果EruekaServer在一定时间内没有接受到某个微服务实例的心跳
EurekaServer将会注销该实例(默认是90秒)。但是当网络分区故障发生(延时、
卡顿、拥堵)时,微服务与EurekaServer之间无法正常通信,以上行为可能变的
非常危险了——因为微服务本身其实是健康的,次数本不应该注销这个微服务。
Eureka通过“自我保护模式”来解决这个问题,——当EurekaServer节点在短时间内
丢失过多客户端是(可能番僧了网络分区故障),那么这个阶段机会进入保护模式
在自我保护模式中,EurekaServer会保护注册表中的信息,不再注销任何服务实例
他的设计哲学就是宁可保留错误的微服务信息,也不盲目的注销任何可能简单的服务实例。
综上,自我保护模式是一中应对网络异常的安全保护措施,他的架构哲学是宁可同时保留
所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何简单的微服务,使用自我
保护模式,可以让Eureka集群更加的健壮、稳定。
一句话:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存
属于CAP里面的AP分支
怎么禁用微服务
出厂默认自我保护机制是开启的,使用eureka.server.enable-self-preservation = false 可以禁用自我保护模式
springcloud 整合Zookeeper代替Eureka
注册中心Zoookeeper
zookeeper是一个分布式协调工具,可以实现注册中心功能,关闭linux服务器防火墙后启动zookeeper服务器
zookeeper服务器取代Eureka服务器,zk作为服务注册中心
zookeeper安装
这里我们下载最新版的3.7.0版本的Zookeeper版本
这里注意:选择带bin的压缩包
mv zoo_sample.cfg zoo.cfg
#修改zoo.cfg信息
dataDir=/tmp/zookeeper
dataLogDir=/tmp/zookeeper/log
#创建上边两个目录
#添加环境变量
export ZOOKEEPER=/usr/local/zookeeper/(Zookeeper所在的目录)
export PATH=$PATH:$ZOOKEEPER/bin
#运行使配置问价立即生效
source /etc/profile
#命令启动、查看zookeepeer状态、启动zookeeper客户端。
zkServer.sh start
zkServer.sh status
zkCli.sh
#启动成功外部访问时候需要关闭防火墙
#关闭防火请
ufw disable
#查看防火请状态
ufw status
#查看服务
zkCli.sh
ls /
#选择服务项
ls /services
ls /services/cloud-provider-payment
CAP
CAP原则又称为CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)
CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值,即写操作之后的读操作,必须返回该值。(分为弱一致性、强一致性和最终一致性)
可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
zookeeper的服务节点是临时节点
Eureka的服务节点是持久节点
对应来说zookeeper/consul一致性的即CP
对应来说Eureka高可用的AP
CP架构
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性
结论:违背了可用性A的要求,只满足一致性和分区容错,即CP
Consul服务注册与发现
Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorp公司用go语言开发。
提供了微服务系统中的服务治理、配置中心、控制总线等功能,这些功能中的每一个都可以根据需求单独使用,
也可以一起使用以构建全访问的服务网格,粽子consul提供了一种完整的服务网格解决方法。
他具有很多有点,包括:基于raft协议,比较简洁,支持健康度检查,同时支持http和DNS协议,支持跨数据中心的WAN集群,提供图形界面,支持LINUX、MAC、Windows
consule 功能
服务发现:提供HTTP和DNS两个方式
健康监测:支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控
KV存储:Key、Value的存储方式
多数据中心:Consul支持多数据中心
运行方式
#windows版本 下载
#cmd 运行
consul.exe agent dev
#访问
localhost:8500
Rinbbon 负载均衡服务调用
springcloud Ribbon 是基于Netflix Ribbon实现的一套客户端 负载均衡工具
简单来说,Ribbon 是netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用,Ribbon客户端组件提供了一些列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出load Balance 简称LB后边所有的及其,Ribbon会自动的帮助你基于某种规则 如减的轮训,随机连接等去连接这些机器,我们很容易使用Ribbon实现自定义的负载均衡算法。
Ribbon目前也进入维护模式
LB负载均衡Load Balance 是什么
简单的说就是将用户的请求平摊的分配到多个服务器上,从而达到系统的HA高可用,
常见的负载均衡有软件Nginx、LVS硬件F5等。
Ribbon 本队负载均衡客户端Vs Nginx 服务端负载均衡区别
Nginx是服务器负载均衡,客户端所有请求都会交给Nginx,然后由nginx实现转发骑牛,即负载均衡是有服务端实现的。
Ribbon本地负载均衡,在调用微服务接口试试,会在注册中心上获取注册信息服务列表之后缓存到jvm本地,从而在本地实现rpc远程服务调用技术
集中式LB
即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;
进程内LB
将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
负载均衡+RestTemplate调用
Ribbon 负载均衡演示
Ribbon在工作时分成两步
第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。
前写样例时候没有引入spring-cloud-starter-ribbon也可以使用ribbon,
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
猜测spring-cloud-starter-netflix-eureka-client自带了spring-cloud-starter-ribbon引用,
证明如下: 可以看到spring-cloud-starter-netflix-eureka-client 确实引入了Ribbon
RestTemplate 的使用
返回对象为响应体重数据转化成的对象,基本上可以理解为json
返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头、响应状态码、响应体等
postForObject/postForEntity
GET请求方法
T getForObject(String url, Class responseType, Object… uriVariables);
T getForObject(String url, Class responseType, Map
T getForObject(URI url, Class responseType);
ResponseEntity getForEntity(String url, Class responseType, Object… uriVariables);
ResponseEntity getForEntity(String url, Class responseType, Map
ResponseEntity getForEntity(URI var1, Class responseType);
POST请求方法
T postForObject(String url, @Nullable Object request, Class responseType, Object… uriVariables);
T postForObject(String url, @Nullable Object request, Class responseType, Map
T postForObject(URI url, @Nullable Object request, Class responseType);
ResponseEntity postForEntity(String url, @Nullable Object request, Class responseType, Object… uriVariables);
ResponseEntity postForEntity(String url, @Nullable Object request, Class responseType, Map
ResponseEntity postForEntity(URI url, @Nullable Object request, Class responseType);
Ribbon核心组件IRule
IRule:根据特定算法中从服务列表中选取一个要访问的服务
com.netflix.loadbalancer.RoundRobinRule 轮询
com.netflix.loadbalancer.RandomRule 随机
com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule轮询策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
WeightedResponseTimeRule 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
AvailabilityFilteringRule 先过滤掉故障实例,再选择并发较小的实例
ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
官方文档明确给出了警告:
这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,
否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。
openFeign 服务接口调用
openFeign 是什么
官网解释:
https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/#spring-cloud-openfeign
Fegin是一个声明式webservice客户端,使用feign能让编写webService客户端更佳丹丹
他的使用方法是定义一个服务接口然后在上面添加注解,feign也支持可插拔式的编码器和解码器,spring cloud对feign进行封装,使其支持了springmvc标准注解和httpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡
Feign能干吗
Feign旨在使编写java http客户端变的更加容易
前面在使用Ribbon+ResrTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模板话的调用方法,但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多出调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用,所以Feign在此基础上做了进一步防撞,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置他,以前是dao接口上面标注Mapper主机额,现在是一个微服务接口上面标志一个Feign注解即可,即可完成对服务提供方的接口绑定,简化了使用spring cloud Ribbon时,自动封装服务调用客户端的开发量。
Feign 集成了Ribbon
利用Ribbon维护payment的服务列表信息,并且通过轮训实现了客户端的负载均衡,而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
feign和openFeign的区别
Feign
Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
OpenFeign
OpenFeign是Spring Cloud 在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
默认Feign客户端只等待一秒钟,
但是服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错。
为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。
yml文件中开启配置
OpenFegin日期打印功能
Feign提供了日志打印功能那个,我们可以通过配置来调整日志级别。从而了解Feign中http请求的细节,说白了
就是对Feign接口的调用情况进行监控和输出。
日志级别
NONE:默认的,不显示任何日志;
BASIC:仅记录请求方法、URL、响应状态码及执行时间;
HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。
Hystrix断路器
分布式系统面临的问题
负载分布式系统结构的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败
服务雪崩
多个微服务之间调用的时候,建设微服务A调用微服务B和微服务C,微服务B和微服务C又迪奥弄其他的微服务,这就是所谓的“扇出”,如果扇出的链路上的某个微服务的调用时间过长或者不可yoga,对微服务A的调用就会占用越来越多的系统资源,进而引起系统的崩溃,所谓的雪崩效应
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和,比失败更糟糕的是,这些应用还可能导致服务之间的延迟增加,备份队列、线程和其他系统资源紧张,导致整个系统发生更多级联故障,这些都表示对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用或系统
所以通过当你发现一个模块下的某个实例失败后,这个时候这个模块亦然还会接受流量,然后这个又问题的模块还调用了其他模块,这样就会发生级联故障,或者叫雪崩。
Hystrix是一个用于处理分布式系统的延迟和容错的开源库
,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
Hystrix主要的作用
服务降级
服务熔断
接近实时的监控
Hystrix官宣,停更进维
Hystrix重要概念
服务降级
服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好的提示
那些情况会发出服务降级:程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满也会导致服务降级
服务熔断
类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示
服务的降级->进而熔断->恢复调用链路
服务限流
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行
@DefaultProperties(defaultFallback = “”)
1 每个方法配置一个服务降级方法,技术上可以,但是实际太过麻烦。
除了重要核心业务有专属,其他普通的可以通过@DefaultProperties(defaultFallback = “”) 统一跳转到统一处理结果页面
服务熔断机制概述
熔断机制是对应雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务出错不可用或者响应太长时,
会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息
当监测到该节点微服务调用响应正常后,恢复调用链路
在spring cloud框架里,熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,
当失败的调用到一定阈值,缺省是五秒内20次调用失败,就会启动熔断机制,,熔断机制的主机是@HystrixCommand。
理论论文:https://martinfowler.com/bliki/CircuitBreaker.html
涉及到断路器的三个重要参数:快照时间窗、请求总数阀值、错误百分比阀值。
1:快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。
2:请求总数阀值:在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。
3:错误百分比阀值:当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%阀值情况下,这时候就会将断路器打开。
断路器开启或者关闭的条件
- 当马努组一定的阈值的时候 默认10秒内超过20个请求次数
- 当失败率达到一定的时候 默认是10秒内超过50%的请求失败
- 到达以上阈值,断路器会开启
- 当开启的时候,所有的其你去都不会进行转发
- 一段时间之后 默认是5秒,这个时候断路器是半开状态,会让其中一个请求进行转发,如果成功,断路器会关闭,若失败,继续开启,重复4和5。
断路器打开之后 - 再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback,通过断路器,实现了自动地转发错误并将降级逻辑切换到主逻辑,减少响应延迟的效果
- 原来的主逻辑要如何恢复?
对于这一个问题,hystrix也为我们实现了自动恢复功能。
当段落器打开,对主扩机进行熔断之后,hystrix会启动一个休眠时间窗。这个时间窗口内,降级逻辑成为临时的主逻辑。
当休眠时间窗到期,断路器进行半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回妈妈断路器将继续闭合,
主逻辑恢复,如果这次请求亦然有问题,断路器继续进行打开专挑没休眠时间窗重新计时。
所有配置
//========================All
@HystrixCommand(fallbackMethod = "str_fallbackMethod",
groupKey = "strGroupCommand",
commandKey = "strCommand",
threadPoolKey = "strThreadPool",
commandProperties = {
// 设置隔离策略,THREAD 表示线程池 SEMAPHORE:信号池隔离
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
// 当隔离策略选择信号池隔离的时候,用来设置信号池的大小(最大并发数)
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),
// 配置命令执行的超时时间
@HystrixProperty(name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"),
// 是否启用超时时间
@HystrixProperty(name = "execution.timeout.enabled", value = "true"),
// 执行超时的时候是否中断
@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
// 执行被取消的时候是否中断
@HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "true"),
// 允许回调方法执行的最大并发数
@HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),
// 服务降级是否启用,是否执行回调函数
@HystrixProperty(name = "fallback.enabled", value = "true"),
// 是否启用断路器
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
// 该属性用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为 20 的时候,
// 如果滚动时间窗(默认10秒)内仅收到了19个请求, 即使这19个请求都失败了,断路器也不会打开。
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
// 该属性用来设置在滚动时间窗中,表示在滚动时间窗中,在请求数量超过
// circuitBreaker.requestVolumeThreshold 的情况下,如果错误请求数的百分比超过50,
// 就把断路器设置为 "打开" 状态,否则就设置为 "关闭" 状态。
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
// 该属性用来设置当断路器打开之后的休眠时间窗。 休眠时间窗结束之后,
// 会将断路器置为 "半开" 状态,尝试熔断的请求命令,如果依然失败就将断路器继续设置为 "打开" 状态,
// 如果成功就设置为 "关闭" 状态。
@HystrixProperty(name = "circuitBreaker.sleepWindowinMilliseconds", value = "5000"),
// 断路器强制打开
@HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
// 断路器强制关闭
@HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),
// 滚动时间窗设置,该时间用于断路器判断健康度时需要收集信息的持续时间
@HystrixProperty(name = "metrics.rollingStats.timeinMilliseconds", value = "10000"),
// 该属性用来设置滚动时间窗统计指标信息时划分"桶"的数量,断路器在收集指标信息的时候会根据
// 设置的时间窗长度拆分成多个 "桶" 来累计各度量值,每个"桶"记录了一段时间内的采集指标。
// 比如 10 秒内拆分成 10 个"桶"收集这样,所以 timeinMilliseconds 必须能被 numBuckets 整除。否则会抛异常
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
// 该属性用来设置对命令执行的延迟是否使用百分位数来跟踪和计算。如果设置为 false, 那么所有的概要统计都将返回 -1。
@HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "false"),
// 该属性用来设置百分位统计的滚动窗口的持续时间,单位为毫秒。
@HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),
// 该属性用来设置百分位统计滚动窗口中使用 “ 桶 ”的数量。
@HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "60000"),
// 该属性用来设置在执行过程中每个 “桶” 中保留的最大执行次数。如果在滚动时间窗内发生超过该设定值的执行次数,
// 就从最初的位置开始重写。例如,将该值设置为100, 滚动窗口为10秒,若在10秒内一个 “桶 ”中发生了500次执行,
// 那么该 “桶” 中只保留 最后的100次执行的统计。另外,增加该值的大小将会增加内存量的消耗,并增加排序百分位数所需的计算时间。
@HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),
// 该属性用来设置采集影响断路器状态的健康快照(请求的成功、 错误百分比)的间隔等待时间。
@HystrixProperty(name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"),
// 是否开启请求缓存
@HystrixProperty(name = "requestCache.enabled", value = "true"),
// HystrixCommand的执行和事件是否打印日志到 HystrixRequestLog 中
@HystrixProperty(name = "requestLog.enabled", value = "true"),
},
threadPoolProperties = {
// 该参数用来设置执行命令线程池的核心线程数,该值也就是命令执行的最大并发量
@HystrixProperty(name = "coreSize", value = "10"),
// 该参数用来设置线程池的最大队列大小。当设置为 -1 时,线程池将使用 SynchronousQueue 实现的队列,
// 否则将使用 LinkedBlockingQueue 实现的队列。
@HystrixProperty(name = "maxQueueSize", value = "-1"),
// 该参数用来为队列设置拒绝阈值。 通过该参数, 即使队列没有达到最大值也能拒绝请求。
// 该参数主要是对 LinkedBlockingQueue 队列的补充,因为 LinkedBlockingQueue
// 队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了。
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "5"),
}
)
public String strConsumer() {
return "hello 2020";
}
public String str_fallbackMethod()
{
return "*****fall back str_fallbackMethod";
}
Hystrix工作流程
1 创建 HystrixCommand(用在依赖的服务返回单个操作结果的时候) 或 HystrixObserableCommand(用在依赖的服务返回多个操作结果的时候) 对象。
2 命令执行。其中 HystrixComand 实现了下面前两种执行方式;而 HystrixObservableCommand 实现了后两种执行方式:execute():同步执行,从依赖的服务返回一个单一的结果对象, 或是在发生错误的时候抛出异常。queue():异步执行, 直接返回 一个Future对象, 其中包含了服务执行结束时要返回的单一结果对象。observe():返回 Observable 对象,它代表了操作的多个结果,它是一个 Hot Obserable(不论 “事件源” 是否有 “订阅者”,都会在创建后对事件进行发布,所以对于 Hot Observable 的每一个 “订阅者” 都有可能是从 “事件源” 的中途开始的,并可能只是看到了整个操作的局部过程)。toObservable(): 同样会返回 Observable 对象,也代表了操作的多个结果,但它返回的是一个Cold Observable(没有 “订阅者” 的时候并不会发布事件,而是进行等待,直到有 “订阅者” 之后才发布事件,所以对于 Cold Observable 的订阅者,它可以保证从一开始看到整个操作的全部过程)。
3 若当前命令的请求缓存功能是被启用的, 并且该命令缓存命中, 那么缓存的结果会立即以 Observable 对象的形式 返回。
4 检查断路器是否为打开状态。如果断路器是打开的,那么Hystrix不会执行命令,而是转接到 fallback 处理逻辑(第 8 步);如果断路器是关闭的,检查是否有可用资源来执行命令(第 5 步)。
5 线程池/请求队列/信号量是否占满。如果命令依赖服务的专有线程池和请求队列,或者信号量(不使用线程池的时候)已经被占满, 那么 Hystrix 也不会执行命令, 而是转接到 fallback 处理逻辑(第8步)。
6 Hystrix 会根据我们编写的方法来决定采取什么样的方式去请求依赖服务。HystrixCommand.run() :返回一个单一的结果,或者抛出异常。HystrixObservableCommand.construct(): 返回一个Observable 对象来发射多个结果,或通过 onError 发送错误通知。
7 Hystrix会将 “成功”、”失败”、”拒绝”、”超时” 等信息报告给断路器, 而断路器会维护一组计数器来统计这些数据。断路器会使用这些统计数据来决定是否要将断路器打开,来对某个依赖服务的请求进行 “熔断/短路”。
8 当命令执行失败的时候, Hystrix 会进入 fallback 尝试回退处理, 我们通常也称该操作为 “服务降级”。而能够引起服务降级处理的情况有下面几种:第4步: 当前命令处于”熔断/短路”状态,断路器是打开的时候。第5步: 当前命令的线程池、 请求队列或 者信号量被占满的时候。第6步:HystrixObservableCommand.construct() 或 HystrixCommand.run() 抛出异常的时候。
9 当Hystrix命令执行成功之后, 它会将处理结果直接返回或是以Observable 的形式返回。
tips:如果我们没有为命令实现降级逻辑或者在降级处理逻辑中抛出了异常, Hystrix 依然会返回一个 Observable 对象, 但是它不会发射任何结果数据, 而是通过 onError 方法通知命令立即中断请求,并通过onError()方法将引起命令失败的异常发送给调用者。
服务监控hystrixDashboard
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。
Apache JMeter 使用
windows 下直接点击bin目录下ApacheJMeter.jar运行
Zuul 路由网关
概述简介 https://github.com/Netflix/zuul/wiki/Getting-Started
Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务。zuul是Netflix出品的一个基于JVM路由和服务端负载均衡器,
AIP网关为微服务架构中的服务提供同一的访问入口,客户端通过API网关访问相关服务,API网关的定义类似于设计模式中的门面模式,他相当于整个微服务架构中的门面,所有的客户端的访问都通过他进行路由以及过滤,他实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能
Zuul包含如下主要的功能
代理+路由+过滤三大功能
还可以实现 灰度发布
Zuul 已经进入维护阶段,仅做了解即可
GetWay
简介
Gateway 实在spring生态系统之上构建的API网关服务,基于spring5,springboot2和project Reactor等技术
GatWay旨在提供一种简单而有效的方式来对API进行路由,以及提供强大的过滤器功能,例如:熔断、限流、重试等。
SpringCloud Getway是sprigcloud 的一个全新项目,基于spring5.0+spring boot2.0和project Reactor等技术开发的网关,他旨在为微服务架构提供一种简单的同一的API路由管理方式。
springcloud GateWay作为springcloud生态系统中的网关,目标是替代zuul,在springcloud2.0以上的版本中,没有对新版本的zuul2.0以上最新高性能版本的集成,仍然还是使用zuul1.x非Reator模式老版本。而为了提供提升网关的性能,springcloud gateway是基于webFlux框架实现的,而Webflux框架的底层则使用了高性能的Reactor模式哦通信框架Netty。
spring Cloud Geteway的目标提供同一的右路方式且基于Filter链的方式提供了网关基本的功能,例如:安全、监控、指标和限流。
SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
主要作用
反向代理
鉴权
流量控制
熔断
日志监控
Spring Cloud Gateway 具有如下特性:
基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建;
动态路由:能够匹配任何请求属性;
可以对路由指定 Predicate(断言)和 Filter(过滤器);
集成Hystrix的断路器功能;
集成 Spring Cloud 服务发现功能;
易于编写的 Predicate(断言)和 Filter(过滤器);
请求限流功能;
支持路径重写。
Spring Cloud Gateway 与 Zuul的区别
在SpringCloud Finchley 正式版之前,Spring Cloud 推荐的网关是 Netflix 提供的Zuul:
1、Zuul 1.x,是一个基于阻塞 I/ O 的 API Gateway
2、Zuul 1.x 基于Servlet 2. 5使用阻塞架构它不支持任何长连接(如 WebSocket) Zuul 的设计模式和Nginx较像,每次 I/ O 操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx 用C++ 实现,Zuul 用 Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。
3、Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。 Zuul 2.x的性能较 Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试, Spring Cloud Gateway 的 RPS(每秒请求数)是Zuul 的 1. 6 倍。
4、Spring Cloud Gateway 建立 在 Spring Framework 5、 Project Reactor 和 Spring Boot 2 之上, 使用非阻塞 API。
5、Spring Cloud Gateway 还 支持 WebSocket, 并且与Spring紧密集成拥有更好的开发体验
Springcloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Servlet IO处理模型。
学过尚硅谷web中期课程都知道一个题目,Servlet的生命周期?servlet由servlet container进行生命周期管理。
container启动时构造servlet对象并调用servlet init()进行初始化;
container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service()。
container关闭时调用servlet destory()销毁servlet;
上述模式的缺点:
servlet是一个简单的网络IO模型,当请求进入servlet container时,servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发(比如抽风用jemeter压),线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势
所以Zuul 1.X是基于servlet之上的一个阻塞式处理模型,即spring实现了处理所有request请求的一个servlet(DispatcherServlet)并由该servlet阻塞式处理处理。所以Springcloud Zuul无法摆脱servlet模型的弊端
WebFlux
传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的。
但是
在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring5必须让你使用java8)
Spring WebFlux 是 Spring 5.0 引入的新的响应式框架,区别于 Spring MVC,它不需要依赖Servlet API,它是完全异步非阻塞的,并且基于 Reactor 来实现响应式流规范。
Geteway 核心概念
Rout路由
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
Predicate断言
参考的是Java8的java.util.function.Predicate
开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤)
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
predicate就是我们的匹配条件;
而filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了
Gateway工作流程
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。
Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,
在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。
Route Predicate Factories这个是什么东东?
spring cloud Geteway将路由匹配作为spring webFlux HandlerMapping 基础架构的一部分。
Spring CloudGeteway包括许多内置的Route Predicate工厂,所有这些Predicate都与HTTP请求的不同属性匹配,多个Route PreDicate 工厂可以进行组合
springCloud GeteWay 创建Route对象时,使用RoutePredicateFactory创建Predicate对象,Predicate对象可以赋值给Route。springCloudGateWay包括许多内置的RoutePredicateFactories
所有这些谓词都是匹配HTTP请求的不同属性,多种谓词工厂可以组合,并通过逻辑and。
GatewayFilter
路由过滤器可用于修改进入的HTTP请求和返回HTTP响应,路由过滤器只能指定路由进行使用
Spring Cloud GateWay 诶只多种路哟过滤器,他们都由GateWayFilter的工厂类来产生的。
git clone git://github.com/LiyYanHao/springcloud-config
git config —global url.”https://".insteadOf git://
git remote add origin git@gitee.com:lyhonline/lyhonline.git
Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。
Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,
它整合了Java的事件处理机制和消息中间件的功能。
Spring Clud Bus目前支持RabbitMQ和Kafka。
Bus支持两种消息代理:RabbitMQ 和 Kafka
什么是总线
在微服务架构的系统中,通过会使用轻量级的消息代理来构建一个公用的消息主题,并让系统中所有的微服务实例都连接上去,由于该主题中产生的消息会被所有实例监听和消费,所有成他为消息总线,在总线上的各个实例,都可以方便的地广播一些需要让其他了解在该主题上的实例都知道的消息
基本原理
ConfigClient实例都监听MQ中同一个topic 默认是springCloudbus 当一个服务刷新数据的时候,他会吧这个信息放入到Topic中,这样其他监听同一Topic的服务就能得到通知,然后去更新自身的配置。
springcloud Bus动态刷新全局广播
设计思想
- 利用消息总线触发一个客户端/bus/refresh而刷新所有的客户端配置
- 利用消息总线触发一个服务端ConfigServer的/bus/refresh断电,而刷新所有客户端的配置
- 图2的架构显然更佳适合,图一不是的原因如下
- 打破了微服务的职责单一性,因为微服务本身是业务模块,他本不应该承担配置刷新的职责
- 他破坏了微服务各个节点的对等性
- 有一定的局限性,例如 微服务在迁移是,他的网络地址尝尝会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改
什么是SpringCloudStream
官方定义springcloudstream是一个构建消息驱动微服务的框架
应用程序通过in puts或者out puts来与spring cloud stream中builder对象交互
通过我们配置来bingding绑定,而spring cloud stream的builder对象负责与消息中间件交互
所以,我们只需要搞清楚如何与springcloud stream 交互就可以方便使用消息驱动的方式
通过使用spring integration 来连接消息代理中间件以实现消息事件驱动,
spring cloud stram 为一些供应商的消息中间件产品提供了个性化的自动配置实现,引用了发布-订阅、消费组、分区的三个概念
目前仅支持RabbitMQ 、KafKa
springcloud stram 是用于构建与共享消息传递系统的高度可伸缩的时间驱动微服务矿建,该框架提供了一个灵活的变成模型,他建立在已经建立和属性的spring熟语和最佳时间上,包括支持持久化的发布、订阅、消费以及消息分区的三个概念。
消息重复消费问题
比如在如下场景中,订单系统我们做集群部署,都会从RabbitMQ中获取订单信息,那如果一个订单同时被两个服务获取到,那么久会造成数据错误,我们得避免造成这种情况,这时我们就可以使用stream中的消息分组来解决。
注意在stream中处于同一个group中的多个消费者是竞争关系,就能保证消息只会被其中一个应用消费一次,
不同组的是可以全面消费重复消费
同一组内会发生竞争关系,只有其中一个可以消费
SpringCloud Sleuth分布式请求链路跟踪
zipkin启动
nohup java -jar zipkin-server-2.16.0-exec.jar &
查看日志
tail -f nohup.out
启动后需要先进行一次请求才会被监控到。
根据端口号找线程
netstat -nlp | grep 9411