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 {
    /**
     * Create state router.
     *
     * @param url url
     * @return router instance
     * @since 3.0
     */
    @Adaptive("protocol")
    <T> StateRouter<T> getRouter(Class<T> 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

            

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

<dubbo:provider tag="tag1"/>
<dubbo:service tag="tag1"/>
java -jar xxx-provider.jar -Ddubbo.provider.tag={tag1}

            

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

# 消费端调用标签tag1的服务
RpcContext.getContext().setAttachment(Constants.REQUEST_TAG_KEY,"tag1");
<dubbo:reference interface="com.xxx.MenuService" tag="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 <T> StateRouter<T> getRouter(Class<T> 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=<file-content>
            //将文件url转换为scripr路由url,并且加载文件内容附加在url中,如
            //file:///d:/path/to/route.js?router=script
            //转换为script:///d:/path/to/route.js?type=js&rule=<file-content>
            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

/**
 * ScriptRouterFactory
 * <p>
 * Example URLS used by Script Router Factory:
 * <ol> 
 * <li> script://registryAddress?type=js&rule=xxxx          //注册中心脚本路由
 * <li> script:///path/to/routerfile.js?type=js&rule=xxxx   //linux、mac脚本路由
 * <li> script://D:\path\to\routerfile.js?type=js&rule=xxxx //windows脚本路由
 * <li> script://C:/path/to/routerfile.js?type=js&rule=xxxx
 * </ol>
 * The host value in URL points out the address of the source content of the Script Router,Registry、File etc
 *
 */
public class ScriptStateRouterFactory implements StateRouterFactory {
 
    public static final String NAME = "script";
 
    @Override
    public <T> StateRouter<T> getRouter(Class<T> interfaceClass, URL url) {
        return new ScriptStateRouter<>(url);
    }
 
}

                

                

                                   

消费端标签过滤

       

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

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface DubboReference {
 
    /**
     * Interface class, default value is void.class
     */
    Class<?> interfaceClass() default void.class;
 
    /**
     * Interface class name, default value is empty string
     */
    String interfaceName() default "";
 
    String group() default "";    //服务分组
    String version() default "";  //服务版本
 
    /**
     * Service target URL for direct invocation, if this is specified, then registry center takes no effect.
     */
    String url() default "";      //直连服务提供端(如果配置了,则不使用注册中心)
 
    /**
     * Client transport type, default value is "netty"
     */
    String client() default "";   //客户端传输方式,默认为netty
 
    /**
     * Whether to enable generic invocation, default value is false
     * @deprecated Do not need specify generic value, judge by injection type and interface class
     */
    @Deprecated
    boolean generic() default false;   //已禁用
 
    /**
     * When enable, prefer to call local service in the same JVM if it's present, default value is true
     * @deprecated using scope="local" or scope="remote" instead
     */
    @Deprecated
    boolean injvm() default true;      //已禁用
 
    /**
     * Check if service provider is available during boot up, default value is true
     */
    boolean check() default true;
 
    /**
     * Whether eager initialize the reference bean when all properties are set, default value is true ( null as true)
     * @see ReferenceConfigBase#shouldInit()
     */
    boolean init() default true;
 
    /**
     * Whether to make connection when the client is created, the default value is false
     */
    boolean lazy() default false;
 
    /**
     * Export an stub service for event dispatch, default value is false.
     * <p>
     * see org.apache.dubbo.rpc.Constants#STUB_EVENT_METHODS_KEY
     */
    boolean stubevent() default false;
 
    /**
     * Whether to reconnect if connection is lost, if not specify, reconnect is enabled by default, and the interval
     * for retry connecting is 2000 ms
     * <p>
     * see org.apache.dubbo.remoting.Constants#DEFAULT_RECONNECT_PERIOD
     */
    String reconnect() default "";
 
    /**
     * Whether to stick to the same node in the cluster, the default value is false
     * <p>
     * see Constants#DEFAULT_CLUSTER_STICKY
     */
    boolean sticky() default false;
 
    /**
     * How the proxy is generated, legal values include: jdk, javassist
     */
    String proxy() default "";
 
    /**
     * Service stub name, use interface name + Local if not set
     */
    String stub() default "";
 
    /**
     * Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
     * you can use {@link org.apache.dubbo.common.constants.ClusterRules#FAIL_FAST} ……
     */
    String cluster() default ClusterRules.EMPTY;
 
    /**
     * Maximum connections service provider can accept, default value is 0 - connection is shared
     */
    int connections() default -1;
 
    /**
     * The callback instance limit peer connection
     * <p>
     * see org.apache.dubbo.rpc.Constants#DEFAULT_CALLBACK_INSTANCES
     */
    int callbacks() default -1;
 
    /**
     * Callback method name when connected, default value is empty string
     */
    String onconnect() default "";
 
    /**
     * Callback method name when disconnected, default value is empty string
     */
    String ondisconnect() default "";
 
    /**
     * Service owner, default value is empty string
     */
    String owner() default "";
 
    /**
     * Service layer, default value is empty string
     */
    String layer() default "";
 
    /**
     * Service invocation retry times
     * <p>
     * see Constants#DEFAULT_RETRIES
     */
    int retries() default -1;
 
    /**
     * Load balance strategy, legal values include: random, roundrobin, leastactive
     * you can use {@link org.apache.dubbo.common.constants.LoadbalanceRules#RANDOM} ……
     */
    String loadbalance() default LoadbalanceRules.EMPTY;
 
    /**
     * Whether to enable async invocation, default value is false
     */
    boolean async() default false;
 
    /**
     * Maximum active requests allowed, default value is 0
     */
    int actives() default -1;
 
    /**
     * Whether the async request has already been sent, the default value is false
     */
    boolean sent() default false;
 
    /**
     * Service mock name, use interface name + Mock if not set
     */
    String mock() default "";
 
    /**
     * Whether to use JSR303 validation, legal values are: true, false
     */
    String validation() default "";
 
    /**
     * Timeout value for service invocation, default value is 0
     */
    int timeout() default -1;
 
    /**
     * Specify cache implementation for service invocation, legal values include: lru, threadlocal, jcache
     */
    String cache() default "";
 
    /**
     * Filters for service invocation
     * <p>
     * see Filter
     */
    String[] filter() default {};
 
    /**
     * Listeners for service exporting and unexporting
     * <p>
     * see ExporterListener
     */
    String[] listener() default {};
 
    /**
     * Customized parameter key-value pair, for example: {key1, value1, key2, value2} or {"key1=value1", "key2=value2"}
     */
    String[] parameters() default {};
 
    /**
     * Application name
     * @deprecated This attribute was deprecated, use bind application/module of spring ApplicationContext
     */
    @Deprecated
    String application() default "";
 
    /**
     * Module associated name
     */
    String module() default "";
 
    /**
     * Consumer associated name
     */
    String consumer() default "";
 
    /**
     * Monitor associated name
     */
    String monitor() default "";
 
    /**
     * Registry associated name
     */
    String[] registry() default {};
 
    /**
     * The communication protocol of Dubbo Service
     *
     * @return the default value is ""
     * @since 2.6.6
     */
    String protocol() default "";
 
    /**
     * Service tag name
     */
    String tag() default "";       //标签设置
 
    /**
     * Service merger
     */
    String merger() default "";
 
    /**
     * methods support
     */
    Method[] methods() default {};
 
    /**
     * The id
     * NOTE: The id attribute is ignored when using @DubboReference on @Bean method
     * @return default value is empty
     * @since 2.7.3
     */
    String id() default "";
 
    /**
     * @return The service names that the Dubbo interface subscribed
     * @see RegistryConstants#SUBSCRIBED_SERVICE_NAMES_KEY
     * @since 2.7.8
     * @deprecated using {@link DubboReference#providedBy()}
     */
    @Deprecated
    String[] services() default {};
 
    /**
     * declares which app or service this interface belongs to
     * @see RegistryConstants#PROVIDED_BY
     */
    String[] providedBy() default {};
 
    /**
     * the scope for referring/exporting a service, if it's local, it means searching in current JVM only.
     * @see org.apache.dubbo.rpc.Constants#SCOPE_LOCAL
     * @see org.apache.dubbo.rpc.Constants#SCOPE_REMOTE
     */
    String scope() default "";
 
    /**
     * Weather the reference is refer asynchronously
     */
    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";
    }
}

             

                 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值