shenyu-grpc插件动态修改同一个selector下的请求的负载策略

思路:
1、在admin页面中的添加selector中对数据进行修改
2、shenyu内部通过发布对应的selectorEvent相关的事件同时修改对应的selector数据库表中该selector相关的数据内容
3、admin的事件发布触发shenyu网关中的相关事件,对应grpc插件内容进行处理时此时会重新在GrpcClientBuilder类中初始化ManagedChannel同时指定负载策略(动态修改时该策略由admin中页面修改后通过事件方式传递内容,该数据也就是selectorData实体),从selectorData中获取新的负载策略

代码修改:

admin、shenyu-common:

SelectorDTO类中添加字符类型字段 loadBalance
SelectorDO类中添加字符类型字段 loadBalance
SelectorData类中添加字符类型字段 loadBalance 同时有参类构造方法中进行数据赋值; 同时器静态内部类 Builder 同添加对loadBalance字段的方法数据设置
SelectorDO#buildSelectorDO()方法中设置传递的负载字段内容 selectorDO.setLoadBalance(selectorDTO.getLoadBalance());
SelectorDO#transFrom()方法中设置传递的负载字段内容 .loadBalance(selectorDO.getLoadBalance())

grpc-plugin:
GrpcPluginDataHandler#handlerSelector()

  // 获取grpc插件中的Selector中的配置信息
    @Override
    public void handlerSelector(final SelectorData selectorData) {
        if (Objects.isNull(selectorData.getName())) {
            return;
        }
        // TODO 从SelectorData中获取到负载策略用于重新初始化客户端的负载方式
        String loadBalance = selectorData.getLoadBalance();
        // 初始化传递selectorName
        GrpcClientCache.initGrpcClient(selectorData.getName(),loadBalance);
        ApplicationConfigCache.getInstance().initPrx(selectorData);
    }

GrpcClientBuilder#buildClient()

/**
     * Build the client.
     *
     * @param contextPath contextPath - selectorName
     * @return ShenyuGrpcClient  shenyuGrpcClient
     */
    public static ShenyuGrpcClient buildClient(final String contextPath, String loadBalance) {
        // TODO 自定义修改负载策略
        if (StringUtil.isNullOrEmpty(loadBalance)) {
            loadBalance = LoadBalancerStrategy.RANDOM.getStrategy();
        } else {
            // 策略方式不是自定义中某一种
            List<String> strategyNames = Arrays.stream(LoadBalancerStrategy.values()).map(item -> item.getStrategy()).collect(Collectors.toList());
            // 全部转为小写方式比较策略名称
            if (!strategyNames.contains(loadBalance.toLowerCase(Locale.ROOT))) {
                loadBalance = LoadBalancerStrategy.RANDOM.getStrategy();
            }
        }
        ManagedChannelBuilder<?> builder = ManagedChannelBuilder
                // build channel to server with server's address
                .forTarget(contextPath)
                // 设置拦截器
                .intercept(new ContextClientInterceptor())
                // 设置默认的负载规则
                .defaultLoadBalancingPolicy(loadBalance)
                // 不会再去尝试升级http1
                .usePlaintext()
                // 消息传输大小限制
                .maxInboundMessageSize(100 * 1024 * 1024)
                //
                .executor(buildExecutor())
                // 关闭重试
                .disableRetry();
        ManagedChannel channel = builder.build();
        channel.getState(true);
        return new ShenyuGrpcClient(channel);
    }

由于前台没有事先构造,postman中构造数据验证

{
  "pluginId": "15",
  "name": "/grpc",
  "type": "1",
  "matchMode": "0",
  "continued": true,
  "loged": false,
  "enabled": true,
  "sort": 1,
  # handle中的数据为grpc服务端的权重和端口信息,端口值设置由客户端实现的GrpcServerBuilder接口实现类决定
  "handle":" [{\"weight\":50,\"upstreamUrl\":\"192.168.43.156:38080\",\"status\":true},{\"weight\":50,\"upstreamUrl\":\"192.168.43.156:38081\",\"status\":true}]",
  "selectorConditions": [
    {
      "id": "1676849893883617280",
      "selectorId": "1676849893816508416",
      "paramType": "uri",
      "paramTypeName": "uri",
      "operator": "startsWith",
      "operatorName": "startsWith",
      "paramName": "/",
      "paramValue": "/grpc/",
      "dateCreated": "2023-07-06 16:18:39",
      "dateUpdated": "2023-07-06 16:18:39"
    }
  ],
  "id": "1676849893816508416",
  # 添加的自定义字段动态决定负载均衡方式,自定义扩展grpc赋值策略可以仿照org.apache.shenyu.plugin.grpc.loadbalance包类型实现
  "loadBalance": "random"
}

表结构修改
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值