Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue#322 add sofa plugin #384

Merged
merged 6 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<frontend.plugin.skip>true</frontend.plugin.skip>
<swagger.version>2.9.2</swagger.version>
<apache-rat-plugin.version>0.12</apache-rat-plugin.version>
<sofa.rpc.version>5.7.6</sofa.rpc.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -170,6 +171,12 @@
<version>${apache.dubbo.version}</version>
</dependency>

<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-rpc-all</artifactId>
<version>${sofa.rpc.version}</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,15 @@ public String registerSpringCloud(@RequestBody final SpringCloudRegisterDTO spri
public String registerRpc(@RequestBody final MetaDataDTO metaDataDTO) {
return soulClientRegisterService.registerDubbo(metaDataDTO);
}

/**
* Register rpc string.
*
* @param metaDataDTO the meta data dto
* @return the string
*/
@PostMapping("/sofa-register")
public String registerSofaRpc(@RequestBody final MetaDataDTO metaDataDTO) {
return soulClientRegisterService.registerSofa(metaDataDTO);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,12 @@ public interface SoulClientRegisterService {
* @return the string
*/
String registerDubbo(MetaDataDTO metaDataDTO);

/**
* Register rpc string.
*
* @param metaDataDTO the meta data dto
* @return the string
*/
String registerSofa(MetaDataDTO metaDataDTO);
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.dromara.soul.common.dto.convert.DivideUpstream;
import org.dromara.soul.common.dto.convert.rule.DivideRuleHandle;
import org.dromara.soul.common.dto.convert.rule.DubboRuleHandle;
import org.dromara.soul.common.dto.convert.rule.SofaRuleHandle;
import org.dromara.soul.common.dto.convert.rule.SpringCloudRuleHandle;
import org.dromara.soul.common.enums.ConfigGroupEnum;
import org.dromara.soul.common.enums.DataEventTypeEnum;
Expand Down Expand Up @@ -163,6 +164,39 @@ private void handlerDubboRule(final String selectorId, final MetaDataDTO metaDat
}
}

@Override
public String registerSofa(final MetaDataDTO dto) {
MetaDataDO byPath = metaDataMapper.findByPath(dto.getPath());
if (Objects.nonNull(byPath)
&& (!byPath.getMethodName().equals(dto.getMethodName())
|| !byPath.getServiceName().equals(dto.getServiceName()))) {
return "you path already exist!";
}
final MetaDataDO exist = metaDataMapper.findByServiceNameAndMethod(dto.getServiceName(), dto.getMethodName());
saveOrUpdateMetaData(exist, dto);
String selectorId = handlerSofaSelector(dto);
handlerSofaRule(selectorId, dto, exist);
return "success";
}

private String handlerSofaSelector(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 void handlerSofaRule(final String selectorId, final MetaDataDTO metaDataDTO, final MetaDataDO exist) {
RuleDO existRule = ruleMapper.findByName(metaDataDTO.getPath());
if (Objects.isNull(exist) || Objects.isNull(existRule)) {
registerRule(selectorId, metaDataDTO.getPath(), metaDataDTO.getRpcType(), metaDataDTO.getRuleName());
}
}

private void saveSpringMvcMetaData(final SpringMvcRegisterDTO dto) {
MetaDataDO metaDataDO = new MetaDataDO();
metaDataDO.setAppName(dto.getAppName());
Expand Down Expand Up @@ -297,6 +331,9 @@ private String registerSelector(final String contextPath, final String rpcType,
} else if (RpcTypeEnum.SPRING_CLOUD.getName().equals(rpcType)) {
selectorDTO.setPluginId("8");
selectorDTO.setHandle(appName);
} else if (RpcTypeEnum.SOFA.getName().equals(rpcType)) {
selectorDTO.setPluginId("11");
selectorDTO.setHandle(appName);
} else {
//is divide
DivideUpstream divideUpstream = buildDivideUpstream(uri);
Expand Down Expand Up @@ -352,6 +389,12 @@ private void registerRule(final String selectorId, final String path, final Stri
divideRuleHandle.setLoadBalance(LoadBalanceEnum.RANDOM.getName());
divideRuleHandle.setRetry(0);
ruleDTO.setHandle(JsonUtils.toJson(divideRuleHandle));
} else if (rpcType.equals(RpcTypeEnum.SOFA.getName())) {
SofaRuleHandle sofaRuleHandle = new SofaRuleHandle();
sofaRuleHandle.setLoadBalance(LoadBalanceEnum.RANDOM.getName());
sofaRuleHandle.setRetries(0);
sofaRuleHandle.setTimeout(3000);
ruleDTO.setHandle(JsonUtils.toJson(sofaRuleHandle));
} else {
SpringCloudRuleHandle springCloudRuleHandle = new SpringCloudRuleHandle();
springCloudRuleHandle.setPath(path);
Expand Down
1 change: 1 addition & 0 deletions soul-admin/src/main/resources/META-INF/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ INSERT IGNORE INTO `plugin` (`id`, `name`,`role`,`config`,`enabled`, `date_creat
INSERT IGNORE INTO `plugin` (`id`, `name`,`role`, `enabled`, `date_created`, `date_updated`) VALUES ('8', 'springCloud','0', '0', '2018-06-25 13:47:57', '2018-06-25 13:47:57');
INSERT IGNORE INTO `plugin` (`id`, `name`,`role`, `enabled`, `date_created`, `date_updated`) VALUES ('9', 'hystrix', '0','0', '2020-01-15 10:19:10', '2020-01-15 10:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`,`role`, `enabled`, `date_created`, `date_updated`) VALUES ('10', 'sentinel', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`,`role`, `config`, `enabled`, `date_created`, `date_updated`) VALUES ('11', 'sofa', '0', '{"protocol":"zookeeper","register":"127.0.0.1:2181"}', '0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');

INSERT IGNORE INTO plugin_handle (`id`,`plugin_id`,`field`,`label`,`data_type`,`date_created`,`date_updated`) VALUES ('1','10', 'flowRuleGrade', '限流阈值类型','3', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT IGNORE INTO plugin_handle (`id`,`plugin_id`,`field`,`label`,`data_type`,`date_created`,`date_updated`) VALUES ('2','10', 'flowRuleControlBehavior', '流控效果','3', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
Expand Down
1 change: 1 addition & 0 deletions soul-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<module>soul-client-common</module>
<module>soul-client-http</module>
<module>soul-client-dubbo</module>
<module>soul-client-sofa</module>
</modules>

<dependencies>
Expand Down
66 changes: 66 additions & 0 deletions soul-client/soul-client-sofa/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>soul-client</artifactId>
<groupId>org.dromara</groupId>
<version>2.2.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>soul-client-sofa</artifactId>

<dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-client-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>runtime-sofa-boot-starter</artifactId>
<version>3.1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-rpc-all</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.dromara.soul.client.sofa;

import com.alipay.sofa.runtime.service.component.Service;
import com.alipay.sofa.runtime.spring.factory.ServiceFactoryBean;
import lombok.extern.slf4j.Slf4j;
import org.dromara.soul.client.common.utils.OkHttpTools;
import org.dromara.soul.client.sofa.common.annotation.SoulSofaClient;
import org.dromara.soul.client.sofa.common.config.SofaConfig;
import org.dromara.soul.client.sofa.common.dto.MetaDataDTO;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
* The Sofa ServiceBean PostProcessor.
*
* @author tydhot
*/
@Slf4j
public class SofaServiceBeanPostProcessor implements BeanPostProcessor {

private SofaConfig sofaConfig;

private ExecutorService executorService;

private final String url;

public SofaServiceBeanPostProcessor(final SofaConfig sofaConfig) {
String contextPath = sofaConfig.getContextPath();
String adminUrl = sofaConfig.getAdminUrl();
if (contextPath == null || "".equals(contextPath)
|| adminUrl == null || "".equals(adminUrl)) {
throw new RuntimeException("sofa client must config the contextPath, adminUrl");
}
this.sofaConfig = sofaConfig;
url = sofaConfig.getAdminUrl() + "/soul-client/sofa-register";
executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
}

@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
if (bean instanceof ServiceFactoryBean) {
executorService.execute(() -> handler((ServiceFactoryBean) bean));
}
return bean;
}

private void handler(final ServiceFactoryBean serviceBean) {
Class<?> clazz = null;
try {
clazz = ((Service) serviceBean.getObject()).getTarget().getClass();
} catch (Exception e) {
log.error("failed to get sofa target class");
return;
}
if (ClassUtils.isCglibProxyClass(clazz)) {
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);
for (Method method : methods) {
SoulSofaClient soulDubboClient = method.getAnnotation(SoulSofaClient.class);
if (Objects.nonNull(soulDubboClient)) {
post(buildJsonParams(serviceBean, soulDubboClient, method));
}
}
}

private String buildJsonParams(final ServiceFactoryBean serviceBean, final SoulSofaClient soulSofaClient, final Method method) {
String appName = sofaConfig.getAppName();
String path = sofaConfig.getContextPath() + soulSofaClient.path();
String desc = soulSofaClient.desc();
String serviceName = serviceBean.getInterfaceClass().getName();
String configRuleName = soulSofaClient.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(sofaConfig.getContextPath())
.path(path)
.ruleName(ruleName)
.pathDesc(desc)
.parameterTypes(parameterTypes)
.rpcType("sofa")
.enabled(soulSofaClient.enabled())
.build();
return OkHttpTools.getInstance().getGosn().toJson(metaDataDTO);

}

private void post(final String json) {
try {
String result = OkHttpTools.getInstance().post(url, json);
if (Objects.equals(result, "success")) {
log.info("sofa client register success :{} " + json);
} else {
log.error("sofa client register error :{} " + json);
}
} catch (IOException e) {
log.error("cannot register soul admin param :{}", url + ":" + json);
}
}
}
Loading