gateway
的负载均衡以及feign
服务之间的调用或者RestTemplate
请求,都可以使用自定义IRule
规则进行路由转发。
自定义IRule
-
固定
IRule
:将IRule
的一个实现类注入到spring容器中@Configuration public class MyIRuleConfig { @Bean public IRule myIRule() { return new RandomRule(); } }
注意: 这个自定义配置类不能放在
@ComponentScan
所扫描的当前包及其子包下 -
固定
IRule
: 使用注解@RibbonClient
;// configuration 属性可以包含构成客户端的部分的重写@Bean定义,例如ILoadBalancer、ServerListFilter、IRule。 @RibbonClient(name = "test-client", configuration = RandomRule.class)
-
可以动态调整的
IRule
:需要继承ribbon
的SpringClientFactory
类并且创建bean对象,里面要重写getLoadBalancer
,给ILoadBalancer
设置自定义的IRule
路由规则。@Slf4j public class MySpringClientFactory extends SpringClientFactory { @Override public ILoadBalancer getLoadBalancer(String name) { ILoadBalancer instance = this.getInstance(name, ILoadBalancer.class); if (instance instanceof DynamicServerListLoadBalancer) { DynamicServerListLoadBalancer dsbl = (DynamicServerListLoadBalancer) instance; try { // 伪代码,这里实际应该使用你自己定义的 IRule,同时,这里可以进行动态调整,因为每一次进行请求时,rabbon都会调用这个 getLoadBalancer()方法。 IRule iRule = new RandomRule(); dsbl.setRule(iRule); return dsbl; } catch (Exception e) { logger.error("ribbon获取负载均衡器实例异常", e); } } return instance; } }
动态设置IRule
原理:
-
gateway
路由转发:本质上,还是使用请求过滤器,gateway用的是
LoadBalancerClientFilter
,在这里的filter方法,会在获取ServiceInstance
时调用RibbonLoadBalancerClient
的choose方法选择一个服务,在choose
方法中,调用了getServer()
,getServer()
调用getLoadBalancer()
,使用SpringClientFactory
bean对象获取ILoadBalancer,所以我们要继承ribbon的SpringClientFactory
类并且创建bean对象,子类里面要重写getLoadBalancer
,给ILoadBalancer
设置自定义的IRule
路由规则,这样就能自定义路由转发;
-
openfeign
:会调用LoadBalancerFeignClient.lbClient()创建FeignLoadBalancer对象,这里调用CachingSpringLoadBalancerFactory.create(),先去类的本地缓存map变量cache中获取,FeignLoadBalancer没有就创建,创建时会加载ILoadBalancer,ILoadBalancer由
SpringClientFactory
的getLoadBalancer获取(所以重写getLoadBalancer()方法,能设置ILoadBalancer的权重规则IRule),最后还是构造HttpURLConnection来发送http请求。
-
RestTemplate
调用:增加
@LoadBalanced
注解之后,就会在restTemplate
里面 通过restTemplate.setInterceptors
放入给RestTemplate 增加LoadBalancerInterceptor
拦截器,在拦截器中使用LoadBalancerClient
的实现类RibbonLoadBalancerClient.execute()
方法进行负载均衡调用。所以这里也是继承ribbon的SpringClientFactory
类并且创建bean对象,里面要重写getLoadBalancer
,给ILoadBalancer
设置自定义的IRule
路由规则。