欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

dubbo路由过滤

时间:2023-06-20

dubbo 路由过滤

          

官网:https://dubbo.apache.org/zh/docs/advanced/routing-rule/

                 

              

                                   

路由过滤

           

路由过滤:消费端调用服务时,根据自定义规则过滤服务调用列表

              

              

消费端服务调用流程

消费端应用启动时,创建clusterInvoker对象(默认为failoverClusterInvoker) # 消费端发起服务调用时,依次执行如下过程:获取所有可用invoker列表(directory#list) * dynamicDirectory:动态invoker列表,从注册中心获取 * staticDirectory:静态invoker列表,创建staticDirectory对象时传入的invoker列表对所有可用列表进行路由过滤(routerChain#route)使用负载均衡算法(loadbalance#select)在路由过滤后的invoker列表选择一个invoker,发起远程服务调用; # 服务调用结果处理如果调用正常,消费端收到服务端返回的结果(如果有结果返回);如果调用异常,执行容错策略:重试(failover,默认)、忽略异常(failsafe)等;如果设置了mock,服务调用异常时,可进行服务降级;

                

路由分类

条件路由:使用dubbo定义的语法规则在dubbo-admin中写路由规则;文件路由:将路由规则写在文件中,读取文件提取路由规则;脚本路由:使用jdk支持的引擎解析路由脚本,默认使用javascript引擎标签路由:给服务(provider)打标签,后续如果consumer调用时携带标签, 标签如果匹配则优先调用,如果不匹配则调用不携带标签的provider服务

            

StateRouteFactory

@SPIpublic interface StateRouterFactory { @Adaptive("protocol") StateRouter getRouter(Class interfaceClass, URL url);}

              

                 

***********

条件路由

        

应用粒度条件路由

# app1的消费者只能消费所有端口为20880的服务实例# app2的消费者只能消费所有端口为20881的服务实例---scope: applicationforce: trueruntime: trueenabled: truekey: governance-conditionrouter-consumerconditions: - application=app1 => address=*:20880 - application=app2 => address=*:20881

            

接口粒度条件路由

# 服务粒度示例# DemoService的sayHello方法只能消费所有端口为20880的服务实例# DemoService的sayHi方法只能消费所有端口为20881的服务实例---scope: serviceforce: trueruntime: trueenabled: truekey: org.apache.dubbo.samples.governance.api.DemoServiceconditions: - method=sayHello => address=*:20880 - method=sayHi => address=*:20881

               

参数说明

scope:application(应用粒度)、service(服务粒度)force:路由结果为空时,是否强制执行,默认false true:强制执行,路由结果为空,则返回空结果 false:路由结果为空时,返回所有服务列表runtime:是否在每次调用时执行路由规则,默认false true:每次调用时执行路由规则,如果使用参数路由,必须设置为true false:只有在服务者列表更新后执行路由规则,如果没有更新,使用缓存的列表enabled:是否启用路由规则,默认truepriority:路由规则优先级,值越大越靠前执行,默认为0key:路由规则作用的应用名(scope为application)、服务名(scope为service) scope为application时,key:应用名 scope为service时,key:[{group}]{service}[{version}],group、version可缺省conditions:路由条件规则设置(whenRule => thenRule)

            

conditions 路由规则:whenRule ==> thenRule

whenRule:消费者匹配条件,消费者满足匹配条件时,执行后面的过滤规则thenRule:服务提供者匹配条件,返回满足匹配条件的服务者列表whenRule为空,表示对所有消费者都应用后面的匹配规则(thenRule),如:=> host != 10.20.153.11thenRule为空,表示禁止访问,如:host = 10.20.153.10 => whenRule、thenRule格式:key = value、key != valuekey为服务调用信息(method、argument等)暂不支持参数路由、 url本身字段(protocol, host, port 等)、 url上的所有参数,如:application, organization value可包含特殊字符:*(通配符),如host != 10.20.* ,(分隔符),如host != 10.20.153.10,10.20.153.11 $(引用消费者参数),如host = $host # 路由规则示例=> host != 172.22.3.91:所有消费者均不调用172.22.3.91上的服务register.ip != 10.20.153.10,10.20.153.11 =>:注册地址不在指定地址的服务不得调用任何服务application != kylin => host != 172.22.3.95,172.22.3.96:应用名不为指定名称的不得调用不为指定host的服务

                   

***********

标签路由

        

动态标签:dubbo admin中设置

