1.GateWay
GateWay⽬标是取代Netflflix Zuul,它基于Spring5.0+SpringBoot2.0+WebFlux等技术开发,提供统⼀的路由⽅式(反向代理)并且基于 Filter(定义过滤器对请求过滤,完成⼀些功能) 链的⽅式提供了⽹关基本的功能,例如:鉴权、流量控制、熔断、路径重写、⽇志监控。
●组成:
✮路由route: ⽹关最基础的⼯作单元。路由由⼀个ID、⼀个⽬标URL、⼀系列的断⾔(匹配条件判断)和Filter过滤器组成。如果断⾔为true,则匹配该路由。
✮断⾔predicates:参考了Java8中的断⾔Predicate,匹配Http请求中的所有内容(类似于nginx中的location匹配⼀样),如果断⾔与请求相匹配则路由。
✮过滤器filter:标准的Spring webFilter,使⽤过滤器在请求之前或者之后执⾏业务逻辑。
✮请求前pre类型过滤器:做参数校验、权限校验、流量监控、⽇志输出、协议转换等,
✮请求前post类型的过滤器:做响应内容、响应头的修改、⽇志的输出、流量监控等。
GateWayFilter 应⽤到单个路由路由上 、GlobalFilter 应⽤到所有的路由上
2.Eureka/Zookeeper
服务注册中⼼本质上是为了解耦服务提供者和服务消费者,为了⽀持弹性扩缩容特性,⼀个微服务的提供者的数量和分布往往是动态变化的。
Eureka通过⼼跳检测、健康检查和客户端缓存等机制,提⾼系统的灵活性、可伸缩性和可⽤性。
①us-east-1c、us-east-1d,us-east-1e代表不同的机房,每⼀个Eureka Server都是⼀个集群。
②Service作为服务提供者向Eureka中注册服务,Eureka接受到注册事件会在集群和分区中进⾏数据同步,Client作为消费端(服务消费者)可以从Eureka中获取到服务注册信息,进⾏服务调⽤。
③微服务启动后,会周期性地向Eureka发送⼼跳(默认周期为30秒)以续约⾃⼰的信息
④Eureka在⼀定时间内(默认90秒)没有接收到某个微服务节点的⼼跳,Eureka将会注销该微服务节点
⑤Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉,服务消费者依然可以使⽤缓存中的信息找到服务提供者
●Eureka缓存
新服务上线后,服务消费者不能立即访问到刚上线的新服务,需要过⼀段时间后才能访问?或是将服务下线后,服务还是会被调⽤到,⼀段时候后才彻底停⽌服务,访问前期会导致频繁报错
服务注册到注册中⼼后,服务实例信息是存储在Registry表中的,也就是内存中。但Eureka为了提⾼响应速度,在内部做了优化,加⼊了两层的缓存结构,将Client需要的实例信息,直接缓存起来,获取的时候直接从缓存中拿数据然后响应给 Client。
●第⼀层缓存是readOnlyCacheMap,采⽤ConcurrentHashMap来存储数据的,主要负责定时与readWriteCacheMap进⾏数据同步,默认同步时间为 30 秒⼀次。
●第⼆层缓存是readWriteCacheMap,采⽤Guava来实现缓存。缓存过期时间默认为180秒,当服务下线、过期、注册、状态变更等操作都会清除此缓存中的数据。
●如果两级缓存都无法查询,会触发缓存的加载,从存储层拉取数据到缓存中,然后再返回给 Client。
Eureka之所以设计⼆级缓存机制,也是为了提⾼ Eureka Server 的响应速度,缺点是缓存会导致 Client获取不到最新的服务实例信息,然后导致⽆法快速发现新的服务和已下线的服务。
●解决方案
✮我们可以缩短读缓存的更新时间让服务发现变得更加及时,或者直接将只读缓存关闭,同时可以缩短客户端如ribbon服务的定时刷新间隔,多级缓存也导致C层⾯(数据⼀致性)很薄弱。
✮Eureka Server 中会有定时任务去检测失效的服务,将服务实例信息从注册表中移除,也可以将这个失效检测的时间缩短,这样服务下线后就能够及时从注册表中清除。
●自我保护机制开启条件
✮期望最小每分钟能够续租的次数(实例* 频率 * 比例==10* 2 *0.85)
✮期望的服务实例数量(10)
●健康检查
✮Eureka Client 会定时发送心跳给 Eureka Server 来证明自己处于健康的状态
✮集成SBA以后可以把所有健康状态信息一并返回给eureka
3.Feign / Ribbon
●Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡,
●Feign 可以与 Hystrix 组合使用,支持熔断回退
●Feign 可以与ProtoBuf实现快速的RPC调用
●InvocationHandlerFactory 代理
采用 JDK 的动态代理方式生成代理对象,当我们调用这个接口,实际上是要去调用远程的 HTTP API
●Contract 契约组件
比如请求类型是 GET 还是 POST,请求的 URI 是什么
●Encoder 编码组件 \ Decoder 解码组件
通过该组件我们可以将请求信息采用指定的编码方式进行编解码后传输
●Logger 日志记录
负责 Feign 中记录日志的,可以指定 Logger 的级别以及自定义日志的输出
●Client 请求执行组件
负责 HTTP 请求执行的组件,Feign 中默认的 Client 是通过 JDK 的 HttpURLConnection 来发起请求的,在每次发送请求的时候,都会创建新的 HttpURLConnection 链接,Feign 的性能会很差,可以通过扩展该接口,使用 Apache HttpClient 等基于连接池的高性能 HTTP 客户端。
●Retryer 重试组件
负责重试的组件,Feign 内置了重试器,当 HTTP 请求出现 IO 异常时,Feign 会限定一个最大重试次数来进行重试操作。
●RequestInterceptor 请求拦截器
可以为 Feign 添加多个拦截器,在请求执行前设置一些扩展的参数信息。
4.Feign最佳使用技巧
●继承特性
●拦截器
比如添加指定的请求头信息,这个可以用在服务间传递某些信息的时候。
●GET 请求多参数传递
●日志配置
FULL 会输出全部完整的请求信息。
●异常解码器
异常解码器中可以获取异常信息,而不是简单的一个code,然后转换成对应的异常对象返回。
●源码查看是如何继承Hystrix
HystrixFeign.builder 中可以看到继承了 Feign 的 Builder,增加了 Hystrix的SetterFactory, build 方法里,对 invocationHandlerFactory 进行了重写, create 的时候返回HystrixInvocationHandler, 在 invoke 的时候会将请求包装成 HystrixCommand 去执行,这里就自然的集成了 Hystrix
5.Ribbon
使用方式
●原生 API,Ribbon 是 Netflix 开源的,没有使用 Spring Cloud,需要使用 Ribbon 的原生 API。
●Ribbon + RestTemplate,整合Spring Cloud 后,可以基于 RestTemplate 提供负载均衡的服务
●Ribbon + Feign
★负载均衡算法
①RoundRobinRule 是轮询的算法,A和B轮流选择。
②RandomRule 是随机算法,这个就比较简单了,在服务列表中随机选取。
③BestAvailableRule 选择一个最小的并发请求 server
★自定义负载均衡算法
①实现 Irule 接口
②继承 AbstractLoadBalancerRule 类
★自定义负载均衡使用场景(核心)
①灰度发布
灰度发布是能够平滑过渡的一种发布方式,在发布过程中,先发布一部分应用,让指定的用户使用刚发布的应用,等到测试没有问题后,再将其他的全部应用发布。如果新发布的有问题,只需要将这部分恢复即可,不用恢复所有的应用。
②多版本隔离
多版本隔离跟灰度发布类似,为了兼容或者过度,某些应用会有多个版本,这个时候如何保证 1.0 版本的客户端不会调用到 1.1 版本的服务,就是我们需要考虑的问题。
③故障隔离
当线上某个实例发生故障后,为了不影响用户,我们一般都会先留存证据,比如:线程信息、JVM 信息等,然后将这个实例重启或直接停止。然后线下根据一些信息分析故障原因,如果我能做到故障隔离,就可以直接将出问题的实例隔离,不让正常的用户请求访问到这个出问题的实例,只让指定的用户访问,这样就可以单独用特定的用户来对这个出问题的实例进行测试、故障分析等。