Merge pull request #1667 from mercyblitz/master

Dubbo Cloud Gateway
pull/1668/head
Mercy Ma 5 years ago committed by GitHub
commit f57743d957
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -18,7 +18,7 @@
<description>Spring Cloud Alibaba Dependencies</description>
<properties>
<revision>2.2.1.RELEASE</revision>
<revision>2.2.2-SNAPSHOT</revision>
<sentinel.version>1.7.2</sentinel.version>
<oss.version>3.1.0</oss.version>
<seata.version>1.3.0</seata.version>

@ -17,7 +17,8 @@
package com.alibaba.cloud.dubbo.bootstrap;
import com.alibaba.cloud.dubbo.service.EchoService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -33,7 +34,7 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class DubboSpringCloudClientBootstrap {
@Reference
@DubboReference
private EchoService echoService;
@GetMapping("/echo")

@ -1,8 +1,9 @@
dubbo:
registry:
address: spring-cloud://localhost
cloud:
subscribed-services: spring-cloud-alibaba-dubbo-server
protocols:
dubbo:
port: -1
spring:
application:

@ -23,7 +23,8 @@ import com.alibaba.cloud.dubbo.annotation.DubboTransported;
import com.alibaba.cloud.dubbo.service.RestService;
import com.alibaba.cloud.dubbo.service.User;
import com.alibaba.cloud.dubbo.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -60,10 +61,10 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@EnableCaching
public class DubboSpringCloudConsumerBootstrap {
@Reference
@DubboReference
private UserService userService;
@Reference(version = "1.0.0", protocol = "dubbo")
@DubboReference(version = "1.0.0", protocol = "dubbo")
private RestService restService;
@Autowired

@ -1,15 +1,10 @@
dubbo:
registry:
# The Spring Cloud Dubbo's registry extension
## the default value of dubbo-provider-services is "*", that means to subscribe all providers,
## thus it's optimized if subscriber specifies the required providers.
address: spring-cloud://localhost
# The traditional Dubbo's registry also is supported
# address: zookeeper://127.0.0.1:2181
cloud:
# The subscribed services in consumer side
subscribed-services: ${provider.application.name}
protocols:
dubbo:
port: -1
consumer:
check: false

@ -20,12 +20,12 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
/**
* In-Memory {@link UserService} implementation.
*/
@Service(protocol = "dubbo")
@DubboService(protocol = "dubbo")
public class InMemoryUserService implements UserService {
private Map<Long, User> usersRepository = new HashMap<>();

@ -30,7 +30,8 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -42,7 +43,7 @@ import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Service(version = "1.0.0", protocol = { "dubbo", "rest" })
@DubboService(version = "1.0.0", protocol = { "dubbo", "rest" })
@Path("/")
public class StandardRestService implements RestService {

@ -9,11 +9,6 @@ dubbo:
name: rest
port: 9090
server: netty
registry:
# The Spring Cloud Dubbo's registry extension
address: spring-cloud://localhost
# The traditional Dubbo's registry
# address: zookeeper://127.0.0.1:2181
feign:
hystrix:
enabled: true

@ -20,12 +20,12 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
/**
* In-Memory {@link UserService} implementation.
*/
@Service(protocol = "dubbo")
@DubboService(protocol = "dubbo")
public class InMemoryUserService implements UserService {
private Map<Long, User> usersRepository = new HashMap<>();

@ -19,7 +19,8 @@ package com.alibaba.cloud.dubbo.service;
import java.util.HashMap;
import java.util.Map;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -39,7 +40,7 @@ import static com.alibaba.cloud.dubbo.util.LoggerUtils.log;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Service(version = "1.0.0")
@DubboService(version = "1.0.0")
@RestController
public class SpringRestService implements RestService {

@ -3,16 +3,7 @@ dubbo:
base-packages: com.alibaba.cloud.dubbo.service
protocols:
dubbo:
name: dubbo
port: -1
registries:
new:
address: spring-cloud://localhost
# registry:
# The Spring Cloud Dubbo's registry extension
# address: spring-cloud://localhost
# The traditional Dubbo's registry
# address: nacos://127.0.0.1:8848
feign:
hystrix:

@ -17,7 +17,8 @@
package com.alibaba.cloud.dubbo.bootstrap;
import com.alibaba.cloud.dubbo.service.EchoService;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -36,7 +37,7 @@ public class DubboSpringCloudServerBootstrap {
}
@Service
@DubboService
class EchoServiceImpl implements EchoService {
@Override

@ -4,8 +4,6 @@ dubbo:
protocol:
name: dubbo
port: -1
registry:
address: spring-cloud://localhost
spring:
application:

@ -22,6 +22,7 @@
<module>spring-cloud-starter-stream-rocketmq</module>
<module>spring-cloud-starter-bus-rocketmq</module>
<module>spring-cloud-starter-dubbo</module>
<module>spring-cloud-starter-dubbo-gateway</module>
<module>spring-cloud-starter-alibaba-sidecar</module>
<module>spring-cloud-circuitbreaker-sentinel</module>
<module>spring-cloud-starter-alibaba-sentinel</module>

@ -59,6 +59,7 @@
<artifactId>spring-cloud-starter-gateway</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>

@ -44,7 +44,9 @@ import org.springframework.web.context.request.RequestContextHolder;
*/
public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
private final Logger logger = LoggerFactory.getLogger(SeataHystrixConcurrencyStrategy.class);
private final Logger logger = LoggerFactory
.getLogger(SeataHystrixConcurrencyStrategy.class);
private HystrixConcurrencyStrategy delegate;
public SeataHystrixConcurrencyStrategy() {
@ -53,18 +55,25 @@ public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
if (this.delegate instanceof SeataHystrixConcurrencyStrategy) {
return;
}
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy();
logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher, propertiesStrategy);
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins
.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance()
.getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance()
.getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance()
.getPropertiesStrategy();
logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher,
propertiesStrategy);
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance()
.registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
} catch (Exception ex) {
}
catch (Exception ex) {
logger.error("Failed to register Seata Hystrix Concurrency Strategy", ex);
}
}
@ -73,20 +82,22 @@ public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
HystrixMetricsPublisher metricsPublisher,
HystrixPropertiesStrategy propertiesStrategy) {
if (logger.isDebugEnabled()) {
logger.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy [" + this.delegate + "],"
+ "eventNotifier [" + eventNotifier + "]," + "metricPublisher [" + metricsPublisher + "],"
logger.debug("Current Hystrix plugins configuration is ["
+ "concurrencyStrategy [" + this.delegate + "]," + "eventNotifier ["
+ eventNotifier + "]," + "metricPublisher [" + metricsPublisher + "],"
+ "propertiesStrategy [" + propertiesStrategy + "]," + "]");
logger.debug("Registering Seata Hystrix Concurrency Strategy.");
}
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize,
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixProperty<Integer> corePoolSize,
HystrixProperty<Integer> maximumPoolSize,
HystrixProperty<Integer> keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit,
workQueue);
return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize,
keepAliveTime, unit, workQueue);
}
@Override
@ -101,7 +112,8 @@ public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
}
@Override
public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
public <T> HystrixRequestVariable<T> getRequestVariable(
HystrixRequestVariableLifecycle<T> rv) {
return this.delegate.getRequestVariable(rv);
}
@ -114,14 +126,16 @@ public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
Callable<K> wrappedCallable;
if (this.delegate != null) {
wrappedCallable = this.delegate.wrapCallable(c);
} else {
}
else {
wrappedCallable = c;
}
if (wrappedCallable instanceof SeataContextCallable) {
return wrappedCallable;
}
return new SeataContextCallable<>(wrappedCallable, RequestContextHolder.getRequestAttributes());
return new SeataContextCallable<>(wrappedCallable,
RequestContextHolder.getRequestAttributes());
}
private static class SeataContextCallable<K> implements Callable<K> {
@ -144,7 +158,8 @@ public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
RequestContextHolder.setRequestAttributes(requestAttributes);
RootContext.bind(xid);
return actual.call();
} finally {
}
finally {
RootContext.unbind();
RequestContextHolder.resetRequestAttributes();
}

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-starters</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-dubbo-gateway</artifactId>
<name>Spring Cloud Starter Dubbo Gateway</name>
<dependencies>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Cloud dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<optional>true</optional>
</dependency>
<!-- &lt;!&ndash; Zuul &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-zuul</artifactId>-->
<!-- <optional>true</optional>-->
<!-- </dependency>-->
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<optional>true</optional>
</dependency>
<!-- Dubbo Spring Cloud Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<!-- &lt;!&ndash; Eureka Service Discovery &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- Zookeeper Service Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<version>${spring-cloud-zookeeper.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
<scope>test</scope>
</dependency>
<!-- &lt;!&ndash; Spring Cloud Consul &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-consul-discovery</artifactId>-->
<!-- <version>${spring-cloud-consul.version}</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; Nacos Service Discovery &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
</dependencies>
</project>

@ -0,0 +1,34 @@
/*
* 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 com.alibaba.cloud.dubbo.gateway;
import com.alibaba.cloud.dubbo.util.DubboCloudConstants;
/**
* The constants of Dubbo Cloud Gateway
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public interface DubboCloudGatewayConstants {
/**
* The property prefix of Configuration
*/
String CONFIG_PROPERTY_PREFIX = DubboCloudConstants.CONFIG_PROPERTY_PREFIX
+ ".gateway";
}

