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

Grpc plugin #1081

Merged
merged 6 commits into from
Feb 2, 2021
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
Empty file added script/soul.sql
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public String registerSpringMvc(@RequestBody final SpringMvcRegisterDTO springMv
public String registerSpringCloud(@RequestBody final SpringCloudRegisterDTO springCloudRegisterDTO) {
return soulClientRegisterService.registerSpringCloud(springCloudRegisterDTO);
}

/**
* Register dubbo string.
*
Expand Down Expand Up @@ -100,4 +100,15 @@ public String registerSofaRpc(@RequestBody final MetaDataDTO metaDataDTO) {
public String registerTarsRpc(@RequestBody final MetaDataDTO metaDataDTO) {
return soulClientRegisterService.registerTars(metaDataDTO);
}

/**
* Register spring mvc string.
*
* @param grpcMetaDataDTO the spring mvc register dto
* @return the string
*/
@PostMapping("/grpc-register")
public String registerGrpc(@RequestBody final MetaDataDTO grpcMetaDataDTO) {
return soulClientRegisterService.registerGrpc(grpcMetaDataDTO);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@
* The interface Soul client service.
*/
public interface SoulClientRegisterService {

/**
* Register http string.
*
* @param springMvcRegisterDTO the http register dto
* @return the string
*/
String registerSpringMvc(SpringMvcRegisterDTO springMvcRegisterDTO);

/**
* Register spring cloud string.
*
* @param springCloudRegisterDTO the spring cloud register dto
* @return the string
*/
String registerSpringCloud(SpringCloudRegisterDTO springCloudRegisterDTO);

/**
* Register rpc string.
*
Expand All @@ -65,4 +65,12 @@ public interface SoulClientRegisterService {
* @return the string
*/
String registerTars(MetaDataDTO metaDataDTO);

/**
* Register grpc string.
*
* @param metaDataDTO the meta data dto
* @return the string
*/
String registerGrpc(MetaDataDTO metaDataDTO);
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ public class SoulClientRegisterServiceImpl implements SoulClientRegisterService
private final PluginMapper pluginMapper;




/**
* Instantiates a new Meta data service.
*
Expand Down Expand Up @@ -210,6 +208,15 @@ public String registerTars(final MetaDataDTO dto) {
return SoulResultMessage.SUCCESS;
}

@Override
public String registerGrpc(final MetaDataDTO dto) {
MetaDataDO exist = metaDataMapper.findByPath(dto.getPath());
saveOrUpdateMetaData(exist, dto);
String selectorId = handlerGrpcSelector(dto);
handlerGrpcRule(selectorId, dto, exist);
return SoulResultMessage.SUCCESS;
}

private String handlerTarsSelector(final MetaDataDTO metaDataDTO) {
return getString(metaDataDTO);
}
Expand All @@ -232,6 +239,17 @@ private void handlerSofaRule(final String selectorId, final MetaDataDTO metaData
}
}

private String handlerGrpcSelector(final MetaDataDTO metaDataDTO) {
return getString(metaDataDTO);
}

private void handlerGrpcRule(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) {
Timestamp currentTime = new Timestamp(System.currentTimeMillis());
MetaDataDO metaDataDO = MetaDataDO.builder()
Expand Down Expand Up @@ -374,6 +392,9 @@ private String registerSelector(final String contextPath, final String rpcType,
} else if (RpcTypeEnum.TARS.getName().equals(rpcType)) {
selectorDTO.setPluginId(getPluginId(PluginEnum.TARS.getName()));
selectorDTO.setHandle(appName);
} else if (RpcTypeEnum.GRPC.getName().equals(rpcType)) {
selectorDTO.setPluginId(getPluginId(PluginEnum.GRPC.getName()));
selectorDTO.setHandle(appName);
} else {
//is divide
DivideUpstream divideUpstream = buildDivideUpstream(uri);
Expand Down
1 change: 1 addition & 0 deletions soul-admin/src/main/resources/META-INF/schema.h2.sql
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ INSERT INTO `plugin` (`id`, `name`, `role`, `config`, `enabled`, `date_created`,
INSERT INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('12','resilience4j', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('13', 'tars', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('14', 'context_path', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('15', 'grpc', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');

/**default admin user**/
INSERT INTO `dashboard_user` (`id`, `user_name`, `password`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('1','admin','jHcpKkiDbbQh7W7hh8yQSA==', '1', '1', '2018-06-23 15:12:22', '2018-06-23 15:12:23');
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 @@ -264,6 +264,7 @@ INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `config`, `enabled`, `date_cr
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('12','resilience4j', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('13', 'tars', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('14', 'context_path', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('15', 'grpc', '1','0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');

/**default admin user**/
INSERT IGNORE INTO `dashboard_user` (`id`, `user_name`, `password`, `role`, `enabled`, `date_created`, `date_updated`) VALUES ('1','admin','jHcpKkiDbbQh7W7hh8yQSA==', '1', '1', '2018-06-23 15:12:22', '2018-06-23 15:12:23');
Expand Down
1 change: 1 addition & 0 deletions soul-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<module>soul-client-dubbo</module>
<module>soul-client-sofa</module>
<module>soul-client-tars</module>
<module>soul-client-grpc</module>
</modules>

<dependencies>
Expand Down
63 changes: 63 additions & 0 deletions soul-client/soul-client-grpc/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?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-grpc</artifactId>

<properties>
<grpc.version>1.33.1</grpc.version>
</properties>

<dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-client-common</artifactId>
<version>${project.version}</version>
</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>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* 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.grpc;

import io.grpc.BindableService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.soul.client.common.utils.OkHttpTools;
import org.dromara.soul.client.common.utils.RegisterUtils;
import org.dromara.soul.client.grpc.common.annotation.SoulGrpcClient;
import org.dromara.soul.client.grpc.common.config.GrpcConfig;
import org.dromara.soul.client.grpc.common.dto.MetaDataDTO;
import org.dromara.soul.common.enums.RpcTypeEnum;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.NonNull;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

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

/**
* The type Soul grpc client bean post processor.
*
* @author zhanglei
*/
@Slf4j
public class GrpcClientBeanPostProcessor implements BeanPostProcessor {

private final ThreadPoolExecutor executorService;

private final String url;

private final GrpcConfig grpcConfig;

private final String serviceName = "SERVICE_NAME";

/**
* Instantiates a new Soul client bean post processor.
*
* @param config the soul grpc config
*/
public GrpcClientBeanPostProcessor(final GrpcConfig config) {
String contextPath = config.getContextPath();
String adminUrl = config.getAdminUrl();
Integer port = config.getPort();
if (contextPath == null || "".equals(contextPath)
|| adminUrl == null || "".equals(adminUrl)
|| port == null) {
log.error("grpc param must config contextPath, adminUrl and port");
throw new RuntimeException("grpc param must config contextPath, adminUrl and port");
}
this.grpcConfig = config;
url = adminUrl + "/soul-client/grpc-register";
executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
}

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

private void handler(final Object serviceBean) {
Class<?> clazz;
try {
clazz = serviceBean.getClass();
} catch (Exception e) {
log.error("failed to get grpc target class");
return;
}
Class parent = clazz.getSuperclass();
Class classes = parent.getDeclaringClass();
String packageName = null;
try {
Field field = classes.getField(serviceName);
field.setAccessible(true);
packageName = field.get(null).toString();
} catch (Exception e) {
log.error(String.format("SERVICE_NAME field not found: %s", classes));
return;
}
if (StringUtils.isEmpty(packageName)) {
log.error(String.format("grpc SERVICE_NAME can not found: %s", classes));
return;
}
final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(clazz);
for (Method method : methods) {
SoulGrpcClient grpcClient = method.getAnnotation(SoulGrpcClient.class);
if (Objects.nonNull(grpcClient)) {
RegisterUtils.doRegister(buildJsonParams(packageName, grpcClient, method), url, RpcTypeEnum.GRPC);
}
}
}

private String buildJsonParams(final String packageName, final SoulGrpcClient soulGrpcClient, final Method method) {
String path = grpcConfig.getContextPath() + soulGrpcClient.path();
String desc = soulGrpcClient.desc();
String configRuleName = soulGrpcClient.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 grpcMetaDataDTO = MetaDataDTO.builder()
.appName(String.join(":", grpcConfig.getHost(), grpcConfig.getPort().toString()))
.serviceName(packageName)
.methodName(methodName)
.contextPath(grpcConfig.getContextPath())
.path(path)
.ruleName(ruleName)
.pathDesc(desc)
.parameterTypes(parameterTypes)
.rpcType("grpc")
.rpcExt(buildRpcExt(soulGrpcClient))
.enabled(soulGrpcClient.enabled())
.build();
return OkHttpTools.getInstance().getGson().toJson(grpcMetaDataDTO);
}

private String buildRpcExt(final SoulGrpcClient soulGrpcClient) {
MetaDataDTO.RpcExt build = MetaDataDTO.RpcExt.builder()
.timeout(soulGrpcClient.timeout())
.build();
return OkHttpTools.getInstance().getGson().toJson(build);

}
}


Loading