IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 远程过程调用RPC 5:Dubbo路由 -> 正文阅读

[网络协议]远程过程调用RPC 5:Dubbo路由

prev:远程过程调用RPC 4:RPC服务框架Dubbo

Dubbo路由概述

dubbo2.7官方文档-旧路由规则
Dubbo在服务治理方面提供了路由功能,主要是决定一次Dubbo服务调用时调用的目标服务器。
dubbo主要支持三种路由方式:

  • 条件路由
  • 脚本路由
  • 标签路由
  • 扩展SPI实现自定义路由

条件路由

条件路由是基于条件表达式的路由规则。大致语法是以=>符号进行分隔:

  • => 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则
  • => 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表
  • 符号前后可以为空,表示对提供方/消费方进行不加限制/禁止访问

举个简单的例子:

# 表示允许IP为10.20.153.10访问IP为10.20.153.11的服务
host = 10.20.153.10 => host = 10.20.153.11
#表示允许IP为10.20.153.10访问IP为10.20.153.10、10.20.153.11之外的服务
host = 10.20.153.10 => host != 10.20.153.10,10.20.153.11
# 表示任何访问不得访问IP为172.22网段的服务
=> host != 172.22.*

此种路由方式支持对method、argument、protocol、host、port、application、organization上的参数进行区分

脚本路由

脚本路由无法在dubbo控制台上进行配置,脚本路由规则支持JDK脚本引擎的所有脚本,比如:javascript, jruby, groovy 等,通过type=javascript参数设置脚本类型,缺省为 javascript。

demo

本例中,涉及两个provider对外提供rpc服务,使用consumer对服务进行消费,使用的例子是之前远程过程调用RPC 4:RPC服务框架Dubbo的进一步深入。

结构

在这里插入图片描述
主要涉及两个provider和一个consumer。分别是三个Spring Boot的模块。

provider

provider的提供的接口是ProviderService,定义在com.mxb.provider.service下:

public interface ProviderService {
    String sayHello(String word);
}

其实现功能为:返回一个字符串,内容为hello + 参数的word。实现在com.mxb.provider.service下:

public class ProviderServiceImpl implements ProviderService{
    @Override
    public String sayHello(String word) {
        return "hello" + word;
    }
}

provider的配置文件定义在resource下的META-INF/spring文件夹下,内容为:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!--唯一名称,计算依赖关系的标签-->
    <dubbo:application name="provider" owner="mxb"></dubbo:application>
    <dubbo:monitor protocol="registry"/>
    <!--dubbo服务所要暴露的服务地址所对应的注册中心-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!--当前服务发布所依赖的协议;webserovice、Thrift、Hessain、http-->
    <dubbo:protocol name="dubbo" port="20881"/>
    <!--服务发布的配置,需要暴露的服务接口-->
    <dubbo:service
            interface="com.mxb.provider.service.ProviderService"
            ref="providerService"
    />
    <!--Bean bean定义-->
    <bean id="providerService" class="com.mxb.provider.service.ProviderServiceImpl"/>
</beans>

可以看出,注册在了我本地2181端口上的zookeeper上,provider01的端口为20881,服务名为provider。
同样的,provider02的实现类似,不过返回的字符串为灰度测试hello+参数name,模拟提供灰度服务:

public class ProviderServiceImpl implements ProviderService{
    @Override
    public String sayHello(String word) {
        return "灰度测试    hello" + word;
    }
}

provider01的端口为20882,服务名为provider
启动类为:

@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/myprovider.xml");
        context.start();
        System.in.read();
    }
}

拉起来两个服务后,dubbo控制台可以看到:
在这里插入图片描述

consumer

在这里插入图片描述
在消费端,消费这两个服务:

public class ConsumerApplication {

    public static void main(String[] args) throws IOException, InterruptedException {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        ProviderService providerService = (ProviderService) context.getBean("providerService");
        while (true)
        {
            String str = providerService.sayHello(" mxb");
            System.out.println(str);
            str = providerService.sayHello(" sgj");
            System.out.println(str);
            Thread.sleep(1500);
        }
    }
}

consumer.xml定义如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="consumer" owner="mxb"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:monitor protocol="registry"/>
    <dubbo:reference id="providerService"
                     interface="com.mxb.provider.service.ProviderService"/>
</beans>

在运行时,效果为随机执行两个服务的逻辑:
在这里插入图片描述

引入路由脚本

为了简单起见,这里我们直接向zookeeper上写入router数据,zookeeper上路由配置在/dubbo/com.mxb.provider.service.ProviderService/routers里面,从客户端可以看出目前无路由策略:
在这里插入图片描述
直接将脚本注册到zookeeper上:

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry;
import com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory;
import com.alibaba.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter;

