soul数据上传之dubbo

【soul-admin】数据获取

【soul-admin】开放的dubbo注册接口

/**

* Register dubbo string.

*

* @param metaDataDTO the meta data dto

* @return the string

*/

@PostMapping("/dubbo-register")

public String registerRpc(@RequestBody final MetaDataDTO metaDataDTO) {

    return soulClientRegisterService.registerDubbo(metaDataDTO);

}

调用了如下方法:

@Override

@Transactional

public String registerDubbo(final MetaDataDTO dto) {

    MetaDataDO exist = metaDataMapper.findByPath(dto.getPath());

    saveOrUpdateMetaData(exist, dto); // 保存元数据

    String selectorId = handlerDubboSelector(dto); // 处理选择器数据

    handlerDubboRule(selectorId, dto); // 处理规则数据

    return SoulResultMessage.SUCCESS;

}

这个方法分为三步:

1. 保存更新元数据

private void saveOrUpdateMetaData(final MetaDataDO exist, final MetaDataDTO metaDataDTO) {

    DataEventTypeEnum eventType;

    MetaDataDO metaDataDO = MetaDataTransfer.INSTANCE.mapToEntity(metaDataDTO);

    if (Objects.isNull(exist)) { // 数据库中不存在该元数据,执行创建元数据逻辑

        Timestamp currentTime = new Timestamp(System.currentTimeMillis());

        metaDataDO.setId(UUIDUtils.getInstance().generateShortUuid());

        metaDataDO.setDateCreated(currentTime);

        metaDataDO.setDateUpdated(currentTime);

        metaDataMapper.insert(metaDataDO);

        eventType = DataEventTypeEnum.CREATE;

    } else { // 更新元数据

        metaDataDO.setId(exist.getId());

        metaDataMapper.update(metaDataDO);

        eventType = DataEventTypeEnum.UPDATE;

    }

    // publish MetaData's event

    eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.META_DATA, eventType,

    Collections.singletonList(MetaDataTransfer.INSTANCE.mapToData(metaDataDTO))));

}

2. 处理选择器数据

private String handlerDubboSelector(final MetaDataDTO metaDataDTO) {

    return getString(metaDataDTO);

}

private String getString(final MetaDataDTO metaDataDTO) {

    SelectorDO selectorDO = selectorService.findByName(metaDataDTO.getContextPath()); // 到数据库中获取选择器数据

    String selectorId;

    if (Objects.isNull(selectorDO)) {

        // 注册选择器数据

        selectorId = registerSelector(metaDataDTO.getContextPath(), metaDataDTO.getRpcType(), metaDataDTO.getAppName(), "");

    } else {

        selectorId = selectorDO.getId();

    }

    return selectorId;

}

private String registerSelector(final String contextPath, final String rpcType, final String appName, final String uri) {

    SelectorDTO selectorDTO = SelectorDTO.builder()

        .name(contextPath)

        .type(SelectorTypeEnum.CUSTOM_FLOW.getCode())

        .matchMode(MatchModeEnum.AND.getCode())

        .enabled(Boolean.TRUE)

        .loged(Boolean.TRUE)

        .continued(Boolean.TRUE)

        .sort(1)

        .build();

    if (RpcTypeEnum.DUBBO.getName().equals(rpcType)) { // 设置Dubbo插件

        selectorDTO.setPluginId(getPluginId(PluginEnum.DUBBO.getName()));

    } else if (RpcTypeEnum.SPRING_CLOUD.getName().equals(rpcType)) {

        selectorDTO.setPluginId(getPluginId(PluginEnum.SPRING_CLOUD.getName()));
        selectorDTO.setHandle(GsonUtils.getInstance().toJson(buildSpringCloudSelectorHandle(appName)));

    } else if (RpcTypeEnum.SOFA.getName().equals(rpcType)) {

        selectorDTO.setPluginId(getPluginId(PluginEnum.SOFA.getName()));

        selectorDTO.setHandle(appName);

    } else if (RpcTypeEnum.TARS.getName().equals(rpcType)) {

        selectorDTO.setPluginId(getPluginId(PluginEnum.TARS.getName()));

        selectorDTO.setHandle(appName);

    } else {

        //is divide

        DivideUpstream divideUpstream = buildDivideUpstream(uri);

        String handler = GsonUtils.getInstance().toJson(Collections.singletonList(divideUpstream));

        selectorDTO.setHandle(handler);

        selectorDTO.setPluginId(getPluginId(PluginEnum.DIVIDE.getName()));

        upstreamCheckService.submit(selectorDTO.getName(), divideUpstream);

    }

    SelectorConditionDTO selectorConditionDTO = new SelectorConditionDTO();

    selectorConditionDTO.setParamType(ParamTypeEnum.URI.getName());

    selectorConditionDTO.setParamName("/");

    selectorConditionDTO.setOperator(OperatorEnum.MATCH.getAlias());

    selectorConditionDTO.setParamValue(contextPath + "/**");
    
    selectorDTO.setSelectorConditions(Collections.singletonList(selectorConditionDTO));

    return selectorService.register(selectorDTO);

}

