Merge branch 'release/0.2.0'

This commit is contained in:
huangsimin 2019-08-20 10:23:48 +08:00
commit 088cf83b92
29 changed files with 650 additions and 223 deletions

10
pom.xml
View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version> <version>2.1.7.RELEASE</version>
<relativePath /> <relativePath />
</parent> </parent>
@ -22,7 +22,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version> <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
<dubbo.version>2.7.2</dubbo.version> <dubbo.version>2.7.3</dubbo.version>
</properties> </properties>
@ -47,19 +47,19 @@
<dependency> <dependency>
<groupId>org.apache.dubbo</groupId> <groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId> <artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.1</version> <version>${dubbo.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.dubbo</groupId> <groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId> <artifactId>dubbo</artifactId>
<version>2.7.2</version> <version>${dubbo.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.dubbo</groupId> <groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId> <artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.1</version> <version>${dubbo.version}</version>
<type>pom</type> <type>pom</type>
<exclusions> <exclusions>
<exclusion> <exclusion>

View File

@ -17,9 +17,11 @@
<properties> <properties>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<build.skip.assembly>false</build.skip.assembly>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>cn.ecpark.service</groupId> <groupId>cn.ecpark.service</groupId>
<artifactId>usergw-api</artifactId> <artifactId>usergw-api</artifactId>
@ -56,7 +58,7 @@
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.21</version> <version>1.24</version>
</dependency> </dependency>
<dependency> <dependency>
@ -64,12 +66,12 @@
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.58</version> <version>1.2.58</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.ecpark.service</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>usergw-api</artifactId> <artifactId>apollo-client</artifactId>
<version>${project.parent.version}</version> <version>1.4.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -85,17 +87,42 @@
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>cn.ecpark.service.usergw.App</mainClass>
</configuration>
</plugin> </plugin>
<plugin><artifactId>maven-compiler-plugin</artifactId></plugin>
<plugin><artifactId>maven-resources-plugin</artifactId></plugin>
<plugin><artifactId>maven-source-plugin</artifactId></plugin>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
</plugin> <version>3.1.1</version>
<plugin> <executions>
<artifactId>maven-resources-plugin</artifactId> <execution>
</plugin> <id>make-assembly</id>
<plugin> <phase>package</phase>
<artifactId>maven-source-plugin</artifactId> <goals>
</plugin> <goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<skipTests>true</skipTests>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<!-- <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs> -->
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
@ -123,4 +150,4 @@
</build> </build>
</project> </project>

View File

@ -0,0 +1,45 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>assembly</id>
<formats>
<format>dir</format>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/assembly/scripts</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
<filtered>true</filtered>
</fileSet>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>config</outputDirectory>
<includes>
<include>*.properties</include>
<include>gateway.yaml</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
<!-- <dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<scope>compile</scope>
</dependencySet>
</dependencySets> -->
</assembly>

View File

@ -0,0 +1,10 @@
@echo off & setlocal enabledelayedexpansion
set BIN_DIR=%~dp0
::run
cd %BIN_DIR%\..
set APP_JAR=""
for %%f in (*-*-*.jar) do set APP_JAR=%%f
java -Dloader.path=config -Dfile.encoding=UTF-8 -Xms256m -Xmx512m -jar %APP_JAR%
cd %BIN_DIR%

View File

@ -0,0 +1,8 @@
#!/bin/sh
##cnf
APP_PMS="-Xms256m -Xmx512m"
APP_JAR=`echo *-*-*.jar`
##run
cur=$(dirname $(readlink -f "$0")) && cd $cur/..
exec java -Dloader.path=config -Dfile.encoding=UTF-8 ${APP_PMS} -jar ${APP_JAR}

View File

@ -1,5 +1,12 @@
{"properties": [{ {"properties": [
"name": "yame.config", {
"type": "java.lang.String", "name": "yame.gateway.config",
"description": "用于配置网关的路径, 如果不填.默认: gateway.yml, gateway.yaml, Gateway.yml, Gateway.yaml" "type": "java.lang.String",
}]} "description": "用于配置网关的路径, 如果不填.默认: gateway.yml, gateway.yaml, Gateway.yml, Gateway.yaml"
},
{
"name": "apollo.namespace",
"type": "java.lang.String",
"description": "默认gateway.yml和gateway.yaml"
}
]}

View File

@ -1,14 +1,18 @@
package cn.ecpark.service.usergw; package cn.ecpark.service.usergw;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig; import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@Configurable
@ConfigurationProperties
@SpringBootApplication @SpringBootApplication
@SpringBootConfiguration @SpringBootConfiguration
@EnableAutoConfiguration @EnableAutoConfiguration

View File

@ -0,0 +1,22 @@
package cn.ecpark.service.usergw.biz.events;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
@Service
public class ConfigRefresh implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
public void notifyChanged() {
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
}

View File

@ -1,7 +1,10 @@
package cn.ecpark.service.usergw.biz.filters.bean; package cn.ecpark.service.usergw.biz.filters.bean;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
import org.apache.dubbo.rpc.service.GenericService; import org.apache.dubbo.rpc.service.GenericService;
/** /**
@ -9,17 +12,47 @@ import org.apache.dubbo.rpc.service.GenericService;
*/ */
public class GenericServicePool { public class GenericServicePool {
HashMap<String, GenericService> gsDictionary; private class ReferenceConfigStore {
private ReferenceConfig<GenericService> ref;
private GenericService gs;
public ReferenceConfigStore(ReferenceConfig<GenericService> refValue) {
this.ref = refValue;
this.gs = ref.get();
}
public GenericService get() {
return gs;
}
public void destroy() {
this.ref.destroy();
this.ref = null;
this.gs = null ;
}
}
HashMap<String, ReferenceConfigStore> gsDictionary;
public GenericServicePool() { public GenericServicePool() {
gsDictionary = new HashMap<String, GenericService>(); gsDictionary = new HashMap<String, ReferenceConfigStore>();
}
@Override
protected void finalize() throws Throwable {
for(Entry<String, ReferenceConfigStore> entry : gsDictionary.entrySet()) {
entry.getValue(). destroy();
}
super.finalize();
} }
public GenericService get(String key) { public GenericService get(String key) {
return gsDictionary.get(key); return gsDictionary.get(key).get();
} }
public void put(String key, GenericService genericService) { public void put(String key, ReferenceConfig<GenericService> ref) {
gsDictionary.put(key, genericService); ReferenceConfigStore refStore = new ReferenceConfigStore(ref);
gsDictionary.put(key, refStore);
} }
} }

View File

@ -0,0 +1,136 @@
package cn.ecpark.service.usergw.config;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import cn.ecpark.service.usergw.biz.events.ConfigRefresh;
// @EnableApolloConfig("gateway.yml")
// @ConditionalOnProperty(prefix="app", value="id", matchIfMissing=true)
// @Configurable
public class ConfigApollo implements ConfigChangeListener {
private static final org.slf4j.Logger log =
org.slf4j.LoggerFactory.getLogger(ConfigApollo.class);
// @ApolloConfig("gateway.yml")
private Config config;
@Autowired
private ApplicationContext appContext;
@Value("${apollo.meta:}")
private String apolloMeta;
@Value("${app.id:}")
private String appID;
@Value("${apollo.namespace:}")
private String apolloNamespace;
private int tryConnect;
public ConfigApollo() {
this.tryConnect = 1;
}
public void Connect() {
if (this.isConnected() && this.tryConnect > 0) {
this.tryConnect--;
ConfigSourceType stype = null;
if (apolloNamespace.equals("")) {
String[] tryExamples = { "gateway.yml", "gateway.yaml", "Gateway.yml", "Gateway.yaml" };
for (String ns : tryExamples) {
apolloNamespace = ns;
config = ConfigService.getConfig(apolloNamespace);
stype = config.getSourceType();
if (!stype.name().equals("None")) {
break;
}
}
} else {
config = ConfigService.getConfig(apolloNamespace);
stype = config.getSourceType();
}
if(stype.name().equals("None") || stype == null) {
log.error("getSourceType = {} is error, please check apollo server, or check apollo properties", stype.name());
((ConfigurableApplicationContext)this.appContext).close();
}
if (config != null) {
config.addChangeListener(this);
}
}
}
public boolean isConnected() {
if (!this.appID.equals("") && !this.apolloMeta.equals("")) {
return true;
}
return false;
}
// @ApolloConfigChangeListener("gateway.yml")
// public void listenApolloChange(ConfigChangeEvent changeEvent) {
// }
@Override
public void onChange(ConfigChangeEvent changeEvent) {
ConfigRefresh change = (ConfigRefresh) appContext.getBean(ConfigRefresh.class);
change.notifyChanged();
}
/**
* @return Config return the config
*/
public Config getConfig() {
return config;
}
/**
* @param config the config to set
*/
public void setConfig(Config config) {
this.config = config;
}
/**
* @return String return the apolloMeta
*/
public String getApolloMeta() {
return apolloMeta;
}
/**
* @param apolloMeta the apolloMeta to set
*/
public void setApolloMeta(String apolloMeta) {
this.apolloMeta = apolloMeta;
}
/**
* @return String return the appID
*/
public String getAppID() {
return appID;
}
/**
* @param appID the appID to set
*/
public void setAppID(String appID) {
this.appID = appID;
}
}

View File

@ -1,7 +1,14 @@
package cn.ecpark.service.usergw.config; package cn.ecpark.service.usergw.config;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URI; import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -12,6 +19,12 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import com.ctrip.framework.apollo.internals.ConfigRepository;
import com.ctrip.framework.apollo.internals.DefaultConfig;
import com.ctrip.framework.apollo.internals.PropertiesCompatibleFileConfigRepository;
import com.ctrip.framework.apollo.internals.YamlConfigFile;
import com.ctrip.framework.apollo.internals.YmlConfigFile;
import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.rpc.service.GenericService; import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -23,24 +36,26 @@ import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import cn.ecpark.service.usergw.biz.filters.bean.GenericServicePool; import cn.ecpark.service.usergw.biz.filters.bean.GenericServicePool;
import cn.ecpark.service.usergw.utils.Extract; import cn.ecpark.service.usergw.utils.Extract;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
/** /**
* ConfigGateway * ConfigGateway
*/ */
@Component @Component
@Slf4j
public class ConfigGateway implements RouteDefinitionLocator { public class ConfigGateway implements RouteDefinitionLocator {
// List<MediaType> mediaTypes = new ArrayList<>(); // List<MediaType> mediaTypes = new ArrayList<>();
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ConfigGateway.class);
@Value("${yame.gateway.config:}")
private String gatewayConfigPath;
@Value("${yame.config}")
private String yameConfigPath;
private List<FilterDefinition> defaultFilters = new ArrayList<>(); private List<FilterDefinition> defaultFilters = new ArrayList<>();
private HashMap<String, BiConsumer<ReferenceConfig<GenericService>, Object>> specialField = new HashMap<String, BiConsumer<ReferenceConfig<GenericService>, Object>>(); private HashMap<String, BiConsumer<ReferenceConfig<GenericService>, Object>> specialField = new HashMap<String, BiConsumer<ReferenceConfig<GenericService>, Object>>();
@ -67,31 +82,25 @@ public class ConfigGateway implements RouteDefinitionLocator {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Flux<RouteDefinition> getRouteDefinitions() { public Flux<RouteDefinition> getRouteDefinitions() {
// WebFluxConfigurationSupport a;
defaultFilters.clear(); defaultFilters.clear();
Object inputStream = null; InputStream inputStream;
String[] gatewayConfigPathList;
if (yameConfigPath == null) {
gatewayConfigPathList = new String[] { "gateway.yml", "gateway.yaml", "Gateway.yml", "Gateway.yaml" };
} else {
gatewayConfigPathList = new String[] { yameConfigPath };
}
for (String gatewayConfigPath : gatewayConfigPathList) {
gatewayConfigPath = gatewayConfigPath.trim();
inputStream = this.getClass().getClassLoader().getResourceAsStream(gatewayConfigPath);
if (inputStream != null) {
break;
}
}
ConfigApollo configApollo = appContext.getBean(ConfigApollo.class);
configApollo.Connect();
if(configApollo.isConnected()) {
inputStream = loadApolloConfig(configApollo);
} else {
inputStream = loadLocalFileConfig();
}
if (inputStream != null) { if (inputStream != null) {
Map<String, Object> configYaml = new Yaml().load((InputStream) inputStream); Map<String, Object> configYaml = new Yaml().load(inputStream);
if (configYaml != null) { if (configYaml != null) {
List<String> defaultFiltersYaml = null; List<String> defaultFiltersYaml = null;
Map<String, Object> restfulYaml = null; Map<String, Object> restfulYaml = null;
Map<String, Object> dubboYaml = null; Map<String, Object> dubboYaml = null;
Object unknown; Object unknown;
unknown = configYaml.get("default-filters"); unknown = configYaml.get("default-filters");
if (unknown != null) { if (unknown != null) {
@ -121,13 +130,65 @@ public class ConfigGateway implements RouteDefinitionLocator {
if (!routeList.isEmpty()) { if (!routeList.isEmpty()) {
return Flux.fromIterable(routeList); return Flux.fromIterable(routeList);
} }
} }
} }
return Flux.empty(); return Flux.empty();
} }
private InputStream loadLocalFileConfig() {
InputStream inputStream = null;
String[] gatewayConfigPathList;
if (gatewayConfigPath.equals("")) {
gatewayConfigPathList = new String[] { "gateway.yml", "gateway.yaml", "Gateway.yml", "Gateway.yaml" };
} else {
gatewayConfigPathList = new String[] { gatewayConfigPath };
}
for (String gatewayConfigPath : gatewayConfigPathList) {
gatewayConfigPath = gatewayConfigPath.trim();
inputStream = this.getClass().getClassLoader().getResourceAsStream(gatewayConfigPath);
if(inputStream != null) {
return inputStream;
}
}
log.error("can't find the config of gateway, like gateway.yaml");
return inputStream;
}
private InputStream loadApolloConfig(ConfigApollo configApollo) {
DefaultConfig config = (DefaultConfig) configApollo.getConfig();
try {
String content = null ;
for(int i = 0; i < 3; i++) {
Field m_configRepository = DefaultConfig.class.getDeclaredField("m_configRepository");
m_configRepository.setAccessible(true);
ConfigRepository cr = (ConfigRepository) m_configRepository.get(config);
Field configFile = PropertiesCompatibleFileConfigRepository.class.getDeclaredField("configFile");
configFile.setAccessible(true);
YamlConfigFile ymlConfigFile = (YamlConfigFile) configFile.get(cr);
content = ymlConfigFile.getContent();
if(content == null) {
log.error("eson:debug {}", config.toString());
continue;
}
log.info("Load Apollo YAML Config: \n{}", content);
return new ByteArrayInputStream(content.getBytes());
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/** /**
* *
* @param routeList 路由列表 * @param routeList 路由列表
@ -255,7 +316,7 @@ public class ConfigGateway implements RouteDefinitionLocator {
/** /**
* *
* @param rd {@link RouteDefinition} * @param rd {@link RouteDefinition}
* @param iter Yaml.dubbo.routes * @param iter Yaml.dubbo.routes
* @return dubboUri 字符串标识 eg. dubbo://application/group/com.a.b:1.0.0 * @return dubboUri 字符串标识 eg. dubbo://application/group/com.a.b:1.0.0
*/ */
@ -285,12 +346,11 @@ public class ConfigGateway implements RouteDefinitionLocator {
// 设置uri // 设置uri
Object order = iter.get("order"); Object order = iter.get("order");
if (order != null) { if (order != null) {
rd.setOrder((int)order); rd.setOrder((int) order);
iter.remove("order"); iter.remove("order");
} else { } else {
rd.setOrder(0); rd.setOrder(0);
} }
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setConnections(3); reference.setConnections(3);
@ -342,16 +402,16 @@ public class ConfigGateway implements RouteDefinitionLocator {
UriString += Extract.getReferenceConfigKey(reference); UriString += Extract.getReferenceConfigKey(reference);
GenericServicePool gsPool = appContext.getBean(GenericServicePool.class); GenericServicePool gsPool = appContext.getBean(GenericServicePool.class);
reference.setGeneric(true); reference.setGeneric(true);
gsPool.put(UriString, reference.get()); gsPool.put(UriString, reference);
return UriString; return UriString;
} }
/** /**
* *
* @param predicates List<{@link PredicateDefinition}> 断言列表 * @param predicates List<{@link PredicateDefinition}> 断言列表
* @param iter restful.routes.predicates * @param iter restful.routes.predicates
* @param yamlField 根据域的key 获取 predicates 字符串列 * @param yamlField 根据域的key 获取 predicates 字符串列
*/ */
private void parseAndAddPredicates(List<PredicateDefinition> predicates, LinkedHashMap<String, List<String>> iter, private void parseAndAddPredicates(List<PredicateDefinition> predicates, LinkedHashMap<String, List<String>> iter,
String yamlField) { String yamlField) {
@ -365,9 +425,9 @@ public class ConfigGateway implements RouteDefinitionLocator {
/** /**
* *
* @param filters List<{@link FilterDefinition}> 过滤器列表 * @param filters List<{@link FilterDefinition}> 过滤器列表
* @param iter restful.routes.filters * @param iter restful.routes.filters
* @param yamlField 根据域的key 获取 filters 字符串列 * @param yamlField 根据域的key 获取 filters 字符串列
*/ */
private void parseAndAddFilters(List<FilterDefinition> filters, LinkedHashMap<String, List<String>> iter, private void parseAndAddFilters(List<FilterDefinition> filters, LinkedHashMap<String, List<String>> iter,
String yamlField) { String yamlField) {
@ -382,43 +442,44 @@ public class ConfigGateway implements RouteDefinitionLocator {
/** /**
* *
* @param dubboUri 获取返回的字符串 {@link #parseDubboUriAndSetBase(RouteDefinition, LinkedHashMap)} * @param dubboUri 获取返回的字符串
* @param filters List<{@link FilterDefinition}> 过滤器列表 * {@link #parseDubboUriAndSetBase(RouteDefinition, LinkedHashMap)}
* @param iter dubbo.routes.filters * @param filters List<{@link FilterDefinition}> 过滤器列表
* @param iter dubbo.routes.filters
* @param yamlField 根据域的key 获取 filters 字符串列 * @param yamlField 根据域的key 获取 filters 字符串列
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void parseAndAddDubboFilters(String dubboUri, List<FilterDefinition> filters, private void parseAndAddDubboFilters(String dubboUri, List<FilterDefinition> filters,
LinkedHashMap<String, List<String>> iter, String yamlField) { LinkedHashMap<String, List<String>> iter, String yamlField) {
List<String> filtersYaml = iter.get(yamlField); List<String> filtersYaml = iter.get(yamlField);
filters.addAll(defaultFilters); filters.addAll(defaultFilters);
if (filtersYaml != null) { if (filtersYaml != null) {
for (Object filterObject : filtersYaml) { for (Object filterObject : filtersYaml) {
// 现阶段只支持两种情况 // 现阶段只支持两种情况
if(filterObject.getClass() == String.class) { if (filterObject.getClass() == String.class) {
String filterString = (String)filterObject; String filterString = (String) filterObject;
FilterDefinition fd = new FilterDefinition(filterString); FilterDefinition fd = new FilterDefinition(filterString);
log.info(fd.getName()); log.info(fd.getName());
if (!fd.getName().equals("Dubbo")) { if (!fd.getName().equals("Dubbo")) {
filters.add(fd); filters.add(fd);
} }
} else if (filterObject.getClass() == LinkedHashMap.class) { } else if (filterObject.getClass() == LinkedHashMap.class) {
Map<String, Object> filterMap = (LinkedHashMap<String, Object>)filterObject; Map<String, Object> filterMap = (LinkedHashMap<String, Object>) filterObject;
FilterDefinition fd = new FilterDefinition(); FilterDefinition fd = new FilterDefinition();
fd.setName((String)filterMap.get("name")); fd.setName((String) filterMap.get("name"));
if(filterMap.containsKey("args")) { if (filterMap.containsKey("args")) {
Object args = filterMap.get("args"); Object args = filterMap.get("args");
for( Entry<String, Object> kv : ((Map<String, Object>)args).entrySet()) { for (Entry<String, Object> kv : ((Map<String, Object>) args).entrySet()) {
if(kv.getValue().getClass() != String.class) { if (kv.getValue().getClass() != String.class) {
kv.setValue( String.valueOf(kv.getValue())); kv.setValue(String.valueOf(kv.getValue()));
} }
} }
fd.setArgs((Map<String,String>)args); fd.setArgs((Map<String, String>) args);
} }
log.info(fd.getName()); log.info(fd.getName());
if (!fd.getName().equals("Dubbo")) { if (!fd.getName().equals("Dubbo")) {
filters.add(fd); filters.add(fd);

View File

@ -6,22 +6,29 @@ import org.springframework.stereotype.Component;
import cn.ecpark.service.usergw.biz.filters.bean.GenericServicePool; import cn.ecpark.service.usergw.biz.filters.bean.GenericServicePool;
import cn.ecpark.service.usergw.biz.filters.factory.DubboGatewayFilterFactory; import cn.ecpark.service.usergw.biz.filters.factory.DubboGatewayFilterFactory;
import cn.ecpark.service.usergw.config.ConfigApollo;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@Component @Component
public class ConfigBean { public class ConfigBean {
@Bean
KeyResolver ipResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
}
@Bean @Bean
public GenericServicePool genericServicePool() { public GenericServicePool genericServicePool() {
return new GenericServicePool(); return new GenericServicePool();
} }
@Bean @Bean
public DubboGatewayFilterFactory dubboFilterFactory() { ConfigApollo configApollo() {
return new DubboGatewayFilterFactory(); return new ConfigApollo();
} }
@Bean @Bean
KeyResolver ipResolver() { public DubboGatewayFilterFactory dubboFilterFactory() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString()); return new DubboGatewayFilterFactory();
} }
} }

View File

@ -1,5 +1,17 @@
spring.application.name=gateway spring.application.name=gateway
apollo.namespace=gateway.yml
app.id=gateway
apollo.meta=http://localhost:8180
# local.meta=http://localhost:8180
# dev.meta=http://localhost:8180
# fat.meta=http://localhost:8180
# uat.meta=http://localhost:8180
# lpt.meta=http://localhost:8180
# pro.meta=http://localhost:8180
# eureka.instance.ip-address=http://localhost:8180
dubbo.scan.base-packages=cn.ecpark.service.usergw.impl dubbo.scan.base-packages=cn.ecpark.service.usergw.impl
dubbo.protocol.name=dubbo dubbo.protocol.name=dubbo
dubbo.protocol.port=20999 dubbo.protocol.port=20999
@ -10,6 +22,7 @@ server.port=8888
# logging.level.org.springframework.cloud.gateway=debug # logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log logging.file=logs/log
yame.gateway.config=gateway.yaml
yame.config=gateway.yaml

View File

@ -46,8 +46,8 @@ dubbo:
- name: RequestRateLimiter - name: RequestRateLimiter
args: args:
key-resolver: '#{@ipResolver}' #SPEL表达式去的对应的bean key-resolver: '#{@ipResolver}' #SPEL表达式去的对应的bean
redis-rate-limiter.replenishRate: 40 # 令牌桶的容积 redis-rate-limiter.replenishRate: 30 # 令牌桶的容积
redis-rate-limiter.burstCapacity: 80 # 流速 每秒 redis-rate-limiter.burstCapacity: 60 # 流速 每秒
# - name: RequestRateLimiter1 # - name: RequestRateLimiter1
# args: # args:

View File

@ -0,0 +1,19 @@
dubbo:
routes:
- id: test
order: 0
application: dubbo-exchange
methods: # 如果没填就从 request拿 意味着所有接口都可以使用
- name: Say
param-types:
- java.lang.String
- name: Hello
connections: 4
group: test
# registry: zookeeper://127.0.0.1:2181
interface: ocean.demo.api.IExchange
version: 1.0.0
predicates:
- Path=/dubbo/gateway/test5

View File

@ -6,6 +6,8 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
@ -15,10 +17,9 @@ import reactor.netty.http.client.HttpClientResponse;
// TODO: 添加附加Dubbo Service for Test启动进程
@SpringBootTest(classes= App.class, webEnvironment = WebEnvironment.RANDOM_PORT) @SpringBootTest(classes= App.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@TestPropertySource(locations = {"application.properties"}) @TestPropertySource(locations = "classpath:/resources/test1.properties", properties = {"apollo.meta=", "app.id="})
public class TestHttp2DubboConfig { public class TestHttp2DubboConfig {
@LocalServerPort @LocalServerPort

View File

@ -6,6 +6,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
@ -13,10 +14,10 @@ import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClient.ResponseReceiver; import reactor.netty.http.client.HttpClient.ResponseReceiver;
import reactor.netty.http.client.HttpClientResponse; import reactor.netty.http.client.HttpClientResponse;
// TODO: 添加附加Dubbo Service for Test启动进程
@SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.RANDOM_PORT) @SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@TestPropertySource(locations = { "application2.properties" }) @TestPropertySource(locations = "classpath:/resources/test2.properties", properties = {"apollo.meta=", "app.id="})
public class TestHttp2DubboConfig2 { public class TestHttp2DubboConfig2 {
@LocalServerPort @LocalServerPort

View File

@ -10,6 +10,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
@ -17,10 +18,10 @@ import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClient.ResponseReceiver; import reactor.netty.http.client.HttpClient.ResponseReceiver;
import reactor.netty.http.client.HttpClientResponse; import reactor.netty.http.client.HttpClientResponse;
// TODO: 添加附加Dubbo Service for Test启动进程
@SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.DEFINED_PORT) @SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.DEFINED_PORT)
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@TestPropertySource(locations = { "application3.properties" }) @TestPropertySource(locations = "classpath:/resources/test3.properties", properties = {"apollo.meta=", "app.id="})
public class TestHttp2DubboConfig3 { public class TestHttp2DubboConfig3 {
@LocalServerPort @LocalServerPort

View File

@ -1,3 +1,8 @@
package cn.ecpark.service.usergw; package cn.ecpark.service.usergw;
import org.junit.Assert; import org.junit.Assert;
@ -6,6 +11,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
@ -16,14 +22,14 @@ import reactor.netty.http.client.HttpClientResponse;
// TODO: 添加附加Dubbo Service for Test启动进程 // TODO: 添加附加Dubbo Service for Test启动进程
@SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.RANDOM_PORT) @SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@TestPropertySource(locations = { "application4.properties" }) @TestPropertySource(locations = "classpath:/resources/test4.properties", properties = {"apollo.meta=", "app.id="})
public class TestHttp2DubboConfig4 { public class TestHttp2DubboConfig4 {
@LocalServerPort @LocalServerPort
private int serverPort; private int serverPort;
@Test @Test
public void Test1RequestHttp2DubboSetHeader() { public void Test1RedisLimit() {
// Test Base Url // Test Base Url
for(int i = 0; i < 50;i++) { for(int i = 0; i < 50;i++) {
HttpClient client = HttpClient.create(); HttpClient client = HttpClient.create();
@ -46,14 +52,5 @@ public class TestHttp2DubboConfig4 {
} }
} }
// @Test
// @SuppressWarnings("unchecked")
// public void Test3RestfulFilters() {
// }
} }

View File

@ -0,0 +1,58 @@
package cn.ecpark.service.usergw;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClient.ResponseReceiver;
import reactor.netty.http.client.HttpClientResponse;
// TODO: 添加附加Dubbo Service for Test启动进程
@SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
@TestPropertySource(locations = "classpath:/resources/test5.properties")
@Ignore
public class TestHttp2DubboConfig5 {
@LocalServerPort
private int serverPort;
@Test
public void Test1LoadApolloConfig() {
// Test Base Url
HttpClient client = HttpClient.create();
ResponseReceiver<?> receiver;
String content;
receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/gateway/test5")
.headers(h -> h.set("method", "Hello")).get();
HttpClientResponse response = receiver.response().block();
Assert.assertNotNull(response);
if(response.status().code() == 200) {
content = receiver.responseContent().asString().blockLast();
Assert.assertNotNull(content);
Assert.assertEquals("Hello Dubbo", content);
} else {
Assert.assertEquals(429, response.status().code());
}
receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/hello")
.headers(h -> h.set("method", "Hello")).get();
response = receiver.response().block();
Assert.assertNotNull(response);
Assert.assertNotEquals(200, response.status().code());
}
}

View File

@ -0,0 +1,59 @@
package cn.ecpark.service.usergw;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClient.ResponseReceiver;
import reactor.netty.http.client.HttpClientResponse;
// TODO: 添加附加Dubbo Service for Test启动进程
@SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
@TestPropertySource(locations = "classpath:/resources/test5.properties", properties = {"apollo.namespace=", "app.id=gateway"})
@Ignore
public class TestHttp2DubboConfig6 {
@LocalServerPort
private int serverPort;
@Test
public void Test1LoadDefaultApolloConfig() {
// Test Base Url
HttpClient client = HttpClient.create();
ResponseReceiver<?> receiver;
String content;
receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/hello1")
.headers(h -> h.set("method", "Hello")).get();
HttpClientResponse response = receiver.response().block();
Assert.assertNotNull(response);
if(response.status().code() == 200) {
content = receiver.responseContent().asString().blockLast();
Assert.assertNotNull(content);
Assert.assertEquals("Hello Dubbo", content);
} else {
Assert.assertEquals(429, response.status().code());
}
}
}

View File

@ -1,13 +0,0 @@
spring.application.name=gateway
dubbo.scan.base-packages=cn.ecpark.service.usergw.impl
dubbo.protocol.name=dubbo
dubbo.protocol.port=20999
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.config-center.address=zookeeper://127.0.0.1:2181
dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
server.port=8888
# logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log

View File

@ -1,51 +0,0 @@
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Test-Default-Bar
restful:
routes:
- id: path_route
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route12;
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route13
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
# - id: redirect_to
# uri: http://localhost/test/**
# order: 11
# filters:
# - RedirectTo=302, http://httpbin.org:80/get
dubbo:
routes:
- id: test
order: 0
application: dubbo-exchange
# methods: # 如果没填就从 request拿 意味着所有接口都可以使用
# - name: Say
# param-types:
# - java.lang.String
# - name: Hello
connections: 4
group: test
# registry: zookeeper://127.0.0.1:2181
interface: ocean.demo.api.IExchange
version: 1.0.0
predicates:
- Path=/dubbo/hello

View File

@ -1,50 +0,0 @@
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Test-Default-Bar
restful:
routes:
- id: path_route
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route12;
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route13
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
# - id: redirect_to
# uri: http://localhost/test/**
# order: 11
# filters:
# - RedirectTo=302, http://httpbin.org:80/get
dubbo:
routes:
- id: test
order: 0
application: dubbo-exchange
methods: # 如果没填就从 request拿 意味着所有接口都可以使用
- name: Say
param-types:
- java.lang.String
- name: Hello
connections: 4
group: test
# registry: zookeeper://127.0.0.1:2181
interface: ocean.demo.api.IExchange
version: 1.0.0
predicates:
- Path=/dubbo/hello

View File

@ -10,6 +10,5 @@ server.port=8888
# logging.level.org.springframework.cloud.gateway=debug # logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log logging.file=logs/log
yame.gateway.config=test-gateway.yaml
yame.config=test-gateway.yaml

View File

@ -11,5 +11,5 @@ server.port=8888
# logging.level.org.springframework.cloud.gateway=debug # logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log logging.file=logs/log
yame.config=test-gateway2.yaml yame.gateway.config=test-gateway2.yaml

View File

@ -11,5 +11,5 @@ server.port=8888
# logging.level.org.springframework.cloud.gateway=debug # logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log logging.file=logs/log
yame.config=test-gateway3.yaml yame.gateway.config=test-gateway3.yaml

View File

@ -17,5 +17,5 @@ server.port=8888
# logging.level.org.springframework.cloud.gateway=debug # logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log logging.file=logs/log
yame.config=test-gateway4.yaml yame.gateway.config=test-gateway4.yaml

View File

@ -0,0 +1,33 @@
spring.application.name=gateway
# AppID 非 NameSpace
app.id=test-gateway5
apollo.meta=http://localhost:8180
apollo.namespace=gateway-test5.yaml
# local.meta=http://localhost:8180
# dev.meta=http://localhost:8180
# fat.meta=http://localhost:8180
# uat.meta=http://localhost:8180
# lpt.meta=http://localhost:8180
# pro.meta=http://localhost:8180
# eureka.instance.ip-address=http://localhost:8180
dubbo.scan.base-packages=cn.ecpark.service.usergw.impl
dubbo.protocol.name=dubbo
dubbo.protocol.port=20999
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.config-center.address=zookeeper://127.0.0.1:2181
dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
# 这个链接Apollo非常有意义.
# 因为在一个线程内, 同时Connect Zookeeper 和 Apollo 会导致 Apollo可能超过3秒再加其他操作.Zookeeper会出现阻塞.
dubbo.consumer.timeout=5000
server.port=8888
logging.file=logs/log
yame.gateway.config=test-gateway5.yaml