# 动态标签,动态标签优先级更高,同时包含动态标签、静态标签,以动态标签为准# governance-tagrouter-provider应用增加了两个标签分组tag1和tag2# tag1包含一个实例 127.0.0.1:20880# tag2包含一个实例 127.0.0.1:20881--- force: false runtime: true enabled: true key: governance-tagrouter-provider tags: #可以给应用(该应用下用多个服务实例)打多个标签 - name: tag1 #name标签名称,addresses表示数组中的实例都打上该标签 addresses: ["127.0.0.1:20880"] #地址为127.0.0.1:20880的实例打标签tag1 - name: tag2 addresses: ["127.0.0.1:20881"] #地址为127.0.0.1:20881的实例打标签tag2

            

静态标签:服务端注册服务时设置

java -jar xxx-provider.jar -Ddubbo.provider.tag={tag1}

            

消费端标签过滤:调用时在上下文中设置标签

# 消费端调用标签tag1的服务RpcContext.getContext().setAttachment(Constants.REQUEST_TAG_KEY,"tag1"); # 消费端标签路由规则如果消费端携带标签tag,则优先调用含有同一标签的服务提供者;如果没有同一标签的服务提供者,默认访问tag为null的服务提供者;设置参数request.tag.force=true,当不存在同一tag的服务提供者,则抛出异常; 消费端如果不携带参数,则只会调用tag=null的服务提供者

                  

***********

文件路由

        

FileStateRouterFactory

public class FileStateRouterFactory implements StateRouterFactory { public static final String NAME = "file"; private StateRouterFactory routerFactory; public void setRouterFactory(StateRouterFactory routerFactory) { this.routerFactory = routerFactory; } @Override public StateRouter getRouter(Class interfaceClass, URL url) { try { // Transform File URL into script Route URL, and Load // file:///d:/path/to/route.js?router=script ==> script:///d:/path/to/route.js?type=js&rule= //将文件url转换为scripr路由url,并且加载文件内容附加在url中,如 //file:///d:/path/to/route.js?router=script //转换为script:///d:/path/to/route.js?type=js&rule= String protocol = url.getParameter(ROUTER_KEY, scriptStateRouterFactory.NAME); // Replace original protocol (maybe 'file') with 'script' String type = null; // Use file suffix to config script type, e.g., js, groovy ... String path = url.getPath(); if (path != null) { int i = path.lastIndexOf('.'); if (i > 0) { type = path.substring(i + 1); } } String rule = IOUtils.read(new FileReader(new File(url.getAbsolutePath()))); // FIXME: this code looks useless boolean runtime = url.getParameter(RUNTIME_KEY, false); URL script = URLBuilder.from(url) .setProtocol(protocol) .addParameter(TYPE_KEY, type) .addParameter(RUNTIME_KEY, runtime) .addParameterAndEncoded(RULE_KEY, rule) .build(); return routerFactory.getRouter(interfaceClass, script); } catch (IOException e) { throw new IllegalStateException(e.getMessage(), e); } } }

               

***********

脚本路由

     

scriptStateRouterFactory

public class scriptStateRouterFactory implements StateRouterFactory { public static final String NAME = "script"; @Override public StateRouter getRouter(Class interfaceClass, URL url) { return new scriptStateRouter<>(url); } }

                

                

                                   

消费端标签过滤

       

@DubboReference:消费端服务调用注解

@documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})public @interface DubboReference { Class<?> interfaceClass() default void.class; String interfaceName() default ""; String group() default ""; //服务分组 String version() default ""; //服务版本 String url() default ""; //直连服务提供端(如果配置了,则不使用注册中心) String client() default ""; //客户端传输方式,默认为netty @Deprecated boolean generic() default false; //已禁用 @Deprecated boolean injvm() default true; //已禁用 boolean check() default true; boolean init() default true; boolean lazy() default false; boolean stubevent() default false; String reconnect() default ""; boolean sticky() default false; String proxy() default ""; String stub() default ""; String cluster() default ClusterRules.EMPTY; int connections() default -1; int callbacks() default -1; String onconnect() default ""; String ondisconnect() default ""; String owner() default ""; String layer() default ""; int retries() default -1; String loadbalance() default LoadbalanceRules.EMPTY; boolean async() default false; int actives() default -1; boolean sent() default false; String mock() default ""; String validation() default ""; int timeout() default -1; String cache() default ""; String[] filter() default {}; String[] listener() default {}; String[] parameters() default {}; @Deprecated String application() default ""; String module() default ""; String consumer() default ""; String monitor() default ""; String[] registry() default {}; String protocol() default ""; String tag() default ""; //标签设置 String merger() default ""; Method[] methods() default {}; String id() default ""; @Deprecated String[] services() default {}; String[] providedBy() default {}; String scope() default ""; boolean referAsync() default false;}

              

HelloController

@RestControllerpublic class HelloController { @DubboReference(tag = "tag1") //调用含有标签tag1的服务 private HelloService helloService; @RequestMapping("/hello") public String hello(){ helloService.hello().forEach(System.out::print); return "hello consumer 2"; }}

             

                 

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。