/**

* {@linkplain org.dromara.soul.admin.service.impl.SelectorServiceImpl#register}

**/

@Override

public String register(final SelectorDTO selectorDTO) {

    SelectorDO selectorDO = SelectorDO.buildSelectorDO(selectorDTO);

    List<SelectorConditionDTO> selectorConditionDTOs = selectorDTO.getSelectorConditions();

    if (StringUtils.isEmpty(selectorDTO.getId())) {

        selectorMapper.insertSelective(selectorDO); // 插入选择器数据

        selectorConditionDTOs.forEach(selectorConditionDTO -> {

            selectorConditionDTO.setSelectorId(selectorDO.getId());

            selectorConditionMapper.insertSelective(SelectorConditionDO.buildSelectorConditionDO(selectorConditionDTO));

        });

    }

    publishEvent(selectorDO, selectorConditionDTOs); // 发布数据变更事件

    return selectorDO.getId();

}

3. 处理规则数据

private void handlerDubboRule(final String selectorId, final MetaDataDTO metaDataDTO) {

    RuleDO existRule = ruleMapper.findByName(metaDataDTO.getPath());

    if (Objects.isNull(existRule)) { // 没有规则数据,则进行注册

        registerRule(selectorId, metaDataDTO.getPath(), metaDataDTO.getRpcType(), metaDataDTO.getRuleName());

    }

}

private void registerRule(final String selectorId, final String path, final String rpcType, final String ruleName) {

    RuleHandle ruleHandle = RuleHandleFactory.ruleHandle(RpcTypeEnum.acquireByName(rpcType), path);

    RuleDTO ruleDTO = RuleDTO.builder()

        .selectorId(selectorId)

        .name(ruleName)

        .matchMode(MatchModeEnum.AND.getCode())

        .enabled(Boolean.TRUE)

        .loged(Boolean.TRUE)

        .sort(1)

        .handle(ruleHandle.toJson())

        .build();

    RuleConditionDTO ruleConditionDTO = RuleConditionDTO.builder()

        .paramType(ParamTypeEnum.URI.getName())

        .paramName("/")

        .paramValue(path)
    
        .build();

    if (path.indexOf("*") > 1) { // 有*号则为匹配规则

        ruleConditionDTO.setOperator(OperatorEnum.MATCH.getAlias());

    } else { // 没有 * 号则为相等规则

        ruleConditionDTO.setOperator(OperatorEnum.EQ.getAlias());

    }

    ruleDTO.setRuleConditions(Collections.singletonList(ruleConditionDTO));

    ruleService.register(ruleDTO);

}

/**

* {@linkplain org.dromara.soul.admin.service.impl.RuleServiceImpl#register}

**/

@Override

public String register(final RuleDTO ruleDTO) {

    RuleDO ruleDO = RuleDO.buildRuleDO(ruleDTO);

    List<RuleConditionDTO> ruleConditions = ruleDTO.getRuleConditions();

    if (StringUtils.isEmpty(ruleDTO.getId())) { // 不存在的规则数据,添加

        ruleMapper.insertSelective(ruleDO);

        ruleConditions.forEach(ruleConditionDTO -> {

            ruleConditionDTO.setRuleId(ruleDO.getId());

            ruleConditionMapper.insertSelective(RuleConditionDO.buildRuleConditionDO(ruleConditionDTO));

        });

    }

    publishEvent(ruleDO, ruleConditions); // 发布规则变更事件

    return ruleDO.getId();

}

客户端

客户端是通过Spring的事件机制(Spring容器初始化完成之后会在容器中发布ContextRefreshedEvent事件)对Spring管理的Bean进行扫描相对应的注解来注册服务的

@Configuration
public class SoulApacheDubboClientConfiguration {
    /**
    * Apache dubbo service bean post processor alibaba dubbo service bean post processor.
    *
    * @param dubboConfig the dubbo config
    * @return the alibaba dubbo service bean post processor
    */
    @Bean
    public ApacheDubboServiceBeanPostProcessor apacheDubboServiceBeanPostProcessor(final DubboConfig dubboConfig) {
        return new ApacheDubboServiceBeanPostProcessor(dubboConfig);
    }