public class ZkConfig {
    public static void main(String[] args) {
        URL registryUrl = URL.valueOf("zookeeper://127.0.0.1:2181");
        ZookeeperRegistryFactory zookeeperRegistryFactory = new
                ZookeeperRegistryFactory();
        zookeeperRegistryFactory.setZookeeperTransporter(new
                CuratorZookeeperTransporter());
        Registry zookeeperRegistry = (ZookeeperRegistry)
                zookeeperRegistryFactory.createRegistry(registryUrl);
        URL routerURL =
                URL.valueOf("script://0.0.0.0/com.mxb.provider.service.ProviderService?category=routers&dynamic=false&enabled=true&force=false&priority=0");
        routerURL = routerURL.addParameter("rule",URL.encode("(function route(invokers) {\n" +
                "    var result = new java.util.ArrayList(invokers.size());\n" +
                "    for (i = 0; i < invokers.size(); i ++) {\n" +
                "        if (\"30.22.97.17:20882\".equals(invokers.get(i).getUrl().getAddress())) {\n" +
                "            result.add(invokers.get(i));\n" +
                "        }\n" +
                "    }\n" +
                "    return result;\n" +
                "} (invokers));  ") );
        zookeeperRegistry.register(routerURL);
    }
}

这里的脚本如下:

(function route(invokers) {
    var result = new java.util.ArrayList(invokers.size());
    for (i = 0; i < invokers.size(); i ++) {
        if ("30.22.97.17:20882".equals(invokers.get(i).getUrl().getAddress())) {
            result.add(invokers.get(i));
        }
    }
    return result;
} (invokers));

这里的invokers是全部的服务,这里脚本的意思是将address为30.22.96.238:20882的加入list并返回,表述只能访问30.22.96.238:20882的服务。
执行后,可以看到zookeeper的/dubbo/com.mxb.provider.service.ProviderService/routers下已经有了信息:
在这里插入图片描述
那么在使用消费者的时候,只能访问端口20882下灰度的服务:
在这里插入图片描述
那么,能否实现根据参数的内容进行路由呢,采用下面的脚本进行测试:参考Dubbo服务治理之灰度发布方案(版本发布控制影响范围)

(function route(invokers, invocation) {
    var serviceInvokers = new java.util.ArrayList(invokers.size());
    var grayInvokers = new java.util.ArrayList(invokers.size());
    for (i=0;i<invokers.size(); i++) {  
        if ("30.22.97.17:20881".equals(invokers.get(i).getUrl().getAddress())) {
            serviceInvokers.add(invokers.get(i));
        }else{
            grayInvokers.add(invokers.get(i));
        }
    }
    var invArguments = invocation.getArguments();
   // 进入了此分支
    if(invArguments == null || invArguments.length == 0) {
        return serviceInvokers;
    }
    var name = invArguments[0];
    if(name == "mxb") {
        return grayInvokers;
    }else{
        return serviceInvokers;
    }
}(invokers, invocation) );

这里的invocation参数的invocation.getArguments()是获取接口的参数,详见:源码分析。
但是在注释那块就进入了分支,也就是说并没有获得接口参数。尝试失败

标签路由

标签路由引入自dubbo2.7:官方文档-标签路由
运行下面demo之前记得清楚zookeeper上的router规则:

deleteall /dubbo/com.mxb.provider.service.ProviderService/routers

动态打标签

来自官方文档的例子:

force: false
  runtime: true
  enabled: true
  key: governance-tagrouter-provider
  tags:
    - name: tag1
      addresses: ["127.0.0.1:20880"]
    - name: tag2
      addresses: ["127.0.0.1:20881"]

这样就给127.0.0.1:20880上的governance-tagrouter-provider服务打上了tag1标签。

静态打标签

修改配置文件,在本项目中,在provider02的配置文件中加入:

    <dubbo:provider tag="grey"/>

给provider02打上了grey标签
在consumer调用的时候:

public class ConsumerApplication {
    public static void main(String[] args) throws IOException, InterruptedException {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        ProviderService providerService = (ProviderService) context.getBean("providerService");
        while (true)
        {
            RpcContext.getContext().setAttachment(Constants.TAG_KEY,"grey");
            String str = providerService.sayHello(" mxb");
            System.out.println(str);
            str = providerService.sayHello(" sgj");
            System.out.println(str);
            Thread.sleep(1500);
        }
    }
}

也就是在每次调用之前,加入Tag grey,因为这个标签仅一次有效,效果为应该是mxb的为灰度测试,sgj的为普通效果,如下:
在这里插入图片描述
可以看出tag发挥了作用

扩展SPI自定义路由

支持扩展SPI自定义路由规则:官方文档-路由扩展
demo没跑通,在调试。

参考

官方文档-路由扩展
官方文档-路由规则
Dubbo自定义路由
Dubbo3.0如何实现进行路由扩展
深度解析dubbo集群路由之脚本路由
Dubbo-Router条件路由、脚本路由使用
dubbo设置自定义路由
[Dubbo] 源码解析之服务路由策略
Dubbo服务治理之灰度发布方案(版本发布控制影响范围)
Curator基本操作
Dubbo 路由规则之标签路由

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 19:26:03  更:2022-06-29 19:26:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年3日历 -2024/3/29 21:29:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码