栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

dubbo 路由过滤

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

dubbo 路由过滤


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

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

              

                 

***********

条件路由

        

应用粒度条件路由

# app1的消费者只能消费所有端口为20880的服务实例
# app2的消费者只能消费所有端口为20881的服务实例
---
scope: application
force: true
runtime: true
enabled: true
key: governance-conditionrouter-consumer
conditions:
  - application=app1 => address=*:20880
  - application=app2 => address=*:20881

            

接口粒度条件路由

# 服务粒度示例
# DemoService的sayHello方法只能消费所有端口为20880的服务实例
# DemoService的sayHi方法只能消费所有端口为20881的服务实例
---
scope: service
force: true
runtime: true
enabled: true
key: org.apache.dubbo.samples.governance.api.DemoService
conditions:
  - method=sayHello => address=*:20880
  - method=sayHi => address=*:20881

               

参数说明

scope:application(应用粒度)、service(服务粒度)
force:路由结果为空时,是否强制执行,默认false
      true:强制执行,路由结果为空,则返回空结果
      false:路由结果为空时,返回所有服务列表
runtime:是否在每次调用时执行路由规则,默认false
         true:每次调用时执行路由规则,如果使用参数路由,必须设置为true
         false:只有在服务者列表更新后执行路由规则,如果没有更新,使用缓存的列表
enabled:是否启用路由规则,默认true
priority:路由规则优先级,值越大越靠前执行,默认为0
key:路由规则作用的应用名(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.11
thenRule为空,表示禁止访问,如:host = 10.20.153.10 =>
 
whenRule、thenRule格式:key = value、key != value
key为服务调用信息(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

@RestController
public class HelloController {

    @DubboReference(tag = "tag1")       //调用含有标签tag1的服务
    private HelloService helloService;

    @RequestMapping("/hello")
    public String hello(){
        helloService.hello().forEach(System.out::print);

        return "hello consumer 2";
    }
}

             

                 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/735271.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号