You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by zh...@apache.org on 2023/01/09 03:35:15 UTC
[shenyu] branch master updated: [ISSUE #3450]Add brpc-plugin (#4300)
This is an automated email from the ASF dual-hosted git repository.
zhangzicheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 01988f4f0 [ISSUE #3450]Add brpc-plugin (#4300)
01988f4f0 is described below
commit 01988f4f039ec945eb1e4e9d2837e21be3e394be
Author: SongTao Zhuang <51...@users.noreply.github.com>
AuthorDate: Mon Jan 9 11:35:09 2023 +0800
[ISSUE #3450]Add brpc-plugin (#4300)
* add: brpc plugin
* ci: common
* add: spring boot starter plugin brpc
* delete: spring boot starter plugin brpc
---
.../apache/shenyu/common/constant/Constants.java | 5 +
.../dto/convert/plugin/BrpcRegisterConfig.java | 183 +++++++++++
shenyu-plugin/pom.xml | 1 +
.../shenyu/plugin/api/result/ShenyuResultEnum.java | 4 +
.../plugin/base/RpcParamTransformPlugin.java | 3 +-
shenyu-plugin/shenyu-plugin-brpc/pom.xml | 60 ++++
.../org/apache/shenyu/plugin/brpc/BrpcPlugin.java | 112 +++++++
.../plugin/brpc/cache/ApplicationConfigCache.java | 353 +++++++++++++++++++++
.../brpc/context/BrpcShenyuContextDecorator.java | 43 +++
.../brpc/exception/ShenyuBrpcPluginException.java | 38 +++
.../plugin/brpc/handler/BrpcMetaDataHandler.java | 69 ++++
.../plugin/brpc/handler/BrpcPluginDataHandler.java | 57 ++++
.../shenyu/plugin/brpc/proxy/BrpcProxyService.java | 147 +++++++++
.../shenyu/plugin/brpc/util/ProxyInfoUtil.java | 178 +++++++++++
.../apache/shenyu/plugin/brpc/BrpcPluginTest.java | 107 +++++++
.../brpc/cache/ApplicationConfigCacheTest.java | 101 ++++++
.../context/BrpcShenyuContextDecoratorTest.java | 57 ++++
.../brpc/handler/BrpcPluginDataHandlerTest.java | 52 +++
.../shenyu/plugin/brpc/util/ProxyInfoUtilTest.java | 81 +++++
.../plugin/context/path/ContextPathPlugin.java | 3 +-
.../plugin/response/strategy/RPCMessageWriter.java | 2 +-
.../shenyu/plugin/rewrite/RewritePlugin.java | 3 +-
22 files changed, 1655 insertions(+), 4 deletions(-)
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
index 55052d52d..e45485890 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
@@ -82,6 +82,11 @@ public interface Constants {
*/
String MOTAN_RPC_RESULT_EMPTY = "motan has not return value!";
+ /**
+ * The constant BRPC_RPC_RESULT_EMPTY.
+ */
+ String BRPC_RPC_RESULT_EMPTY = "brpc has not return value!";
+
/**
* The constant CLIENT_RESPONSE_RESULT_TYPE.
*/
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/plugin/BrpcRegisterConfig.java b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/plugin/BrpcRegisterConfig.java
new file mode 100644
index 000000000..a97c56107
--- /dev/null
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/plugin/BrpcRegisterConfig.java
@@ -0,0 +1,183 @@
+/*
+ * 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.apache.shenyu.common.dto.convert.plugin;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * The type brpc register config.
+ */
+public class BrpcRegisterConfig implements Serializable {
+
+ private static final long serialVersionUID = -1124348422759120146L;
+
+ private String address;
+
+ private Integer port;
+
+ private String threadpool;
+
+ private Integer corethreads;
+
+ private Integer threads;
+
+ private Integer queues;
+
+
+ /**
+ * get address.
+ *
+ * @return address
+ */
+ public String getAddress() {
+ return address;
+ }
+
+ /**
+ * set address.
+ *
+ * @param address address
+ */
+ public void setAddress(final String address) {
+ this.address = address;
+ }
+
+ /**
+ * get port.
+ *
+ * @return port
+ */
+ public Integer getPort() {
+ return port;
+ }
+
+ /**
+ * set port.
+ *
+ * @param port port
+ */
+ public void setPort(final Integer port) {
+ this.port = port;
+ }
+
+ /**
+ * get threadpool.
+ *
+ * @return threadpool
+ */
+ public String getThreadpool() {
+ return threadpool;
+ }
+
+ /**
+ * set threadpool.
+ *
+ * @param threadpool threadpool
+ */
+ public void setThreadpool(final String threadpool) {
+ this.threadpool = threadpool;
+ }
+
+ /**
+ * get corethreads.
+ *
+ * @return corethreads
+ */
+ public Integer getCorethreads() {
+ return corethreads;
+ }
+
+ /**
+ * set corethreads.
+ *
+ * @param corethreads corethreads
+ */
+ public void setCorethreads(final Integer corethreads) {
+ this.corethreads = corethreads;
+ }
+
+ /**
+ * get threads.
+ *
+ * @return threads
+ */
+ public Integer getThreads() {
+ return threads;
+ }
+
+ /**
+ * set threads.
+ *
+ * @param threads threads
+ */
+ public void setThreads(final Integer threads) {
+ this.threads = threads;
+ }
+
+ /**
+ * get queues.
+ *
+ * @return queues
+ */
+ public Integer getQueues() {
+ return queues;
+ }
+
+ /**
+ * set queues.
+ *
+ * @param queues queues
+ */
+ public void setQueues(final Integer queues) {
+ this.queues = queues;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ BrpcRegisterConfig that = (BrpcRegisterConfig) o;
+ return Objects.equals(address, that.address) && Objects.equals(port, that.port)
+ && Objects.equals(threadpool, that.threadpool) && Objects.equals(corethreads, that.corethreads)
+ && Objects.equals(threads, that.threads) && Objects.equals(queues, that.queues);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address, port, threadpool, corethreads, threads, queues);
+ }
+
+ @Override
+ public String toString() {
+ return "BrpcRegisterConfig{"
+ + "address='" + address
+ + '\''
+ + ", port=" + port
+ + ", threadpool='" + threadpool
+ + '\''
+ + ", corethreads=" + corethreads
+ + ", threads=" + threads
+ + ", queues=" + queues
+ + '}';
+ }
+}
diff --git a/shenyu-plugin/pom.xml b/shenyu-plugin/pom.xml
index 46bfd1fcb..de6994057 100644
--- a/shenyu-plugin/pom.xml
+++ b/shenyu-plugin/pom.xml
@@ -64,5 +64,6 @@
<module>shenyu-plugin-mock</module>
<module>shenyu-plugin-casdoor</module>
<module>shenyu-plugin-key-auth</module>
+ <module>shenyu-plugin-brpc</module>
</modules>
</project>
diff --git a/shenyu-plugin/shenyu-plugin-api/src/main/java/org/apache/shenyu/plugin/api/result/ShenyuResultEnum.java b/shenyu-plugin/shenyu-plugin-api/src/main/java/org/apache/shenyu/plugin/api/result/ShenyuResultEnum.java
index b0d76cbb7..eafff3621 100644
--- a/shenyu-plugin/shenyu-plugin-api/src/main/java/org/apache/shenyu/plugin/api/result/ShenyuResultEnum.java
+++ b/shenyu-plugin/shenyu-plugin-api/src/main/java/org/apache/shenyu/plugin/api/result/ShenyuResultEnum.java
@@ -107,6 +107,10 @@ public enum ShenyuResultEnum {
*/
MOTAN_HAVE_BODY_PARAM(437, "Motan must have body param, please enter the JSON format in the body!"),
+ /**
+ * Brpc have body param shenyu result enum.
+ */
+ BRPC_HAVE_BODY_PARAM(438, "Brpc must have body param, please enter the JSON format in the body!"),
/**
* full selector type enum.
diff --git a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/RpcParamTransformPlugin.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/RpcParamTransformPlugin.java
index fd5b01edd..c40263070 100644
--- a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/RpcParamTransformPlugin.java
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/RpcParamTransformPlugin.java
@@ -113,7 +113,8 @@ public class RpcParamTransformPlugin implements ShenyuPlugin {
RpcTypeEnum.GRPC,
RpcTypeEnum.TARS,
RpcTypeEnum.MOTAN,
- RpcTypeEnum.SOFA);
+ RpcTypeEnum.SOFA,
+ RpcTypeEnum.BRPC);
}
@NonNull
diff --git a/shenyu-plugin/shenyu-plugin-brpc/pom.xml b/shenyu-plugin/shenyu-plugin-brpc/pom.xml
new file mode 100644
index 000000000..f0cf7e107
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/pom.xml
@@ -0,0 +1,60 @@
+<?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>
+ <groupId>org.apache.shenyu</groupId>
+ <artifactId>shenyu-plugin</artifactId>
+ <version>2.5.1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>shenyu-plugin-brpc</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shenyu</groupId>
+ <artifactId>shenyu-plugin-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.baidu.cloud</groupId>
+ <artifactId>spring-cloud-starter-baidu-starlight</artifactId>
+ <version>${brpc.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.cloud</groupId>
+ <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+ <version>${spring-cloud.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/BrpcPlugin.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/BrpcPlugin.java
new file mode 100644
index 000000000..33847e4d1
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/BrpcPlugin.java
@@ -0,0 +1,112 @@
+/*
+ * 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.apache.shenyu.plugin.brpc;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.plugin.api.ShenyuPluginChain;
+import org.apache.shenyu.plugin.api.context.ShenyuContext;
+import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
+import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
+import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
+import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
+import org.apache.shenyu.plugin.brpc.proxy.BrpcProxyService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.Objects;
+
+/**
+ * The type brpc plugin.
+ */
+public class BrpcPlugin extends AbstractShenyuPlugin {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BrpcPlugin.class);
+
+ private final BrpcProxyService brpcProxyService;
+
+ /**
+ * Instantiates a new brpc plugin.
+ *
+ * @param brpcProxyService the brpc proxy service
+ */
+ public BrpcPlugin(final BrpcProxyService brpcProxyService) {
+ this.brpcProxyService = brpcProxyService;
+ }
+
+ @Override
+ protected Mono<Void> doExecute(final ServerWebExchange exchange, final ShenyuPluginChain chain, final SelectorData selector, final RuleData rule) {
+ String param = exchange.getAttribute(Constants.PARAM_TRANSFORM);
+ ShenyuContext shenyuContext = exchange.getAttribute(Constants.CONTEXT);
+ assert shenyuContext != null;
+ MetaData metaData = exchange.getAttribute(Constants.META_DATA);
+ if (!checkMetaData(metaData)) {
+ assert metaData != null;
+ LOG.error("path is :{}, meta data have error.... {}", shenyuContext.getPath(), metaData);
+ exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
+ Object error = ShenyuResultWrap.error(exchange, ShenyuResultEnum.META_DATA_ERROR);
+ return WebFluxResultUtils.result(exchange, error);
+ }
+ if (StringUtils.isNoneBlank(metaData.getParameterTypes()) && StringUtils.isBlank(param)) {
+ exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
+ Object error = ShenyuResultWrap.error(exchange, ShenyuResultEnum.BRPC_HAVE_BODY_PARAM);
+ return WebFluxResultUtils.result(exchange, error);
+ }
+ final Mono<Object> result = brpcProxyService.genericInvoker(param, metaData, exchange);
+ return result.then(chain.execute(exchange));
+ }
+
+ @Override
+ public int getOrder() {
+ return PluginEnum.BRPC.getCode();
+ }
+
+ @Override
+ public String named() {
+ return PluginEnum.BRPC.getName();
+ }
+
+ @Override
+ public boolean skip(final ServerWebExchange exchange) {
+ return skipExcept(exchange, RpcTypeEnum.BRPC);
+ }
+
+ @Override
+ protected Mono<Void> handleSelectorIfNull(final String pluginName, final ServerWebExchange exchange, final ShenyuPluginChain chain) {
+ return WebFluxResultUtils.noSelectorResult(pluginName, exchange);
+ }
+
+ @Override
+ protected Mono<Void> handleRuleIfNull(final String pluginName, final ServerWebExchange exchange, final ShenyuPluginChain chain) {
+ return WebFluxResultUtils.noRuleResult(pluginName, exchange);
+ }
+
+ private boolean checkMetaData(final MetaData metaData) {
+ return Objects.nonNull(metaData)
+ && StringUtils.isNoneBlank(metaData.getMethodName())
+ && StringUtils.isNoneBlank(metaData.getServiceName());
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/cache/ApplicationConfigCache.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/cache/ApplicationConfigCache.java
new file mode 100644
index 000000000..e130fff42
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/cache/ApplicationConfigCache.java
@@ -0,0 +1,353 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.cache;
+
+import com.baidu.cloud.starlight.api.rpc.StarlightClient;
+import com.baidu.cloud.starlight.api.rpc.config.ServiceConfig;
+import com.baidu.cloud.starlight.api.rpc.config.TransportConfig;
+import com.baidu.cloud.starlight.core.rpc.SingleStarlightClient;
+import com.baidu.cloud.starlight.core.rpc.generic.AsyncGenericService;
+import com.baidu.cloud.starlight.core.rpc.proxy.JDKProxyFactory;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.convert.plugin.BrpcRegisterConfig;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.brpc.exception.ShenyuBrpcPluginException;
+import org.apache.shenyu.plugin.brpc.util.ProxyInfoUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.lang.NonNull;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Brpc config cache.
+ */
+public final class ApplicationConfigCache {
+
+ /**
+ * The constant PARAM_MAP.
+ */
+ public static final ConcurrentMap<String, BrpcParamInfo> PARAM_MAP = new ConcurrentHashMap<>();
+
+ private static final String BRPC_PROTOCOL = "brpc";
+
+ private static final Logger LOG = LoggerFactory.getLogger(ApplicationConfigCache.class);
+
+ private StarlightClient clientConfig;
+
+ private JDKProxyFactory proxyFactory;
+
+ private final LoadingCache<String, AsyncGenericService> cache = CacheBuilder.newBuilder()
+ .maximumSize(Constants.CACHE_MAX_COUNT)
+ .build(new CacheLoader<String, AsyncGenericService>() {
+ @Override
+ public AsyncGenericService load(@NonNull final String key) {
+ return null;
+ }
+ });
+
+ private ApplicationConfigCache() {
+ }
+
+ /**
+ * init service.
+ *
+ * @param metaData the meta data
+ * @return service
+ */
+ public AsyncGenericService initService(final MetaData metaData) {
+ try {
+ AsyncGenericService service = cache.get(metaData.getPath());
+ if (Objects.nonNull(service)) {
+ return service;
+ }
+ } catch (Exception e) {
+ LOG.warn("init brpc ref ex:{}", e.getMessage());
+ }
+ return build(metaData);
+ }
+
+ /**
+ * init brpc config.
+ *
+ * @param brpcRegisterConfig the config of brpc
+ */
+ public void init(final BrpcRegisterConfig brpcRegisterConfig) {
+ if (Objects.isNull(clientConfig)) {
+ TransportConfig config = new TransportConfig();
+ clientConfig = new SingleStarlightClient(brpcRegisterConfig.getAddress(), brpcRegisterConfig.getPort(), config);
+ clientConfig.init();
+ proxyFactory = new JDKProxyFactory();
+ }
+ }
+
+ /**
+ * Build service.
+ *
+ * @param metaData the meta data
+ * @return service
+ */
+ public AsyncGenericService build(final MetaData metaData) {
+ if (Objects.isNull(clientConfig)) {
+ throw new UnsupportedOperationException("unsupport!!");
+ }
+ ServiceConfig serviceConfig = new ServiceConfig();
+ serviceConfig.setProtocol(BRPC_PROTOCOL);
+ serviceConfig.setServiceId(metaData.getServiceName());
+
+ BrpcParamExtInfo brpcParamExtInfo =
+ GsonUtils.getInstance().fromJson(metaData.getRpcExt(), BrpcParamExtInfo.class);
+ brpcParamExtInfo.getMethodInfo().forEach(methodInfo -> {
+ if (CollectionUtils.isNotEmpty(methodInfo.getParamTypes())) {
+ try {
+ Class<?>[] paramTypes = new Class[methodInfo.getParamTypes().size()];
+ String[] paramNames = new String[methodInfo.getParamTypes().size()];
+ for (int i = 0; i < methodInfo.getParamTypes().size(); i++) {
+ Pair<String, String> pair = methodInfo.getParamTypes().get(i);
+ paramTypes[i] = ProxyInfoUtil.getParamClass(pair.getKey());
+ paramNames[i] = pair.getValue();
+ PARAM_MAP.put(methodInfo.getMethodName(), new BrpcParamInfo(paramTypes, paramNames));
+ }
+ } catch (Exception e) {
+ LOG.error("failed to init brpc, {}", e.getMessage());
+ throw new ShenyuBrpcPluginException(e.getCause());
+ }
+ }
+ });
+ AsyncGenericService service = proxyFactory.getProxy(AsyncGenericService.class, serviceConfig, clientConfig);
+ cache.put(metaData.getPath(), service);
+ return service;
+ }
+
+ /**
+ * Get service.
+ *
+ * @param path path
+ * @return the service
+ */
+ public AsyncGenericService get(final String path) {
+ try {
+ return cache.get(path);
+ } catch (ExecutionException e) {
+ throw new ShenyuBrpcPluginException(e.getCause());
+ }
+ }
+
+ /**
+ * Invalidate.
+ *
+ * @param path the path name
+ */
+ public void invalidate(final String path) {
+ cache.invalidate(path);
+ }
+
+ /**
+ * Invalidate all.
+ */
+ public void invalidateAll() {
+ cache.invalidateAll();
+ }
+
+ /**
+ * Get param info key.
+ *
+ * @param className className
+ * @param methodName methodName
+ * @return the key
+ */
+ public static String getClassMethodKey(final String className, final String methodName) {
+ return String.join("_", className, methodName);
+ }
+
+ /**
+ * Gets the client config.
+ *
+ * @return the client config
+ */
+ public StarlightClient getClientConfig() {
+ return clientConfig;
+ }
+
+ /**
+ * Gets the proxy factory.
+ *
+ * @return the proxy factory
+ */
+ public JDKProxyFactory getProxyFactory() {
+ return proxyFactory;
+ }
+
+ /**
+ * Gets instance.
+ *
+ * @return the instance
+ */
+ public static ApplicationConfigCache getInstance() {
+ return ApplicationConfigCacheInstance.INSTANCE;
+ }
+
+ /**
+ * The type Application config cache instance.
+ */
+ static final class ApplicationConfigCacheInstance {
+
+ /**
+ * The Instance.
+ */
+ static final ApplicationConfigCache INSTANCE = new ApplicationConfigCache();
+
+ private ApplicationConfigCacheInstance() {
+
+ }
+ }
+
+ /**
+ * The type Brpc param ext info.
+ */
+ public static class MethodInfo {
+
+ private String methodName;
+
+ private List<Pair<String, String>> paramTypes;
+
+ /**
+ * Gets method name.
+ *
+ * @return the method name
+ */
+ public String getMethodName() {
+ return methodName;
+ }
+
+ /**
+ * Sets method name.
+ *
+ * @param methodName the method name
+ */
+ public void setMethodName(final String methodName) {
+ this.methodName = methodName;
+ }
+
+
+ /**
+ * Gets paramTypes.
+ *
+ * @return the paramTypes
+ */
+ public List<Pair<String, String>> getParamTypes() {
+ return paramTypes;
+ }
+
+ /**
+ * Sets paramTypes.
+ *
+ * @param paramTypes the paramTypes
+ */
+ public void setParamTypes(final List<Pair<String, String>> paramTypes) {
+ this.paramTypes = paramTypes;
+ }
+ }
+
+ /**
+ * The type Brpc param ext info.
+ */
+ public static class BrpcParamExtInfo {
+
+ private List<MethodInfo> methodInfo;
+
+ /**
+ * Gets method info.
+ *
+ * @return the method info
+ */
+ public List<MethodInfo> getMethodInfo() {
+ return methodInfo;
+ }
+
+ /**
+ * Sets method info.
+ *
+ * @param methodInfo the method info
+ */
+ public void setMethodInfo(final List<MethodInfo> methodInfo) {
+ this.methodInfo = methodInfo;
+ }
+ }
+
+ /**
+ * The type Brpc param ext info.
+ */
+ public static class BrpcParamInfo {
+
+ private Class<?>[] paramTypes;
+
+ private String[] paramNames;
+
+ BrpcParamInfo(final Class<?>[] paramTypes, final String[] paramNames) {
+ this.paramTypes = paramTypes;
+ this.paramNames = paramNames;
+ }
+
+ /**
+ * Get param types class [ ].
+ *
+ * @return the class [ ]
+ */
+ public Class<?>[] getParamTypes() {
+ return paramTypes;
+ }
+
+ /**
+ * Sets param types.
+ *
+ * @param paramTypes the param types
+ */
+ public void setParamTypes(final Class<?>[] paramTypes) {
+ this.paramTypes = paramTypes;
+ }
+
+ /**
+ * Get param names string [ ].
+ *
+ * @return the string [ ]
+ */
+ public String[] getParamNames() {
+ return paramNames;
+ }
+
+ /**
+ * Sets param names.
+ *
+ * @param paramNames the param names
+ */
+ public void setParamNames(final String[] paramNames) {
+ this.paramNames = paramNames;
+ }
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/context/BrpcShenyuContextDecorator.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/context/BrpcShenyuContextDecorator.java
new file mode 100644
index 000000000..49576693e
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/context/BrpcShenyuContextDecorator.java
@@ -0,0 +1,43 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.context;
+
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.plugin.api.context.ShenyuContext;
+import org.apache.shenyu.plugin.api.context.ShenyuContextDecorator;
+
+/**
+ * The type Brpc shenyu context decorator.
+ */
+public class BrpcShenyuContextDecorator implements ShenyuContextDecorator {
+
+ @Override
+ public ShenyuContext decorator(final ShenyuContext shenyuContext, final MetaData metaData) {
+ shenyuContext.setModule(metaData.getAppName());
+ shenyuContext.setMethod(metaData.getServiceName());
+ shenyuContext.setContextPath(metaData.getContextPath());
+ shenyuContext.setRpcType(RpcTypeEnum.BRPC.getName());
+ return shenyuContext;
+ }
+
+ @Override
+ public String rpcType() {
+ return RpcTypeEnum.BRPC.getName();
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/exception/ShenyuBrpcPluginException.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/exception/ShenyuBrpcPluginException.java
new file mode 100644
index 000000000..58af8692f
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/exception/ShenyuBrpcPluginException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.exception;
+
+import org.apache.shenyu.common.exception.ShenyuException;
+
+/**
+ * ShenyuBrpcPluginException.
+ */
+public class ShenyuBrpcPluginException extends ShenyuException {
+
+ public ShenyuBrpcPluginException(final Throwable e) {
+ super(e);
+ }
+
+ public ShenyuBrpcPluginException(final String message) {
+ super(message);
+ }
+
+ public ShenyuBrpcPluginException(final String message, final Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/handler/BrpcMetaDataHandler.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/handler/BrpcMetaDataHandler.java
new file mode 100644
index 000000000..233097eda
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/handler/BrpcMetaDataHandler.java
@@ -0,0 +1,69 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.handler;
+
+import com.google.common.collect.Maps;
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.plugin.base.handler.MetaDataHandler;
+import org.apache.shenyu.plugin.brpc.cache.ApplicationConfigCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * The brpc metadata handler.
+ */
+public class BrpcMetaDataHandler implements MetaDataHandler {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BrpcMetaDataHandler.class);
+
+ private static final ConcurrentMap<String, MetaData> META_DATA = Maps.newConcurrentMap();
+
+ @Override
+ public void handle(final MetaData metaData) {
+ try {
+ MetaData exist = META_DATA.get(metaData.getPath());
+ if (Objects.isNull(exist) || Objects.isNull(ApplicationConfigCache.getInstance().get(exist.getPath()))) {
+ // The first initialization
+ ApplicationConfigCache.getInstance().initService(metaData);
+ } else {
+ if (!exist.getServiceName().equals(metaData.getServiceName()) || !exist.getRpcExt().equals(metaData.getRpcExt())) {
+ // update
+ ApplicationConfigCache.getInstance().build(metaData);
+ }
+ }
+ META_DATA.put(metaData.getPath(), metaData);
+ } catch (Exception e) {
+ LOG.error("brpc sync metadata is error, please check brpc service. MetaData: [{}]", metaData, e);
+ }
+ }
+
+ @Override
+ public void remove(final MetaData metaData) {
+ ApplicationConfigCache.getInstance().invalidate(metaData.getPath());
+ META_DATA.remove(metaData.getPath());
+ }
+
+ @Override
+ public String rpcType() {
+ return RpcTypeEnum.BRPC.getName();
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/handler/BrpcPluginDataHandler.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/handler/BrpcPluginDataHandler.java
new file mode 100644
index 000000000..56704ee98
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/handler/BrpcPluginDataHandler.java
@@ -0,0 +1,57 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.handler;
+
+import org.apache.shenyu.common.dto.convert.plugin.BrpcRegisterConfig;
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
+import org.apache.shenyu.common.utils.Singleton;
+import org.apache.shenyu.plugin.brpc.cache.ApplicationConfigCache;
+
+import java.util.Objects;
+
+/**
+ * The type brpc plugin data handler.
+ */
+public class BrpcPluginDataHandler implements PluginDataHandler {
+
+ @Override
+ public void handlerPlugin(final PluginData pluginData) {
+ if (null != pluginData && pluginData.getEnabled()) {
+ BrpcRegisterConfig brpcRegisterConfig = GsonUtils.getInstance().fromJson(pluginData.getConfig(), BrpcRegisterConfig.class);
+ BrpcRegisterConfig exist = Singleton.INST.get(BrpcRegisterConfig.class);
+ if (Objects.isNull(brpcRegisterConfig)) {
+ return;
+ }
+ if (Objects.isNull(exist) || !brpcRegisterConfig.equals(exist)) {
+ // If it is null, initialize it
+ ApplicationConfigCache.getInstance().init(brpcRegisterConfig);
+ ApplicationConfigCache.getInstance().invalidateAll();
+ }
+ Singleton.INST.single(BrpcRegisterConfig.class, brpcRegisterConfig);
+ }
+ }
+
+ @Override
+ public String pluginNamed() {
+ return PluginEnum.BRPC.getName();
+ }
+
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/proxy/BrpcProxyService.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/proxy/BrpcProxyService.java
new file mode 100644
index 000000000..2c6bdef40
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/proxy/BrpcProxyService.java
@@ -0,0 +1,147 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.proxy;
+
+import com.baidu.cloud.starlight.core.rpc.generic.AsyncGenericService;
+import org.apache.shenyu.common.concurrent.ShenyuThreadFactory;
+import org.apache.shenyu.common.concurrent.ShenyuThreadPoolExecutor;
+import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.convert.plugin.BrpcRegisterConfig;
+import org.apache.shenyu.common.enums.ResultEnum;
+import org.apache.shenyu.common.exception.ShenyuException;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.Singleton;
+import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
+import org.apache.shenyu.plugin.brpc.cache.ApplicationConfigCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Brpc proxy service.
+ */
+public class BrpcProxyService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BrpcProxyService.class);
+
+ private final ThreadFactory factory = ShenyuThreadFactory.create("shenyu-brpc", true);
+
+ private ExecutorService threadPool;
+
+ /**
+ * Generic invoker object.
+ *
+ * @param body the body
+ * @param metaData the meta data
+ * @param exchange the exchange
+ * @return the object
+ * @throws ShenyuException the shenyu exception
+ */
+ @SuppressWarnings("all")
+ public Mono<Object> genericInvoker(final String body, final MetaData metaData, final ServerWebExchange exchange) throws ShenyuException {
+ ApplicationConfigCache.BrpcParamInfo brpcParamInfo = ApplicationConfigCache.PARAM_MAP.get(metaData.getMethodName());
+ Object[] params;
+ if (Objects.isNull(brpcParamInfo)) {
+ params = new Object[0];
+ } else {
+ int num = brpcParamInfo.getParamTypes().length;
+ params = new Object[num];
+ Map<String, Object> bodyMap = GsonUtils.getInstance().convertToMap(body);
+ for (int i = 0; i < num; i++) {
+ params[i] = bodyMap.get(brpcParamInfo.getParamNames()[i]).toString();
+ }
+ }
+ initThreadPool();
+ CompletableFuture<Object> future = null;
+ future = new CompletableFuture<>().supplyAsync(() -> getValue(metaData, params), threadPool);
+ return Mono.fromFuture(future.thenApply(ret -> {
+ if (Objects.isNull(ret)) {
+ ret = Constants.BRPC_RPC_RESULT_EMPTY;
+ }
+ exchange.getAttributes().put(Constants.RPC_RESULT, ret);
+ exchange.getAttributes().put(Constants.CLIENT_RESPONSE_RESULT_TYPE, ResultEnum.SUCCESS.getName());
+ return ret;
+ })).onErrorMap(ShenyuException::new);
+ }
+
+ private Map<String, String> getValue(final MetaData metaData, final Object[] params) {
+ try {
+ AsyncGenericService service = ApplicationConfigCache.getInstance().get(metaData.getPath());
+ if (Objects.isNull(service)) {
+ ApplicationConfigCache.getInstance().invalidate(metaData.getPath());
+ service = ApplicationConfigCache.getInstance().initService(metaData);
+ }
+ Map<String, String> result = (Map<String, String>) service.$invokeFuture(metaData.getMethodName(), params).get();
+ return result;
+ } catch (Exception e) {
+ LOG.error("Exception caught in BrpcProxyService#genericInvoker.", e);
+ return null;
+ }
+ }
+
+ private void initThreadPool() {
+ if (Objects.nonNull(threadPool)) {
+ return;
+ }
+ BrpcRegisterConfig config = Singleton.INST.get(BrpcRegisterConfig.class);
+ if (Objects.isNull(config)) {
+ // should not execute to here
+ threadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+ 60L, TimeUnit.SECONDS,
+ new SynchronousQueue<Runnable>(),
+ factory);
+ return;
+ }
+ final String threadpool = Optional.ofNullable(config.getThreadpool()).orElse(Constants.CACHED);
+ switch (threadpool) {
+ case Constants.SHARED:
+ try {
+ threadPool = SpringBeanUtils.getInstance().getBean(ShenyuThreadPoolExecutor.class);
+ return;
+ } catch (NoSuchBeanDefinitionException t) {
+ throw new ShenyuException("shared thread pool is not enable, config ${shenyu.sharedPool.enable} in your xml/yml !", t);
+ }
+ case Constants.FIXED:
+ case Constants.EAGER:
+ case Constants.LIMITED:
+ throw new UnsupportedOperationException();
+ case Constants.CACHED:
+ default:
+ int corePoolSize = Optional.ofNullable(config.getCorethreads()).orElse(0);
+ int maximumPoolSize = Optional.ofNullable(config.getThreads()).orElse(Integer.MAX_VALUE);
+ int queueSize = Optional.ofNullable(config.getQueues()).orElse(0);
+ threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 60L, TimeUnit.SECONDS,
+ queueSize > 0 ? new LinkedBlockingQueue<>(queueSize) : new SynchronousQueue<>(), factory);
+ }
+ }
+
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/util/ProxyInfoUtil.java b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/util/ProxyInfoUtil.java
new file mode 100644
index 000000000..a8bcb3363
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/main/java/org/apache/shenyu/plugin/brpc/util/ProxyInfoUtil.java
@@ -0,0 +1,178 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.util;
+
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.utils.GsonUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * Proxy info util.
+ */
+public final class ProxyInfoUtil {
+
+ private static final Map<String, PrimitiveType> PRIMITIVE_TYPE;
+
+ static {
+ PRIMITIVE_TYPE = new HashMap<>();
+ PRIMITIVE_TYPE.put("int", new PrimitiveType(int.class, o -> {
+ if (o instanceof String) {
+ return Integer.valueOf((String) o);
+ }
+ return ((Long) o).intValue();
+ }));
+ PRIMITIVE_TYPE.put("double", new PrimitiveType(double.class, o -> {
+ if (o instanceof String) {
+ return Double.valueOf((String) o);
+ }
+ return o;
+ }));
+ PRIMITIVE_TYPE.put("long", new PrimitiveType(long.class, o -> {
+ if (o instanceof String) {
+ return Long.valueOf((String) o);
+ }
+ return o;
+ }));
+ PRIMITIVE_TYPE.put("short", new PrimitiveType(short.class, o -> {
+ if (o instanceof String) {
+ return Short.valueOf((String) o);
+ }
+ return ((Long) o).shortValue();
+ }));
+ PRIMITIVE_TYPE.put("byte", new PrimitiveType(byte.class, o -> {
+ if (o instanceof String) {
+ return Byte.valueOf((String) o);
+ }
+ return ((Long) o).byteValue();
+ }));
+ PRIMITIVE_TYPE.put("boolean", new PrimitiveType(boolean.class, o -> {
+ if (o instanceof String) {
+ return Byte.valueOf((String) o);
+ }
+ return o;
+ }));
+ PRIMITIVE_TYPE.put("char", new PrimitiveType(char.class, o -> {
+ if (o instanceof String) {
+ return String.valueOf(o).charAt(0);
+ }
+ return o;
+ }));
+ PRIMITIVE_TYPE.put("float", new PrimitiveType(float.class, o -> {
+ if (o instanceof String) {
+ return Float.valueOf((String) o);
+ }
+ return ((Double) o).floatValue();
+ }));
+ }
+
+ private ProxyInfoUtil() {
+ }
+
+ /**
+ * Get class type by name.
+ *
+ * @param className className
+ * @return the type to invoke
+ * @throws ClassNotFoundException ClassNotFoundException
+ */
+ public static Class<?> getParamClass(final String className) throws ClassNotFoundException {
+ if (PRIMITIVE_TYPE.containsKey(className)) {
+ return PRIMITIVE_TYPE.get(className).getClazz();
+ } else {
+ return Class.forName(className);
+ }
+ }
+
+ /**
+ * Get proxy class name to get brpc proxy.
+ *
+ * @param metaData metaData
+ * @return className
+ */
+ public static String getProxyName(final MetaData metaData) {
+ return metaData.getPath().replace("/", "") + metaData.getMethodName() + "Proxy";
+ }
+
+ /**
+ * Get methodName to get brpc proxy.
+ *
+ * @param methodName methodName
+ * @return methodName
+ */
+ public static String getMethodName(final String methodName) {
+ return methodName;
+ }
+
+ /**
+ * Get objectName to get brpc proxy.
+ *
+ * @param upstreamUrl upstream url
+ * @param serviceName service name
+ * @return objectName
+ */
+ public static String getObjectName(final String upstreamUrl, final String serviceName) {
+ String[] ipAndPort = upstreamUrl.split(":");
+ return serviceName + "@tcp -h " + ipAndPort[0] + " -p " + ipAndPort[1];
+ }
+
+ /**
+ * Get param to invoke brpc server.
+ *
+ * @param paramTypes paramTypes
+ * @param paramNames paramNames
+ * @param body body
+ * @return the param to invoke
+ */
+ public static Object[] getParamArray(final Class<?>[] paramTypes, final String[] paramNames, final String body) {
+ Map<String, Object> bodyMap = GsonUtils.getInstance().convertToMap(body);
+ Object[] param = new Object[paramNames.length];
+ for (int i = 0; i < paramNames.length; i++) {
+ String paramName = paramNames[i];
+ Class<?> paramType = paramTypes[i];
+ if (PRIMITIVE_TYPE.containsKey(paramType.getName())) {
+ param[i] = PRIMITIVE_TYPE.get(paramType.getName()).getFunc().apply(bodyMap.get(paramName));
+ } else {
+ param[i] = bodyMap.get(paramName);
+ }
+ }
+ return param;
+ }
+
+ static class PrimitiveType {
+
+ private final Class<?> clazz;
+
+ private final Function<Object, Object> func;
+
+ PrimitiveType(final Class<?> clazz, final Function<Object, Object> func) {
+ this.clazz = clazz;
+ this.func = func;
+ }
+
+ public Class<?> getClazz() {
+ return clazz;
+ }
+
+ public Function<Object, Object> getFunc() {
+ return func;
+ }
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/BrpcPluginTest.java b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/BrpcPluginTest.java
new file mode 100644
index 000000000..bc4758581
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/BrpcPluginTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.apache.shenyu.plugin.brpc;
+
+import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.plugin.api.ShenyuPluginChain;
+import org.apache.shenyu.plugin.api.context.ShenyuContext;
+import org.apache.shenyu.plugin.brpc.proxy.BrpcProxyService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * The Test Case For {@link BrpcPlugin}.
+ */
+public class BrpcPluginTest {
+
+ private static final String PARAM = "{\"name\":\"brpc\"}";
+
+ private BrpcPlugin brpcPlugin;
+
+ private ShenyuPluginChain chain;
+
+ private SelectorData selectorData;
+
+ private ServerWebExchange exchange;
+
+ private RuleData ruleData;
+
+ private MetaData metaData;
+
+ private BrpcProxyService brpcProxyService;
+
+ @BeforeEach
+ public void setUp() {
+ this.ruleData = mock(RuleData.class);
+ this.chain = mock(ShenyuPluginChain.class);
+ this.selectorData = mock(SelectorData.class);
+ this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("localhost").build());
+ this.metaData = new MetaData();
+ this.metaData.setAppName("brpc");
+ this.metaData.setContextPath("/brpc");
+ this.metaData.setPath("/brpc/hello");
+ this.metaData.setRpcType("brpc");
+ this.metaData.setServiceName("org.apache.shenyu.examples.brpc.service.DemoService");
+ this.metaData.setMethodName("hello");
+ this.metaData.setParameterTypes("java.lang.String");
+ this.metaData.setEnabled(true);
+ metaData.setRpcExt("{\"methodInfo\":[{\"methodName\":\"hello\",\"params\":[{\"left\":\"java.lang.String\",\"right\":\"name\"}]}]}");
+ ShenyuContext shenyuContext = mock(ShenyuContext.class);
+ exchange.getAttributes().put(Constants.CONTEXT, shenyuContext);
+ exchange.getAttributes().put(Constants.PARAM_TRANSFORM, PARAM);
+ exchange.getAttributes().put(Constants.META_DATA, metaData);
+ this.brpcProxyService = mock(BrpcProxyService.class);
+ when(brpcProxyService.genericInvoker(PARAM, metaData, exchange)).thenReturn(Mono.empty());
+ this.brpcPlugin = new BrpcPlugin(brpcProxyService);
+ }
+
+ @Test
+ public void testDoExecute() {
+ when(chain.execute(exchange)).thenReturn(Mono.empty());
+ Mono<Void> result = brpcPlugin.doExecute(exchange, chain, selectorData, ruleData);
+ StepVerifier.create(result).expectSubscription().verifyComplete();
+ }
+
+ @Test
+ public void testNamed() {
+ Assertions.assertEquals(brpcPlugin.named(), "brpc");
+ }
+
+ @Test
+ public void testSkip() {
+ final boolean result = brpcPlugin.skip(exchange);
+ Assertions.assertTrue(result);
+ }
+
+ @Test
+ public void testGetOrder() {
+ Assertions.assertEquals(brpcPlugin.getOrder(), 310);
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/cache/ApplicationConfigCacheTest.java b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/cache/ApplicationConfigCacheTest.java
new file mode 100644
index 000000000..894272dfa
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/cache/ApplicationConfigCacheTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.cache;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.dto.convert.plugin.BrpcRegisterConfig;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Test case for {@link ApplicationConfigCache}.
+ */
+public final class ApplicationConfigCacheTest {
+
+ private ApplicationConfigCache applicationConfigCacheUnderTest;
+
+ @BeforeEach
+ public void setUp() {
+ applicationConfigCacheUnderTest = ApplicationConfigCache.getInstance();
+ }
+
+ @Test
+ public void testGetClassMethodKey() {
+ assertEquals("className_methodName", ApplicationConfigCache.getClassMethodKey("className", "methodName"));
+ }
+
+ @Test
+ public void testGetInstance() {
+ assertNotNull(this.applicationConfigCacheUnderTest);
+ }
+
+ @Test
+ public void testMethodInfo() {
+ List<Pair<String, String>> params = new ArrayList<>();
+ Pair<String, String> pair = Pair.of("left", "right");
+ params.add(pair);
+ ApplicationConfigCache.MethodInfo methodInfo = new ApplicationConfigCache.MethodInfo();
+ methodInfo.setParamTypes(params);
+ Assertions.assertEquals(methodInfo.getParamTypes().get(0).getLeft(), "left");
+ }
+
+ @Test
+ public void testBrpcParamInfo() {
+ ApplicationConfigCache.BrpcParamInfo paramInfo = new ApplicationConfigCache.BrpcParamInfo(null, null);
+ paramInfo.setParamNames(new String[]{"test"});
+ paramInfo.setParamTypes(new Class<?>[]{ApplicationConfigCache.class});
+ Assertions.assertEquals(paramInfo.getParamNames()[0], "test");
+ Assertions.assertEquals(paramInfo.getParamTypes()[0], ApplicationConfigCache.class);
+ }
+
+ @Test
+ public void testBrpcParamExtInfo() {
+ ApplicationConfigCache.BrpcParamExtInfo paramExtInfo = new ApplicationConfigCache.BrpcParamExtInfo();
+ ApplicationConfigCache.MethodInfo methodInfo = new ApplicationConfigCache.MethodInfo();
+ methodInfo.setMethodName("methodName");
+ List<ApplicationConfigCache.MethodInfo> list = new ArrayList<>();
+ list.add(methodInfo);
+ paramExtInfo.setMethodInfo(list);
+ Assertions.assertEquals(paramExtInfo.getMethodInfo().get(0).getMethodName(), "methodName");
+ }
+
+ @Test
+ public void testApplicationConfigCache() {
+ ApplicationConfigCache applicationConfigCache = ApplicationConfigCache.getInstance();
+ Assertions.assertEquals(applicationConfigCache.getInstance().getClass(), ApplicationConfigCache.class);
+ PluginData pluginData = new PluginData();
+ pluginData.setEnabled(true);
+ pluginData.setConfig("{\"address\" : \"127.0.0.1\", \"port\" : \"8005\"}");
+ BrpcRegisterConfig registerConfig = GsonUtils.getInstance().fromJson(pluginData.getConfig(), BrpcRegisterConfig.class);
+ applicationConfigCache.init(registerConfig);
+ Assertions.assertNotNull(applicationConfigCache.getClientConfig());
+ Assertions.assertNotNull(applicationConfigCache.getProxyFactory());
+ Assertions.assertTrue(applicationConfigCache.getClientConfig().isActive());
+ applicationConfigCache.getClientConfig().destroy();
+ Assertions.assertFalse(applicationConfigCache.getClientConfig().isActive());
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/context/BrpcShenyuContextDecoratorTest.java b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/context/BrpcShenyuContextDecoratorTest.java
new file mode 100644
index 000000000..385086935
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/context/BrpcShenyuContextDecoratorTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.context;
+
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.plugin.api.context.ShenyuContext;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * The Test Case For {@link BrpcShenyuContextDecorator}.
+ */
+public final class BrpcShenyuContextDecoratorTest {
+
+ private BrpcShenyuContextDecorator brpcShenyuContextDecorator;
+
+ private ShenyuContext shenyuContext;
+
+ private MetaData metaData;
+
+ @BeforeEach
+ public void setUp() {
+ this.brpcShenyuContextDecorator = new BrpcShenyuContextDecorator();
+ this.metaData = new MetaData();
+ this.shenyuContext = new ShenyuContext();
+ }
+
+ @Test
+ public void testDecorator() {
+ metaData.setAppName("app");
+ metaData.setServiceName("service");
+ metaData.setContextPath("localhost");
+ brpcShenyuContextDecorator.decorator(shenyuContext, metaData);
+ Assertions.assertEquals(shenyuContext.getModule(), "app");
+ }
+
+ @Test
+ public void testRpcType() {
+ Assertions.assertEquals(brpcShenyuContextDecorator.rpcType(), "brpc");
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/handler/BrpcPluginDataHandlerTest.java b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/handler/BrpcPluginDataHandlerTest.java
new file mode 100644
index 000000000..4c880064c
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/handler/BrpcPluginDataHandlerTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.handler;
+
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test case for {@link BrpcPluginDataHandler}.
+ */
+public final class BrpcPluginDataHandlerTest {
+
+ private BrpcPluginDataHandler brpcPluginDataHandlerUnderTest;
+
+ @BeforeEach
+ public void setUp() {
+ brpcPluginDataHandlerUnderTest = new BrpcPluginDataHandler();
+ }
+
+ @Test
+ public void testHandlerPlugin() {
+ final PluginData pluginData = new PluginData("id", "name", "config", "0", false);
+ brpcPluginDataHandlerUnderTest.handlerPlugin(pluginData);
+ assertTrue(pluginData.getName().endsWith("name"));
+ }
+
+ @Test
+ public void testPluginNamed() {
+ final String result = brpcPluginDataHandlerUnderTest.pluginNamed();
+ assertEquals(PluginEnum.BRPC.getName(), result);
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/util/ProxyInfoUtilTest.java b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/util/ProxyInfoUtilTest.java
new file mode 100644
index 000000000..73ff80e26
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-brpc/src/test/java/org/apache/shenyu/plugin/brpc/util/ProxyInfoUtilTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.apache.shenyu.plugin.brpc.util;
+
+import org.apache.shenyu.common.dto.MetaData;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * Test case for {@link ProxyInfoUtil}.
+ */
+@ExtendWith(MockitoExtension.class)
+public class ProxyInfoUtilTest {
+
+ @Test
+ public void testGetParamClass() throws Exception {
+ assertEquals(int.class, ProxyInfoUtil.getParamClass("int"));
+ assertEquals(long.class, ProxyInfoUtil.getParamClass("long"));
+ assertEquals(short.class, ProxyInfoUtil.getParamClass("short"));
+ assertEquals(byte.class, ProxyInfoUtil.getParamClass("byte"));
+ assertEquals(boolean.class, ProxyInfoUtil.getParamClass("boolean"));
+ assertEquals(char.class, ProxyInfoUtil.getParamClass("char"));
+ assertEquals(float.class, ProxyInfoUtil.getParamClass("float"));
+ assertEquals(Integer.class, ProxyInfoUtil.getParamClass("java.lang.Integer"));
+ }
+
+ @Test
+ public void testGetParamClassThrowsClassNotFoundException() throws Exception {
+ assertThrows(ClassNotFoundException.class, () -> {
+ ProxyInfoUtil.getParamClass("className");
+ });
+ }
+
+ @Test
+ public void testGetPrxName() {
+ final MetaData metaData = new MetaData("id", "appName", "contextPath", "/path",
+ "rpcType", "serviceName", "methodName", "parameterTypes",
+ "rpcExt", false);
+ final String result = ProxyInfoUtil.getProxyName(metaData);
+ assertEquals("pathmethodNameProxy", result);
+ }
+
+ @Test
+ public void testGetMethodName() {
+ assertEquals("methodName", ProxyInfoUtil.getMethodName("methodName"));
+ }
+
+ @Test
+ public void testGetObjectName() {
+ final String result = ProxyInfoUtil.getObjectName("127.0.0.1:8005", "serviceName");
+ assertEquals("serviceName@tcp -h 127.0.0.1 -p 8005", result);
+ }
+
+ @Test
+ public void testGetParamArray() {
+ assertArrayEquals(new Object[]{11, Double.valueOf("1.321321312"), Long.valueOf("131231312"), Short.valueOf("11"), Byte.valueOf("0"), false, 'a', 1.321321312F},
+ ProxyInfoUtil.getParamArray(new Class<?>[]{int.class, double.class, long.class, short.class, byte.class, boolean.class, char.class, float.class},
+ new String[]{"int", "double", "long", "short", "byte", "boolean", "char", "float"},
+ "{\"int\":11,\"double\":1.321321312,\"long\":131231312,\"short\":11,\"byte\":0,\"boolean\":false,\"char\":'a',\"float\":1.321321312}"));
+ }
+}
diff --git a/shenyu-plugin/shenyu-plugin-context-path/src/main/java/org/apache/shenyu/plugin/context/path/ContextPathPlugin.java b/shenyu-plugin/shenyu-plugin-context-path/src/main/java/org/apache/shenyu/plugin/context/path/ContextPathPlugin.java
index 0c19a3850..d93e3ff37 100644
--- a/shenyu-plugin/shenyu-plugin-context-path/src/main/java/org/apache/shenyu/plugin/context/path/ContextPathPlugin.java
+++ b/shenyu-plugin/shenyu-plugin-context-path/src/main/java/org/apache/shenyu/plugin/context/path/ContextPathPlugin.java
@@ -81,7 +81,8 @@ public class ContextPathPlugin extends AbstractShenyuPlugin {
RpcTypeEnum.GRPC,
RpcTypeEnum.TARS,
RpcTypeEnum.MOTAN,
- RpcTypeEnum.SOFA);
+ RpcTypeEnum.SOFA,
+ RpcTypeEnum.BRPC);
}
private ContextMappingRuleHandle buildRuleHandle(final RuleData rule) {
diff --git a/shenyu-plugin/shenyu-plugin-response/src/main/java/org/apache/shenyu/plugin/response/strategy/RPCMessageWriter.java b/shenyu-plugin/shenyu-plugin-response/src/main/java/org/apache/shenyu/plugin/response/strategy/RPCMessageWriter.java
index e893d511d..1dc7bc46c 100644
--- a/shenyu-plugin/shenyu-plugin-response/src/main/java/org/apache/shenyu/plugin/response/strategy/RPCMessageWriter.java
+++ b/shenyu-plugin/shenyu-plugin-response/src/main/java/org/apache/shenyu/plugin/response/strategy/RPCMessageWriter.java
@@ -58,6 +58,6 @@ public class RPCMessageWriter implements MessageWriter {
@Override
public List<String> supportTypes() {
return Lists.newArrayList(RpcTypeEnum.DUBBO.getName(), RpcTypeEnum.SOFA.getName(),
- RpcTypeEnum.GRPC.getName(), RpcTypeEnum.MOTAN.getName(), RpcTypeEnum.TARS.getName());
+ RpcTypeEnum.GRPC.getName(), RpcTypeEnum.MOTAN.getName(), RpcTypeEnum.TARS.getName(), RpcTypeEnum.BRPC.getName());
}
}
diff --git a/shenyu-plugin/shenyu-plugin-rewrite/src/main/java/org/apache/shenyu/plugin/rewrite/RewritePlugin.java b/shenyu-plugin/shenyu-plugin-rewrite/src/main/java/org/apache/shenyu/plugin/rewrite/RewritePlugin.java
index 9b5efb696..845516ff9 100644
--- a/shenyu-plugin/shenyu-plugin-rewrite/src/main/java/org/apache/shenyu/plugin/rewrite/RewritePlugin.java
+++ b/shenyu-plugin/shenyu-plugin-rewrite/src/main/java/org/apache/shenyu/plugin/rewrite/RewritePlugin.java
@@ -69,7 +69,8 @@ public class RewritePlugin extends AbstractShenyuPlugin {
RpcTypeEnum.GRPC,
RpcTypeEnum.TARS,
RpcTypeEnum.MOTAN,
- RpcTypeEnum.SOFA);
+ RpcTypeEnum.SOFA,
+ RpcTypeEnum.BRPC);
}
@Override