diff --git a/usergw-service/src/main/java/META-INF/additional-spring-configuration-metadata.json b/usergw-service/src/main/java/META-INF/additional-spring-configuration-metadata.json index 99e2dc0..79fccbc 100644 --- a/usergw-service/src/main/java/META-INF/additional-spring-configuration-metadata.json +++ b/usergw-service/src/main/java/META-INF/additional-spring-configuration-metadata.json @@ -3,5 +3,10 @@ "name": "yame.gateway.config", "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" } ]} \ No newline at end of file diff --git a/usergw-service/src/main/java/cn/ecpark/service/usergw/biz/filters/bean/GenericServicePool.java b/usergw-service/src/main/java/cn/ecpark/service/usergw/biz/filters/bean/GenericServicePool.java index 99154e0..0d298e9 100644 --- a/usergw-service/src/main/java/cn/ecpark/service/usergw/biz/filters/bean/GenericServicePool.java +++ b/usergw-service/src/main/java/cn/ecpark/service/usergw/biz/filters/bean/GenericServicePool.java @@ -1,7 +1,10 @@ package cn.ecpark.service.usergw.biz.filters.bean; 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; /** @@ -9,17 +12,47 @@ import org.apache.dubbo.rpc.service.GenericService; */ public class GenericServicePool { - HashMap gsDictionary; + private class ReferenceConfigStore { + private ReferenceConfig ref; + private GenericService gs; + + public ReferenceConfigStore(ReferenceConfig 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 gsDictionary; public GenericServicePool() { - gsDictionary = new HashMap(); + gsDictionary = new HashMap(); + } + + @Override + protected void finalize() throws Throwable { + + for(Entry entry : gsDictionary.entrySet()) { + entry.getValue(). destroy(); + } + super.finalize(); } public GenericService get(String key) { - return gsDictionary.get(key); + return gsDictionary.get(key).get(); } - public void put(String key, GenericService genericService) { - gsDictionary.put(key, genericService); + public void put(String key, ReferenceConfig ref) { + ReferenceConfigStore refStore = new ReferenceConfigStore(ref); + gsDictionary.put(key, refStore); } } \ No newline at end of file diff --git a/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigApollo.java b/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigApollo.java index 112600a..ee7eb53 100644 --- a/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigApollo.java +++ b/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigApollo.java @@ -3,23 +3,25 @@ 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); + + private static final org.slf4j.Logger log = + org.slf4j.LoggerFactory.getLogger(ConfigApollo.class); // @ApolloConfig("gateway.yml") private Config config; @@ -28,10 +30,13 @@ public class ConfigApollo implements ConfigChangeListener { @Value("${apollo.meta:}") private String apolloMeta; - + @Value("${app.id:}") private String appID; + @Value("${apollo.namespace:}") + private String apolloNamespace; + private int tryConnect; public ConfigApollo() { @@ -39,15 +44,37 @@ public class ConfigApollo implements ConfigChangeListener { } public void Connect() { - if(this.isConnected() && this.tryConnect > 0) { - this.tryConnect --; - config = ConfigService.getConfig("gateway.yml"); - config.addChangeListener(this); + 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("") ) { + if (!this.appID.equals("") && !this.apolloMeta.equals("")) { return true; } return false; @@ -55,16 +82,16 @@ public class ConfigApollo implements ConfigChangeListener { // @ApolloConfigChangeListener("gateway.yml") // public void listenApolloChange(ConfigChangeEvent changeEvent) { - + // } @Override public void onChange(ConfigChangeEvent changeEvent) { - ConfigRefresh change = (ConfigRefresh)appContext.getBean(ConfigRefresh.class); + ConfigRefresh change = (ConfigRefresh) appContext.getBean(ConfigRefresh.class); change.notifyChanged(); } - /** + /** * @return Config return the config */ public Config getConfig() { diff --git a/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigGateway.java b/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigGateway.java index 16935b1..9dfec7d 100644 --- a/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigGateway.java +++ b/usergw-service/src/main/java/cn/ecpark/service/usergw/config/ConfigGateway.java @@ -22,6 +22,7 @@ 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; @@ -160,15 +161,22 @@ public class ConfigGateway implements RouteDefinitionLocator { private InputStream loadApolloConfig(ConfigApollo configApollo) { DefaultConfig config = (DefaultConfig) configApollo.getConfig(); try { - 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); - YmlConfigFile ymlConfigFile = (YmlConfigFile) configFile.get(cr); - String content = ymlConfigFile.getContent(); - log.info("Load Apollo YAML Config: \n{}", content); - return new ByteArrayInputStream(content.getBytes()); + 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) { @@ -394,7 +402,7 @@ public class ConfigGateway implements RouteDefinitionLocator { UriString += Extract.getReferenceConfigKey(reference); GenericServicePool gsPool = appContext.getBean(GenericServicePool.class); reference.setGeneric(true); - gsPool.put(UriString, reference.get()); + gsPool.put(UriString, reference); return UriString; } diff --git a/usergw-service/src/main/java/cn/ecpark/service/usergw/config/bean/ConfigBean.java b/usergw-service/src/main/java/cn/ecpark/service/usergw/config/bean/ConfigBean.java index d2a7462..0e58bfe 100644 --- a/usergw-service/src/main/java/cn/ecpark/service/usergw/config/bean/ConfigBean.java +++ b/usergw-service/src/main/java/cn/ecpark/service/usergw/config/bean/ConfigBean.java @@ -11,9 +11,10 @@ import reactor.core.publisher.Mono; @Component public class ConfigBean { + @Bean - ConfigApollo configApollo() { - return new ConfigApollo(); + KeyResolver ipResolver() { + return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString()); } @Bean @@ -22,14 +23,12 @@ public class ConfigBean { } @Bean - public DubboGatewayFilterFactory dubboFilterFactory() { - return new DubboGatewayFilterFactory(); + ConfigApollo configApollo() { + return new ConfigApollo(); } @Bean - KeyResolver ipResolver() { - return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString()); + public DubboGatewayFilterFactory dubboFilterFactory() { + return new DubboGatewayFilterFactory(); } - - } \ No newline at end of file diff --git a/usergw-service/src/main/resources/application.properties b/usergw-service/src/main/resources/application.properties index b37bb8e..683b2c2 100644 --- a/usergw-service/src/main/resources/application.properties +++ b/usergw-service/src/main/resources/application.properties @@ -1,8 +1,8 @@ spring.application.name=gateway - -# app.id=gateway -# apollo.meta=http://localhost:8180 +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 diff --git a/usergw-service/src/main/resources/test-gateway4.yaml b/usergw-service/src/main/resources/test-gateway4.yaml index 01c7412..0e0fb85 100644 --- a/usergw-service/src/main/resources/test-gateway4.yaml +++ b/usergw-service/src/main/resources/test-gateway4.yaml @@ -46,8 +46,8 @@ dubbo: - name: RequestRateLimiter args: key-resolver: '#{@ipResolver}' #SPEL表达式去的对应的bean - redis-rate-limiter.replenishRate: 40 # 令牌桶的容积 - redis-rate-limiter.burstCapacity: 80 # 流速 每秒 + redis-rate-limiter.replenishRate: 30 # 令牌桶的容积 + redis-rate-limiter.burstCapacity: 60 # 流速 每秒 # - name: RequestRateLimiter1 # args: diff --git a/usergw-service/src/main/resources/test-gateway5.yaml b/usergw-service/src/main/resources/test-gateway5.yaml new file mode 100644 index 0000000..9a3633d --- /dev/null +++ b/usergw-service/src/main/resources/test-gateway5.yaml @@ -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/hello + \ No newline at end of file diff --git a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig.java b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig.java index 1877ac6..bd623d0 100644 --- a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig.java +++ b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig.java @@ -7,6 +7,7 @@ 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.context.annotation.PropertySource; +import org.springframework.core.annotation.Order; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; diff --git a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig2.java b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig2.java index 967eaa0..64fffee 100644 --- a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig2.java +++ b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig2.java @@ -6,6 +6,7 @@ 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; diff --git a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig3.java b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig3.java index 787d1a1..e4379a2 100644 --- a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig3.java +++ b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig3.java @@ -10,6 +10,7 @@ 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; diff --git a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig4.java b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig4.java index 9d2786e..6d00513 100644 --- a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig4.java +++ b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig4.java @@ -1,3 +1,8 @@ + + + + + package cn.ecpark.service.usergw; 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.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; @@ -23,7 +29,7 @@ public class TestHttp2DubboConfig4 { private int serverPort; @Test - public void Test1RequestHttp2DubboSetHeader() { + public void Test1RedisLimit() { // Test Base Url for(int i = 0; i < 50;i++) { HttpClient client = HttpClient.create(); @@ -46,14 +52,5 @@ public class TestHttp2DubboConfig4 { } } - - - // @Test - // @SuppressWarnings("unchecked") - // public void Test3RestfulFilters() { - - - // } - } \ No newline at end of file diff --git a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig5.java b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig5.java index c69bf3b..22376ff 100644 --- a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig5.java +++ b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig5.java @@ -1,11 +1,13 @@ 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; @@ -16,44 +18,41 @@ 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/test4.properties", properties = {"apollo.meta=", "app.id="}) +@TestPropertySource(locations = "classpath:/resources/test5.properties") +@Ignore public class TestHttp2DubboConfig5 { @LocalServerPort private int serverPort; @Test - public void Test1RequestHttp2DubboSetHeader() { + public void Test1LoadApolloConfig() { // Test Base Url - for(int i = 0; i < 50;i++) { - HttpClient client = HttpClient.create(); - ResponseReceiver receiver; - String content; - - receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/hello") - .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(content, "Hello Dubbo"); - } else { - Assert.assertEquals(response.status().code(), 429); - } + + 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()); } - - } - - - // @Test - // @SuppressWarnings("unchecked") - // public void Test3RestfulFilters() { - + - // } - - -} \ No newline at end of file + 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()); + } +} diff --git a/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig6.java b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig6.java new file mode 100644 index 0000000..93558ab --- /dev/null +++ b/usergw-service/src/test/java/cn/ecpark/service/usergw/TestHttp2DubboConfig6.java @@ -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()); + } + } + + + + + +} + \ No newline at end of file diff --git a/usergw-service/src/test/java/resources/test5.properties b/usergw-service/src/test/java/resources/test5.properties new file mode 100644 index 0000000..c513743 --- /dev/null +++ b/usergw-service/src/test/java/resources/test5.properties @@ -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=1000 + +server.port=8888 + +logging.file=logs/log +yame.gateway.config=test-gateway5.yaml + + + + +