    /**   
    * Dubbo config dubbo config.
    *
    * @return the dubbo config
    */
    @Bean
    @ConfigurationProperties(prefix = "soul.dubbo")
    public DubboConfig dubboConfig() {
        return new DubboConfig();
    }
}
@Slf4j
public class ApacheDubboServiceBeanPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
    private DubboConfig dubboConfig;
    private ExecutorService executorService;
    private final String url;
    public ApacheDubboServiceBeanPostProcessor(final DubboConfig dubboConfig) {
        String contextPath = dubboConfig.getContextPath();
        String adminUrl = dubboConfig.getAdminUrl();
        if (StringUtils.isEmpty(contextPath)
            || StringUtils.isEmpty(adminUrl)) {
            throw new RuntimeException("apache dubbo client must config the contextPath, adminUrl");
        }
        this.dubboConfig = dubboConfig;
        url = dubboConfig.getAdminUrl() + "/soul-client/dubbo-register";
        executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
    }

    private void handler(final ServiceBean serviceBean) {
        Class<?> clazz = serviceBean.getRef().getClass();
        if (ClassUtils.isCglibProxyClass(clazz)) { // 获取Spring管理的类
            String superClassName = clazz.getGenericSuperclass().getTypeName();
            try {
                clazz = Class.forName(superClassName);
            } catch (ClassNotFoundException e) {
                log.error(String.format("class not found: %s", superClassName));
                return;
            }
        }
        final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(clazz); // 扫描方法,如果有SoulDubboClient注解,则注册到【soul-admin】中
        for (Method method : methods) {
            SoulDubboClient soulDubboClient = method.getAnnotation(SoulDubboClient.class);
            if (Objects.nonNull(soulDubboClient)) {
                RegisterUtils.doRegister(buildJsonParams(serviceBean, soulDubboClient, method), url, RpcTypeEnum.DUBBO);
            }
        }
    }

    @Override
    public void onApplicationEvent(final ContextRefreshedEvent contextRefreshedEvent) { // Spring容器加载完毕后执行
        if (Objects.nonNull(contextRefreshedEvent.getApplicationContext().getParent())) {
            return;
        }
        Map<String, ServiceBean> serviceBean = contextRefreshedEvent.getApplicationContext().getBeansOfType(ServiceBean.class);
        for (Map.Entry<String, ServiceBean> entry : serviceBean.entrySet()) { // 对 Spirng 容器中所有注解了ServiceBean的对象,注册到 【soul-admin】中
            executorService.execute(() -> handler(entry.getValue()));
        }
    }

    // 构造请求参数
    private String buildJsonParams(final ServiceBean serviceBean, final SoulDubboClient soulDubboClient, final Method method) {
        String appName = dubboConfig.getAppName();
        if (StringUtils.isEmpty(appName)) {
            appName = serviceBean.getApplication().getName();
        }
        String path = dubboConfig.getContextPath() + soulDubboClient.path();
        String desc = soulDubboClient.desc();
        String serviceName = serviceBean.getInterface();
        String configRuleName = soulDubboClient.ruleName();
        String ruleName = ("".equals(configRuleName)) ? path : configRuleName;
        String methodName = method.getName();
        Class<?>[] parameterTypesClazz = method.getParameterTypes();
        String parameterTypes = Arrays.stream(parameterTypesClazz).map(Class::getName)
            .collect(Collectors.joining(","));
        MetaDataDTO metaDataDTO = MetaDataDTO.builder()
            .appName(appName)
            .serviceName(serviceName)
            .methodName(methodName)
            .contextPath(dubboConfig.getContextPath())
            .path(path)
            .ruleName(ruleName)
            .pathDesc(desc)
            .parameterTypes(parameterTypes)
            .rpcExt(buildRpcExt(serviceBean))
            .rpcType("dubbo")
            .enabled(soulDubboClient.enabled())
            .build();
        return OkHttpTools.getInstance().getGson().toJson(metaDataDTO);
    }

    // RPC 额外信息构造 包括组/版本/负载均衡/重试次数/超时时间等
    private String buildRpcExt(final ServiceBean serviceBean) {
        MetaDataDTO.RpcExt build = MetaDataDTO.RpcExt.builder()
            .group(StringUtils.isNotEmpty(serviceBean.getGroup()) ? serviceBean.getGroup() : "")
            .version(StringUtils.isNotEmpty(serviceBean.getVersion()) ? serviceBean.getVersion() : "")
            .loadbalance(StringUtils.isNotEmpty(serviceBean.getLoadbalance()) ? serviceBean.getLoadbalance() : Constants.DEFAULT_LOADBALANCE)
            .retries(Objects.isNull(serviceBean.getRetries()) ? Constants.DEFAULT_RETRIES : serviceBean.getRetries())
            .timeout(Objects.isNull(serviceBean.getTimeout()) ? Constants.DEFAULT_CONNECT_TIMEOUT : serviceBean.getTimeout())
            .url("")
            .build();
        return OkHttpTools.getInstance().getGson().toJson(build);
    }

}

以上就是Dubbo元数据上传流程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值