@ -0,0 +1,166 @@
/*
* 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 com.alibaba.cloud.dubbo.gateway;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.cloud.dubbo.http.MutableHttpServerRequest;
import com.alibaba.cloud.dubbo.metadata.DubboRestServiceMetadata;
import com.alibaba.cloud.dubbo.metadata.RequestMetadata;
import com.alibaba.cloud.dubbo.metadata.RestMethodMetadata;
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContext;
import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContextFactory;
import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.http.HttpRequest;
import static com.alibaba.cloud.dubbo.http.util.HttpUtils.getParameters;
import static org.apache.commons.lang3.StringUtils.substringAfter;
import static org.apache.commons.lang3.StringUtils.substringBetween;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
/**
* The executor of Dubbo Cloud Gateway that handles the HTTP request and responses the
* result of execution of the generic invocation to the Dubbo service providers
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*
*/
public class DubboCloudGatewayExecutor {
private final Log logger = LogFactory.getLog(getClass());
private final DubboServiceMetadataRepository repository;
private final DubboGenericServiceFactory serviceFactory;
private final DubboGenericServiceExecutionContextFactory contextFactory;
private final DubboCloudGatewayProperties dubboCloudGatewayProperties;
private final ConversionService conversionService;
private final Map<String, Object> dubboTranslatedAttributes = new HashMap<>();
public DubboCloudGatewayExecutor(DubboServiceMetadataRepository repository,
DubboGenericServiceFactory serviceFactory,
DubboGenericServiceExecutionContextFactory contextFactory,
DubboCloudGatewayProperties dubboCloudGatewayProperties,
ObjectProvider<ConversionService> conversionServices) {
this.repository = repository;
this.serviceFactory = serviceFactory;
this.contextFactory = contextFactory;
this.dubboCloudGatewayProperties = dubboCloudGatewayProperties;
this.conversionService = conversionServices
.getIfAvailable(DefaultFormattingConversionService::new);
// TODO : Replace these hard-code configurations
this.dubboTranslatedAttributes.put("protocol", "dubbo");
this.dubboTranslatedAttributes.put("cluster", "failover");
}
public Object execute(HttpRequest request) {
String serviceName = resolveServiceName(request);
String restPath = substringAfter(request.getURI().getPath(), serviceName);
// 初始化 serviceName 的 REST 请求元数据
repository.initializeMetadata(serviceName);
// 将 HttpServletRequest 转化为 RequestMetadata
RequestMetadata clientMetadata = buildRequestMetadata(request, restPath);
DubboRestServiceMetadata dubboRestServiceMetadata = repository.get(serviceName,
clientMetadata);
Object result = null;
if (dubboRestServiceMetadata != null) {
RestMethodMetadata dubboRestMethodMetadata = dubboRestServiceMetadata
.getRestMethodMetadata();
GenericService genericService = serviceFactory
.create(dubboRestServiceMetadata, dubboTranslatedAttributes);
byte[] body = getRequestBody(request);
MutableHttpServerRequest httpServerRequest = new MutableHttpServerRequest(
request, body);
DubboGenericServiceExecutionContext context = contextFactory
.create(dubboRestMethodMetadata, httpServerRequest);
GenericException exception = null;
try {
result = genericService.$invoke(context.getMethodName(),
context.getParameterTypes(), context.getParameters());
String returnType = dubboRestMethodMetadata.getReturnType();
logger.info("The result is " + result);
}
catch (GenericException e) {
exception = e;
}
}
return result;
}
private String resolveServiceName(HttpRequest request) {
URI uri = request.getURI();
String requestURI = uri.getPath();
String servletPath = dubboCloudGatewayProperties.getContextPath();
String part = substringAfter(requestURI, servletPath);
String serviceName = substringBetween(part, PATH_SEPARATOR, PATH_SEPARATOR);
return serviceName;
}
/**
* TODO : Get the Request Body from HttpRequest
*
* @param request {@link HttpRequest}
* @return
*/
private byte[] getRequestBody(HttpRequest request) {
return new byte[0];
}
private RequestMetadata buildRequestMetadata(HttpRequest request, String restPath) {
RequestMetadata requestMetadata = new RequestMetadata();
requestMetadata.setPath(restPath);
requestMetadata.setMethod(request.getMethod().toString());
requestMetadata.setParams(getParameters(request));
requestMetadata.setHeaders(request.getHeaders());
return requestMetadata;
}
}

