各组件的实现原理:
zuul网关:
所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能
网关的作用: 统一入口;减少客户端与服务端的耦合;权限校验,请求转发、监控、负载均衡、缓存、静态响应处理,如果服务出现异常,可以返回默认值,或直接抛出异常,或取缓存值;Zuul网关的限流保护
优点:可以为客户端定制api,根据api调用多个微服务,返回请求值。
使用
@EnableZuulProxy开启网关
Zuul网关过滤器
前置过滤器:在请求进入zuul后,立即执行的过滤逻辑
路由后过滤:请求进入zuul后,并zuul执行了请求路由后,执行的过滤逻辑
后置过滤:远程服务调用后,执行的过滤逻辑
异常过滤:任意一个过滤失败,远程调用失败,调用超时后,执行的过滤
zuul的父类提供的抽象方法
filterType:方法返回字符串数据,代表当前过滤器的类型。可选值有-pre, route, post, error。
filterOrder:返回int数据 执行的权限
shouldFilter:返回boolean数据,代表当前filter是否生效。
run:具体的过滤执行逻辑
执行流程
Zuul网关的容错
Zuul中的服务降级处理
网关的实现原理:
ribbon(轮询)+hytrx(熔断)+filter(过滤器)
zuul2.0: 使用netty server作为网关监听服务器监听客户端发来的请求,然后把请求转发到前置过滤器(inbound filters)进行处理,处理完毕后在把请求使用netty client代理到具体的后端服务器进行处理,处理完毕后在把结果交给后者过滤器(outbound filters)进行处理,然后把处理结果通过nettyServer写回客户端。
Hystrix
Hystrix容错
资源隔离
Hystrix设计目标:
1、对来自依赖的延迟和故障进行保护
2、防止故障的连锁反应
3、快速失败,尽快恢复
4、回退并优雅降级
5、提供近实时的监控与告警
设计的原则:
1、防止单独的依赖耗尽资源
2、过载立即切断,防止失败
3、尽可能提供回退以保护用户免受故障
4、使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
5、通过近实时的指标,监控和确保故障被即使发现
6、近实时地监控指标和配置的修改。
Hystrix处理流程
Hystrix整个工作流如下:
1、封装好请求
2、根据条件有以下4种执行方式:
a、判断是否使用缓存响应请求,如果是,开启,直接响应缓存
b、判断熔断器是否打开,如果打开,走Fallback备用逻辑
c、判断线程池/队列/信号量是否已满,已满则走Fallback备用逻辑
d.调用依赖服务,如果执行失败或者超时,走Fallback备用逻辑,否则返回请求响应
3、统计熔断器监控指标;返回请求响应
Hystrix容错:
Hystrix的容错主要是通过添加容许延迟和容错方法,帮助控制这些分布式服务之间的交互。 还通过隔离服务之间的访问点,阻止它们之间的级联故障
资源隔离
线程隔离-线程池
通过将发送请求线程与执行请求的线程分离,可有效防止发生级联故障。当线程池或请求队列饱和时,Hystrix将拒绝服务,使得请求线程可以快速失败,从而避免依赖问题扩散。
线程池模式下,当超过指定时间未响应的服务,Hystrix会通过响应中断的方式通知线程立即结束并返回。
线程隔离的接收线程和请求线程是分开的,每个服务一个线程池,这样的缺点就是计算开销大,需要排队,调度,上下文切换;
线程隔离-信号量
当依赖延迟极低的服务时,线程池隔离技术引入的开销超过了它所带来的好处。这时候可以使用信号量隔离技术来代替,通过设置信号量来限制对任何给定依赖的并发调用量
由于Hystrix默认使用线程池做线程隔离
但是信号量不支持异步,也不支持超时,也就是说当所请求的服务不可用时,信号量会控制超过限制的请求立即返回,但是已经持有信号量的线程只能等待服务响应或从超时中返回,即可能出现长时间等待
熔断器简介
第一步,调用allowRequest()判断是否允许将请求提交到线程池
如果熔断器强制打开,circuitBreaker.forceOpen为true,不允许放行,返回。 如果熔断器强制关闭,circuitBreaker.forceClosed为true,允许放行。此外不必关注熔断器实际状态,也就是说熔断器仍然会维护统计数据和开关状态,只是不生效而已。 第二步,调用isOpen()判断熔断器开关是否打开
如果熔断器开关打开,进入第三步,否则继续; 如果一个周期内总的请求数小于circuitBreaker.requestVolumeThreshold的值,允许请求放行,否则继续; 如果一个周期内错误率小于circuitBreaker.errorThresholdPercentage的值,允许请求放行。否则,打开熔断器开关,进入第三步。 第三步,调用allowSingleTest()判断是否允许单个请求通行,检查依赖服务是否恢复
如果熔断器打开,且距离熔断器打开的时间或上一次试探请求放行的时间超过circuitBreaker.sleepWindowInMilliseconds的值时,熔断器器进入半开状态,允许放行一个试探请求;否则,不允许放行。
回退降级
降级,通常指务高峰期,为了保证核心服务正常运行,需要停掉一些不太重要的业务,或者某些服务不可用时,执行备用逻辑从故障服务中快速失败或快速返回,以保障主体业务不受影响。Hystrix提供的降级主要是为了容错,保证当前服务不受依赖服务故障的影响,从而提高服务的健壮性。要支持回退或降级处理
Hystrix在以下几种情况下会走降级逻辑:
执行construct()或run()抛出异常 熔断器打开导致命令短路 命令的线程池和队列或信号量的容量超额,命令被拒绝 命令执行超时
降级回退方式
Fail Fast 快速失败
快速失败是最普通的命令执行方法,命令没有重写降级逻辑。 如果命令执行发生任何类型的故障,它将直接抛出异常。
Fail Silent 无声失败
指在降级方法中通过返回null,空Map,空List或其他类似的响应来完成。
Fallback: Static
指在降级方法中返回静态默认值。 这不会导致服务以“无声失败”的方式被删除,而是导致默认行为发生。如:应用根据命令执行返回true / false执行相应逻辑,但命令执行失败,则默认为true
Fallback: Stubbed
当命令返回一个包含多个字段的复合对象时,适合以Stubbed 的方式回退。
Fallback: Cache via Network
有时,如果调用依赖服务失败,可以从缓存服务(如redis)中查询旧数据版本。由于又会发起远程调用,所以建议重新封装一个Command,使用不同的ThreadPoolKey,与主线程池进行隔离。
feign的执行流程
1、基于面向接口的动态代理生成实现类(动态创建实例,会根据注解的不同,解析不同的处理器methodhandler)
2、基于requestbean,动态生成request(根据传入的Bean对象和注解信息,从中提取出相应的值,来构造Http Request 对象)
3、使用encoder将bean生成http报文正文
Feign 最终会将请求转换成Http 消息发送出去,传入的请求对象最终会解析成消息体,如下所示:
4、拦截器负责对请求和返回处理
拦截器负责对请求和返回进行装饰处理 在请求转换的过程中,Feign 抽象出来了拦截器接口,用于用户自定义对请求的操作,比如,如果希望Http消息传递过程中被压缩,可以定义一个请求拦截器。
5、发送http请求
Feign 内置了一个重试器,当HTTP请求出现IO异常时,Feign会有一个最大尝试次数发送请求
Feign 真正发送HTTP请求是委托给 feign.Client 来做的。
Feign 默认底层通过JDK 的 java.net.HttpURLConnection 实现了feign.Client接口类,在每次发送请求的时候,都会创建新的HttpURLConnection 链接,这也就是为什么默认情况下Feign的性能很差的原因。可以通过拓展该接口,使用Apache HttpClient 或者OkHttp3等基于连接池的高性能Http客户端。
Feign 整体框架非常小巧,在处理请求转换和消息解析的过程中,基本上没什么时间消耗。真正影响性能的,是处理Http请求的环节。
HttpURLConnection是JDK自带的HTTP客户端技术,并不支持连接池,如果要实现连接池的机制,还需要自己来管理连接对象。对于网络请求这种底层相对复杂的操作,如果有可用的其他方案,也没有必要自己去管理连接对象。 Apache提供的HttpClient框架相比传统JDK自带的HttpURLConnection,它封装了访问http的请求头,参数,内容体,响应等等;它不仅使客户端发送HTTP请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性;另外高并发大量的请求网络的时候,还是用“HTTP连接池”提升吞吐量。 OKHttp是一个处理网络请求的开源项目,是安卓端最火热的轻量级框架。OKHttp拥有共享Socket,减少对服务器的请求次数,通过连接池,减少了请求延迟等技术特点。
优化:
1、使用Gzip压缩发送的数据
2、替换为httpclient客户端(使用http连接池提供性能)
Eureka简介:
ribbon
SpringCloud Config
feign 和 openfeign
Eureka的使用:
服务端搭建:
1.maven导入(其他几个是必要的包)
2.yml文件配置(单机版)
图片说明:
port:访问的端口
hostname:实例名称
主启动类配置:
客户端搭建:
maven导入:
yml文件编辑
客户端1(消费者)
客户端2(提供者)
主启动类配置
集群搭建:
maven不变;
yml各服务互相访问;
客户端的yml,每个节点都访问
在resttemplate 的类中,配置@loadBalanced
resttemplate使用的url换成生产者在eureka上显示的名称,也就是yml上配置的实例名
配置客户端在erueka上显示的别名
服务发现的配置(为了用户可以通过访问生产者,可以看到生产者都有哪些服务可以被调用)
CAP理论
zookeeper和consul
ribbon:提供客户端的软件负载均衡算法和服务调用
ribbon本地负载均衡,在调用服务接口的时候,会在注册中心获取注册的信息,缓存在本地的jvm,从而在本地实现rpc远程调用。
可以通过resttemplate或者Feign,openFeign访问。
ribbon的使用,在客户端的resttemplate配置中加上注解(不用导maven,因为在eureka中已经包含ribbon的包)
没有ribbon的时候,客户端消费者是直接向生产者发请求,有ribbon后,消费者通过ribbon,让ribbon向生产者发送请求
ribbon存在的负载均衡策略:
配置个性化的负载均衡策略:
服务降级
hystrx的服务熔断,降级和限流 降级:返回有友好的提示:使用场景:超时,程序异常,服务熔断导致降级,线程池,信号量打满 熔断,拒绝访问,返回友好提示 限流:限制访问数数量 熔断器在消费端和服务端都可以使用,一般是用在消费端