欢迎访问我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
本篇概览
本文是《Spring Cloud Gateway实战》系列的第七篇,前面的文章咱们学习了各种内置过滤器,还在《Spring Cloud Gateway的断路器(CircuitBreaker)功能》一文深入研究了断路器类型的过滤器(理论&实战&源码分析皆有),相信聪明的您一定会有此疑问:内置的再多也无法覆盖全部场景,定制才是终极武器
所以今天咱们就来开发一个自己专属的过滤器,至于此过滤器的具体功能,其实前文已埋下伏笔,如下图:
简单来说,就是在一个有断路器的Spring Cloud Gateway应用中做个自定义过滤器,在处理每个请求时把断路器的状态打印出来,这样咱们就能明明白白清清楚楚知道断路器的状态啥时候改变,变成了啥样,也算补全了《Spring Cloud Gateway的断路器(CircuitBreaker)功能》的知识点
过滤器分为全局和局部两种,这里咱们选用局部的,原因很简单:咱们的过滤器是为了观察断路器,所以不需要全局生效,只要在使用断路器的路由中生效就够了;
套路提前知晓咱们先看看自定义局部过滤器的的基本套路:
新建一个类(我这里名为StatePrinterGatewayFilter.java),实现GatewayFilter和Ordered接口,重点是filter方法,该过滤器的主要功能就在这里面实现
新建一个类(我这里名为StatePrinterGatewayFilterFactory.java),实现AbstractGatewayFilterFactory方法,其apply方法的返回值就是上一步新建的StatePrinterGatewayFilter的实例,该方法的入参是在路由配置中过滤器节点下面的配置,这样就可以根据配置做一些特殊的处理,然后再创建实例作为返回值
StatePrinterGatewayFilterFactory类实现String name()方法,该方法的返回值就是路由配置文件中过滤器的name
String name()也可以不实现,这是因为定义该方法的接口中有默认实现了,如下图,这样您在路由配置文件中过滤器的name只能是StatePrinter:
在配置文件中,添加您自定义的过滤器,该操作和之前的添加内置过滤器一模一样
以上就是自定义过滤器的基本套路了,可见还是非常简单的,接下来的实战也是按照这个套路来的
在编写自定义过滤器代码之前,还有个拦路虎等着我们,也就是咱们过滤器的基本功能:如何取得断路器的状态
如何取得断路器的状态前文的代码分析中,咱们了解到断路器的核心功能集中在SpringCloudCircuitBreakerFilterFactory.apply方法中(没错,就是刚才提到的apply方法),打开这个类,如下图,从绿框可见断路器功能来自名为cb的对象,而这个对象是在红框处由reactiveCircuitBreakerFactory创建的:
展开上图红框右侧的reactiveCircuitBreakerFactory.create方法继续看,最终跟踪到了ReactiveResilience4JCircuitBreakerFactory类,发现了一个极其重要的变量,就是下图红框中的circuitBreakerRegistry,它的内部有个ConcurrentHashMap(InMemoryRegistryStore的entryMap),这里面存放了所有断路器实例:
此时您应该想到了,拿到断路器的关键就是拿到上图红框中的circuitBreakerRegistry对象,不过怎么拿呢?首先它是私有类型的,其次虽然有个方法返回了该对象,但是此方法并非public的,如下图红框:
这个问题当然难不倒聪明的您了,没错,用反射修改此方法的访问权限,稍后的代码中咱们就这么干
还剩最后一个问题:circuitBreakerRegistry是ReactiveResilience4JCircuitBreakerFactory的成员变量,这个ReactiveResilience4JCircuitBreakerFactory从哪获取?