@ -0,0 +1,56 @@
/*
* 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 com.alibaba.cloud.dubbo.gateway;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayConstants.CONFIG_PROPERTY_PREFIX;
/**
* The Configuration Properties for Dubbo Cloud Gateway
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@ConfigurationProperties(prefix = CONFIG_PROPERTY_PREFIX)
public class DubboCloudGatewayProperties {
/**
* Enabled or not
*/
private boolean enabled = true;
/**
* The context path for the gateway request mapping
*/
private String contextPath = "";
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getContextPath() {
return contextPath;
}
public void setContextPath(String contextPath) {
this.contextPath = contextPath;
}
}

@ -0,0 +1,54 @@
/*
* 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 com.alibaba.cloud.dubbo.gateway.autoconfigure;
import com.alibaba.cloud.dubbo.autoconfigure.DubboMetadataAutoConfiguration;
import com.alibaba.cloud.dubbo.autoconfigure.DubboServiceAutoConfiguration;
import com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayExecutor;
import com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayProperties;
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContextFactory;
import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "dubbo.cloud.gateway", name = "enabled", havingValue = "true", matchIfMissing = true)
@AutoConfigureAfter({ DubboServiceAutoConfiguration.class,
DubboMetadataAutoConfiguration.class })
@EnableConfigurationProperties(DubboCloudGatewayProperties.class)
public class DubboCloudGatewayAutoConfiguration {
@Bean
@ConditionalOnMissingBean(DubboCloudGatewayExecutor.class)
public DubboCloudGatewayExecutor dubboCloudGatewayExecutor(
DubboServiceMetadataRepository repository,
DubboGenericServiceFactory serviceFactory,
DubboGenericServiceExecutionContextFactory contextFactory,
DubboCloudGatewayProperties dubboCloudGatewayProperties,
ObjectProvider<ConversionService> conversionServices) {
return new DubboCloudGatewayExecutor(repository, serviceFactory, contextFactory,
dubboCloudGatewayProperties, conversionServices);
}
}

@ -0,0 +1,74 @@
/*
* 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 com.alibaba.cloud.dubbo.gateway.standard;
import com.alibaba.cloud.dubbo.autoconfigure.DubboMetadataAutoConfiguration;
import com.alibaba.cloud.dubbo.autoconfigure.DubboServiceAutoConfiguration;
import com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayExecutor;
import com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayProperties;
import com.alibaba.cloud.dubbo.gateway.autoconfigure.DubboCloudGatewayAutoConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.support.DefaultServerCodecConfigurer;
/**
* The Auto-{@link Configuration} of Dubbo Spring Cloud Gateway
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(GlobalFilter.class)
@ConditionalOnProperty(prefix = "dubbo.cloud.gateway", name = "enabled", havingValue = "true", matchIfMissing = true)
@AutoConfigureAfter({ DubboServiceAutoConfiguration.class,
DubboMetadataAutoConfiguration.class, DubboCloudGatewayAutoConfiguration.class })
@EnableConfigurationProperties(DubboCloudGatewayProperties.class)
public class DubboSpringCloudGatewayAutoConfiguration {
private final Log logger = LogFactory.getLog(getClass());
@Bean
@ConditionalOnMissingBean(ServerCodecConfigurer.class)
public ServerCodecConfigurer serverCodecConfigurer() {
return new DefaultServerCodecConfigurer();
}
@Bean
public DubboSpringCloudGatewayFilter dubboSpringCloudGatewayFilter(
DubboCloudGatewayExecutor dubboCloudGatewayExecutor) {
return new DubboSpringCloudGatewayFilter(dubboCloudGatewayExecutor);
}
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/**").uri("http://localhost:9090").id("first"))
.build();
}
}

@ -0,0 +1,74 @@
/*
* 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 com.alibaba.cloud.dubbo.gateway.standard;
import com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayExecutor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
/**
* The Spring Cloud {@link GatewayFilter Gateway Filter} for Dubbo
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class DubboSpringCloudGatewayFilter
implements GatewayFilter, GlobalFilter, Ordered {
private final Log logger = LogFactory.getLog(getClass());
private int order;
private final DubboCloudGatewayExecutor dubboCloudGatewayExecutor;
public DubboSpringCloudGatewayFilter(
DubboCloudGatewayExecutor dubboCloudGatewayExecutor) {
this.dubboCloudGatewayExecutor = dubboCloudGatewayExecutor;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Object result = dubboCloudGatewayExecutor.execute(exchange.getRequest());
if (result == null) {
chain.filter(exchange);
}
else {
ServerHttpResponse response = exchange.getResponse();
}
return Mono.empty();
}
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return order;
}
}

@ -0,0 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.dubbo.gateway.autoconfigure.DubboCloudGatewayAutoConfiguration,\
com.alibaba.cloud.dubbo.gateway.standard.DubboSpringCloudGatewayAutoConfiguration

@ -0,0 +1,37 @@
/*
* 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 com.alibaba.cloud.dubbo.gateway.standard;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* The bootstrap class of Dubbo Spring Cloud Gateway
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@SpringBootApplication
@EnableDiscoveryClient
public class DubboSpringCloudGatewayBootstrap {
public static void main(String[] args) {
new SpringApplicationBuilder(DubboSpringCloudGatewayBootstrap.class)
.properties("spring.profiles.active=zookeeper").run(args);
}
}

@ -0,0 +1,74 @@
spring:
application:
name: spring-cloud-alibaba-dubbo-gateway
main:
allow-bean-definition-overriding: true
dubbo:
protocols:
dubbo:
port: -1
server:
port: 9090
# default disable all
cloud:
nacos:
discovery:
enabled: false
register-enabled: false
zookeeper:
enabled: false
consul:
enabled: false
eureka:
client:
enabled: false
---
spring:
profiles: nacos
cloud:
nacos:
username: nacos
password: nacos
discovery:
enabled: true
register-enabled: true
server-addr: 127.0.0.1:8848
ephemeral: false
---
spring:
profiles: eureka
eureka:
client:
enabled: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
---
spring:
profiles: zookeeper
cloud:
zookeeper:
enabled: true
connect-string: 127.0.0.1:2181
---
spring:
profiles: consul
cloud:
consul:
enabled: true
host: 127.0.0.1
port: 8500

@ -22,6 +22,7 @@ import java.util.Set;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static com.alibaba.cloud.dubbo.util.DubboCloudConstants.CONFIG_PROPERTY_PREFIX;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
import static org.springframework.util.StringUtils.hasText;
import static org.springframework.util.StringUtils.trimAllWhitespace;
@ -31,7 +32,7 @@ import static org.springframework.util.StringUtils.trimAllWhitespace;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@ConfigurationProperties(prefix = "dubbo.cloud")
@ConfigurationProperties(prefix = CONFIG_PROPERTY_PREFIX)
public class DubboCloudProperties {
/**

@ -0,0 +1,31 @@
/*
* 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 com.alibaba.cloud.dubbo.util;
/**
* The constants for Dubbo Spring Cloud
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public interface DubboCloudConstants {
/**
* The property prefix of Configuration
*/
String CONFIG_PROPERTY_PREFIX = "dubbo.cloud";
}
Loading…
Cancel
Save