mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
commit
a6ec5c8f5b
@ -17,7 +17,6 @@
|
||||
package com.alibaba.cloud.dubbo.bootstrap;
|
||||
|
||||
import com.alibaba.cloud.dubbo.service.EchoService;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@ -28,6 +27,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Dubbo Spring Cloud Client Bootstrap.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@EnableDiscoveryClient
|
||||
@EnableAutoConfiguration
|
||||
|
@ -23,7 +23,6 @@ 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.DubboReference;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -53,6 +52,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
/**
|
||||
* Dubbo Spring Cloud Consumer Bootstrap.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@EnableDiscoveryClient
|
||||
@EnableAutoConfiguration
|
||||
|
@ -23,6 +23,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* Dubbo Spring Cloud Provider Bootstrap.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@EnableDiscoveryClient
|
||||
@EnableAutoConfiguration
|
||||
|
@ -31,7 +31,6 @@ import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -22,6 +22,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* Dubbo Spring Cloud Provider Bootstrap.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@EnableDiscoveryClient
|
||||
@EnableAutoConfiguration
|
||||
|
@ -20,7 +20,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
package com.alibaba.cloud.dubbo.bootstrap;
|
||||
|
||||
import com.alibaba.cloud.dubbo.service.EchoService;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@ -26,6 +25,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* Dubbo Spring Cloud Server Bootstrap.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@EnableDiscoveryClient
|
||||
@EnableAutoConfiguration
|
||||
|
@ -24,6 +24,8 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
/**
|
||||
* Dubbo Spring Cloud Servlet Gateway Bootstrap.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@EnableDiscoveryClient
|
||||
@EnableAutoConfiguration
|
||||
|
@ -28,71 +28,71 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class ConsulDataSourceProperties extends AbstractDataSourceProperties {
|
||||
|
||||
public ConsulDataSourceProperties(){
|
||||
super(ConsulDataSourceFactoryBean.class.getName());
|
||||
}
|
||||
public ConsulDataSourceProperties() {
|
||||
super(ConsulDataSourceFactoryBean.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* consul server host.
|
||||
*/
|
||||
private String host;
|
||||
/**
|
||||
* consul server host.
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* consul server port.
|
||||
*/
|
||||
private int port=8500;
|
||||
/**
|
||||
* consul server port.
|
||||
*/
|
||||
private int port = 8500;
|
||||
|
||||
/**
|
||||
* data key in Redis.
|
||||
*/
|
||||
private String ruleKey;
|
||||
/**
|
||||
* data key in Redis.
|
||||
*/
|
||||
private String ruleKey;
|
||||
|
||||
/**
|
||||
* Request of query will hang until timeout (in second) or get updated value.
|
||||
*/
|
||||
private int waitTimeoutInSecond = 1;
|
||||
/**
|
||||
* Request of query will hang until timeout (in second) or get updated value.
|
||||
*/
|
||||
private int waitTimeoutInSecond = 1;
|
||||
|
||||
@Override
|
||||
public void preCheck(String dataSourceName) {
|
||||
if(StringUtils.isEmpty(host)){
|
||||
throw new IllegalArgumentException(
|
||||
"ConsulDataSource server-host is empty");
|
||||
}
|
||||
if(StringUtils.isEmpty(ruleKey)){
|
||||
throw new IllegalArgumentException(
|
||||
"ConsulDataSource ruleKey can not be empty");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void preCheck(String dataSourceName) {
|
||||
if (StringUtils.isEmpty(host)) {
|
||||
throw new IllegalArgumentException("ConsulDataSource server-host is empty");
|
||||
}
|
||||
if (StringUtils.isEmpty(ruleKey)) {
|
||||
throw new IllegalArgumentException(
|
||||
"ConsulDataSource ruleKey can not be empty");
|
||||
}
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getRuleKey() {
|
||||
return ruleKey;
|
||||
}
|
||||
public String getRuleKey() {
|
||||
return ruleKey;
|
||||
}
|
||||
|
||||
public void setRuleKey(String ruleKey) {
|
||||
this.ruleKey = ruleKey;
|
||||
}
|
||||
public void setRuleKey(String ruleKey) {
|
||||
this.ruleKey = ruleKey;
|
||||
}
|
||||
|
||||
public int getWaitTimeoutInSecond() {
|
||||
return waitTimeoutInSecond;
|
||||
}
|
||||
public int getWaitTimeoutInSecond() {
|
||||
return waitTimeoutInSecond;
|
||||
}
|
||||
|
||||
public void setWaitTimeoutInSecond(int waitTimeoutInSecond) {
|
||||
this.waitTimeoutInSecond = waitTimeoutInSecond;
|
||||
}
|
||||
|
||||
public void setWaitTimeoutInSecond(int waitTimeoutInSecond) {
|
||||
this.waitTimeoutInSecond = waitTimeoutInSecond;
|
||||
}
|
||||
}
|
||||
|
@ -29,68 +29,64 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
*/
|
||||
public class ConsulDataSourceFactoryBean implements FactoryBean<ConsulDataSource> {
|
||||
|
||||
private String host;
|
||||
private String host;
|
||||
|
||||
private int port;
|
||||
private int port;
|
||||
|
||||
private String ruleKey;
|
||||
private String ruleKey;
|
||||
|
||||
private int waitTimeoutInSecond;
|
||||
private int waitTimeoutInSecond;
|
||||
|
||||
private Converter converter;
|
||||
private Converter converter;
|
||||
|
||||
@Override
|
||||
public ConsulDataSource getObject() throws Exception {
|
||||
return new ConsulDataSource(
|
||||
host,
|
||||
port,
|
||||
ruleKey,
|
||||
waitTimeoutInSecond,
|
||||
converter);
|
||||
}
|
||||
@Override
|
||||
public ConsulDataSource getObject() throws Exception {
|
||||
return new ConsulDataSource(host, port, ruleKey, waitTimeoutInSecond, converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return ConsulDataSource.class;
|
||||
}
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return ConsulDataSource.class;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getRuleKey() {
|
||||
return ruleKey;
|
||||
}
|
||||
public String getRuleKey() {
|
||||
return ruleKey;
|
||||
}
|
||||
|
||||
public void setRuleKey(String ruleKey) {
|
||||
this.ruleKey = ruleKey;
|
||||
}
|
||||
public void setRuleKey(String ruleKey) {
|
||||
this.ruleKey = ruleKey;
|
||||
}
|
||||
|
||||
public int getWaitTimeoutInSecond() {
|
||||
return waitTimeoutInSecond;
|
||||
}
|
||||
public int getWaitTimeoutInSecond() {
|
||||
return waitTimeoutInSecond;
|
||||
}
|
||||
|
||||
public void setWaitTimeoutInSecond(int waitTimeoutInSecond) {
|
||||
this.waitTimeoutInSecond = waitTimeoutInSecond;
|
||||
}
|
||||
public void setWaitTimeoutInSecond(int waitTimeoutInSecond) {
|
||||
this.waitTimeoutInSecond = waitTimeoutInSecond;
|
||||
}
|
||||
|
||||
public Converter getConverter() {
|
||||
return converter;
|
||||
}
|
||||
public Converter getConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
public void setConverter(Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public void setConverter(Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,8 @@ public class SentinelSCGAutoConfiguration {
|
||||
}
|
||||
|
||||
private void initAppType() {
|
||||
System.setProperty(SentinelConfig.APP_TYPE_PROP_KEY, ConfigConstants.APP_TYPE_SCG_GATEWAY);
|
||||
System.setProperty(SentinelConfig.APP_TYPE_PROP_KEY,
|
||||
ConfigConstants.APP_TYPE_SCG_GATEWAY);
|
||||
}
|
||||
|
||||
private void initFallback() {
|
||||
|
@ -131,15 +131,17 @@ public class ReactiveSentinelCircuitBreakerIntegrationTest {
|
||||
@Bean
|
||||
public Customizer<ReactiveSentinelCircuitBreakerFactory> slowCustomizer() {
|
||||
return factory -> {
|
||||
factory.configure(builder -> builder
|
||||
.rules(Collections.singletonList(new DegradeRule("slow_mono")
|
||||
.setCount(50).setSlowRatioThreshold(0.7).setMinRequestAmount(5)
|
||||
.setStatIntervalMs(30000).setTimeWindow(5))),
|
||||
factory.configure(
|
||||
builder -> builder.rules(Collections
|
||||
.singletonList(new DegradeRule("slow_mono").setCount(50)
|
||||
.setSlowRatioThreshold(0.7).setMinRequestAmount(5)
|
||||
.setStatIntervalMs(30000).setTimeWindow(5))),
|
||||
"slow_mono");
|
||||
factory.configure(builder -> builder
|
||||
.rules(Collections.singletonList(new DegradeRule("slow_mono")
|
||||
.setCount(50).setSlowRatioThreshold(0.7).setMinRequestAmount(5)
|
||||
.setStatIntervalMs(30000).setTimeWindow(5))),
|
||||
factory.configure(
|
||||
builder -> builder.rules(Collections
|
||||
.singletonList(new DegradeRule("slow_mono").setCount(50)
|
||||
.setSlowRatioThreshold(0.7).setMinRequestAmount(5)
|
||||
.setStatIntervalMs(30000).setTimeWindow(5))),
|
||||
"slow_flux");
|
||||
factory.configureDefault(id -> new SentinelConfigBuilder()
|
||||
.resourceName(id)
|
||||
|
@ -101,7 +101,8 @@ public class SentinelCircuitBreakerIntegrationTest {
|
||||
protected static class Application {
|
||||
|
||||
@GetMapping("/slow")
|
||||
public String slow(@RequestParam(required = false) Boolean slow) throws InterruptedException {
|
||||
public String slow(@RequestParam(required = false) Boolean slow)
|
||||
throws InterruptedException {
|
||||
if (slow == null || slow) {
|
||||
Thread.sleep(80);
|
||||
}
|
||||
@ -116,10 +117,10 @@ public class SentinelCircuitBreakerIntegrationTest {
|
||||
@Bean
|
||||
public Customizer<SentinelCircuitBreakerFactory> slowCustomizer() {
|
||||
String slowId = "slow";
|
||||
List<DegradeRule> rules = Collections.singletonList(
|
||||
new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT)
|
||||
.setCount(50).setSlowRatioThreshold(0.7).setMinRequestAmount(5)
|
||||
.setStatIntervalMs(30000).setTimeWindow(5));
|
||||
List<DegradeRule> rules = Collections.singletonList(new DegradeRule(slowId)
|
||||
.setGrade(RuleConstant.DEGRADE_GRADE_RT).setCount(50)
|
||||
.setSlowRatioThreshold(0.7).setMinRequestAmount(5)
|
||||
.setStatIntervalMs(30000).setTimeWindow(5));
|
||||
return factory -> {
|
||||
factory.configure(builder -> builder.rules(rules), slowId);
|
||||
factory.configureDefault(id -> new SentinelConfigBuilder()
|
||||
@ -146,7 +147,8 @@ public class SentinelCircuitBreakerIntegrationTest {
|
||||
|
||||
public String slow(boolean slow) {
|
||||
return cbFactory.create("slow").run(
|
||||
() -> rest.getForObject("/slow?slow=" + slow, String.class), t -> "fallback");
|
||||
() -> rest.getForObject("/slow?slow=" + slow, String.class),
|
||||
t -> "fallback");
|
||||
}
|
||||
|
||||
public String normal() {
|
||||
|
@ -106,12 +106,12 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- <!– Eureka Service Discovery –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.cloud</groupId>-->
|
||||
<!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
|
||||
<!-- <scope>test</scope>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- Eureka Service Discovery -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Zookeeper Service Discovery -->
|
||||
<dependency>
|
||||
@ -147,20 +147,20 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- <!– Spring Cloud Consul –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.cloud</groupId>-->
|
||||
<!-- <artifactId>spring-cloud-starter-consul-discovery</artifactId>-->
|
||||
<!-- <version>${spring-cloud-consul.version}</version>-->
|
||||
<!-- <scope>test</scope>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- Spring Cloud Consul -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
|
||||
<version>${spring-cloud-consul.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- <!– Nacos Service Discovery –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.alibaba.cloud</groupId>-->
|
||||
<!-- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>-->
|
||||
<!-- <scope>test</scope>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- Nacos Service Discovery -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* 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
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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,
|
||||
@ -14,21 +13,22 @@
|
||||
* 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
|
||||
* The constants of Dubbo Cloud Gateway.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public interface DubboCloudGatewayConstants {
|
||||
public abstract class DubboCloudGatewayConstants {
|
||||
|
||||
/**
|
||||
* The property prefix of Configuration
|
||||
* The property prefix of Configuration.
|
||||
*/
|
||||
String CONFIG_PROPERTY_PREFIX = DubboCloudConstants.CONFIG_PROPERTY_PREFIX
|
||||
public static final String CONFIG_PROPERTY_PREFIX = DubboCloudConstants.CONFIG_PROPERTY_PREFIX
|
||||
+ ".gateway";
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* 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
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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,
|
||||
@ -14,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.dubbo.gateway;
|
||||
|
||||
import java.net.URI;
|
||||
@ -30,7 +30,6 @@ import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContextFactor
|
||||
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;
|
||||
|
||||
@ -46,10 +45,10 @@ 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
|
||||
* result of execution of the generic invocation to the Dubbo service providers.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DubboCloudGatewayExecutor {
|
||||
|
||||
@ -71,12 +70,12 @@ public class DubboCloudGatewayExecutor {
|
||||
DubboGenericServiceFactory serviceFactory,
|
||||
DubboGenericServiceExecutionContextFactory contextFactory,
|
||||
DubboCloudGatewayProperties dubboCloudGatewayProperties,
|
||||
ObjectProvider<ConversionService> conversionServices) {
|
||||
ObjectProvider<ConversionService> conversionService) {
|
||||
this.repository = repository;
|
||||
this.serviceFactory = serviceFactory;
|
||||
this.contextFactory = contextFactory;
|
||||
this.dubboCloudGatewayProperties = dubboCloudGatewayProperties;
|
||||
this.conversionService = conversionServices
|
||||
this.conversionService = conversionService
|
||||
.getIfAvailable(DefaultFormattingConversionService::new);
|
||||
// TODO : Replace these hard-code configurations
|
||||
this.dubboTranslatedAttributes.put("protocol", "dubbo");
|
||||
@ -145,8 +144,7 @@ public class DubboCloudGatewayExecutor {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO : Get the Request Body from HttpRequest
|
||||
*
|
||||
* TODO : Get the Request Body from HttpRequest.
|
||||
* @param request {@link HttpRequest}
|
||||
* @return
|
||||
*/
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* 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
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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,
|
||||
@ -14,6 +13,7 @@
|
||||
* 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;
|
||||
@ -21,7 +21,7 @@ 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
|
||||
* The Configuration Properties for Dubbo Cloud Gateway.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@ -29,12 +29,12 @@ import static com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayConstants.CONFIG_
|
||||
public class DubboCloudGatewayProperties {
|
||||
|
||||
/**
|
||||
* Enabled or not
|
||||
* Enabled or not.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* The context path for the gateway request mapping
|
||||
* The context path for the gateway request mapping.
|
||||
*/
|
||||
private String contextPath = "";
|
||||
|
||||
@ -53,4 +53,5 @@ public class DubboCloudGatewayProperties {
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* 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
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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,
|
||||
@ -14,6 +13,7 @@
|
||||
* 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;
|
||||
@ -34,7 +34,8 @@ 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)
|
||||
@ConditionalOnProperty(prefix = "dubbo.cloud.gateway", name = "enabled",
|
||||
havingValue = "true", matchIfMissing = true)
|
||||
@AutoConfigureAfter({ DubboServiceAutoConfiguration.class,
|
||||
DubboMetadataAutoConfiguration.class })
|
||||
@EnableConfigurationProperties(DubboCloudGatewayProperties.class)
|
||||
@ -51,4 +52,5 @@ public class DubboCloudGatewayAutoConfiguration {
|
||||
return new DubboCloudGatewayExecutor(repository, serviceFactory, contextFactory,
|
||||
dubboCloudGatewayProperties, conversionServices);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* 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
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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,
|
||||
@ -14,13 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.cloud.dubbo.gateway.standard;
|
||||
|
||||
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.gateway.autoconfigure.DubboCloudGatewayAutoConfiguration;
|
||||
import com.alibaba.cloud.dubbo.gateway.bootstrap.DubboSpringCloudGatewayFilter;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@ -38,13 +38,14 @@ import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.http.codec.support.DefaultServerCodecConfigurer;
|
||||
|
||||
/**
|
||||
* The Auto-{@link Configuration} of Dubbo Spring Cloud Gateway
|
||||
* 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)
|
||||
@ConditionalOnProperty(prefix = "dubbo.cloud.gateway", name = "enabled",
|
||||
havingValue = "true", matchIfMissing = true)
|
||||
@AutoConfigureAfter({ DubboServiceAutoConfiguration.class,
|
||||
DubboMetadataAutoConfiguration.class, DubboCloudGatewayAutoConfiguration.class })
|
||||
@EnableConfigurationProperties(DubboCloudGatewayProperties.class)
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* 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
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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,
|
||||
@ -14,7 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.cloud.dubbo.gateway.standard;
|
||||
|
||||
package com.alibaba.cloud.dubbo.gateway.bootstrap;
|
||||
|
||||
import com.alibaba.cloud.dubbo.gateway.DubboCloudGatewayExecutor;
|
||||
import org.apache.commons.logging.Log;
|
||||
@ -29,7 +29,7 @@ import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* The Spring Cloud {@link GatewayFilter Gateway Filter} for Dubbo
|
||||
* The Spring Cloud {@link GatewayFilter Gateway Filter} for Dubbo.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
@ -1,3 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.alibaba.cloud.dubbo.gateway.autoconfigure.DubboCloudGatewayAutoConfiguration,\
|
||||
com.alibaba.cloud.dubbo.gateway.standard.DubboSpringCloudGatewayAutoConfiguration
|
||||
com.alibaba.cloud.dubbo.gateway.autoconfigure.DubboSpringCloudGatewayAutoConfiguration
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.bootstrap;
|
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
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>
|
||||
*/
|
||||
@EnableAutoConfiguration
|
||||
@EnableDiscoveryClient
|
||||
public final class DubboSpringCloudGatewayBootstrap {
|
||||
|
||||
private DubboSpringCloudGatewayBootstrap() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(DubboSpringCloudGatewayBootstrap.class)
|
||||
.properties("spring.profiles.active=nacos").run(args);
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
@ -1,74 +1,7 @@
|
||||
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
|
||||
port: 9090
|
@ -0,0 +1,66 @@
|
||||
spring:
|
||||
application:
|
||||
name: spring-cloud-alibaba-dubbo-gateway
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
|
||||
|
||||
# default disable all
|
||||
cloud:
|
||||
nacos:
|
||||
username: nacos
|
||||
password: nacos
|
||||
discovery:
|
||||
enabled: false
|
||||
register-enabled: false
|
||||
zookeeper:
|
||||
enabled: false
|
||||
consul:
|
||||
enabled: false
|
||||
|
||||
eureka:
|
||||
client:
|
||||
enabled: false
|
||||
|
||||
|
||||
---
|
||||
spring:
|
||||
profiles: nacos
|
||||
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
enabled: true
|
||||
register-enabled: true
|
||||
server-addr: 127.0.0.1:8848
|
||||
|
||||
|
||||
---
|
||||
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
|
@ -1,6 +1,6 @@
|
||||
<?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"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
|
@ -17,18 +17,18 @@
|
||||
package com.alibaba.cloud.dubbo.autoconfigure;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.alibaba.cloud.dubbo.metadata.DubboProtocolConfigSupplier;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.MetadataServiceInstanceSelector;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.RandomServiceInstanceSelector;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.ServiceInstanceSelector;
|
||||
import com.alibaba.cloud.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver;
|
||||
import com.alibaba.cloud.dubbo.metadata.resolver.MetadataResolver;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataServiceExporter;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy;
|
||||
import com.alibaba.cloud.dubbo.service.IntrospectiveDubboMetadataService;
|
||||
import com.alibaba.cloud.dubbo.util.DubboMetadataUtils;
|
||||
import com.alibaba.cloud.dubbo.util.JSONUtils;
|
||||
import feign.Contract;
|
||||
import org.apache.dubbo.config.ProtocolConfig;
|
||||
@ -44,7 +44,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Spring Boot Auto-Configuration class for Dubbo Metadata.
|
||||
@ -53,7 +52,8 @@ import org.springframework.util.CollectionUtils;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import({ DubboServiceMetadataRepository.class, IntrospectiveDubboMetadataService.class,
|
||||
DubboMetadataServiceExporter.class, JSONUtils.class })
|
||||
DubboMetadataServiceExporter.class, JSONUtils.class,
|
||||
DubboMetadataServiceProxy.class, DubboMetadataUtils.class })
|
||||
public class DubboMetadataAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
@ -73,9 +73,8 @@ public class DubboMetadataAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MetadataServiceInstanceSelector metadataServiceInstanceSelector() {
|
||||
return serviceInstances -> CollectionUtils.isEmpty(serviceInstances)
|
||||
? Optional.empty() : serviceInstances.stream().findAny();
|
||||
public ServiceInstanceSelector metadataServiceInstanceSelector() {
|
||||
return new RandomServiceInstanceSelector();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ -84,15 +83,7 @@ public class DubboMetadataAutoConfiguration {
|
||||
return new DubboProtocolConfigSupplier(protocols);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DubboMetadataServiceProxy dubboMetadataConfigServiceProxy(
|
||||
DubboGenericServiceFactory factory) {
|
||||
return new DubboMetadataServiceProxy(factory);
|
||||
}
|
||||
|
||||
// Event-Handling
|
||||
|
||||
@EventListener(ServiceBeanExportedEvent.class)
|
||||
public void onServiceBeanExported(ServiceBeanExportedEvent event) {
|
||||
ServiceBean serviceBean = event.getServiceBean();
|
||||
|
@ -56,6 +56,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@ -135,6 +136,9 @@ public class DubboServiceDiscoveryAutoConfiguration {
|
||||
*/
|
||||
private final ObjectProvider<Predicate<HeartbeatEvent>> heartbeatEventChangedPredicate;
|
||||
|
||||
@Value("${spring.application.name:${dubbo.application.name:application}}")
|
||||
private String currentApplicationName;
|
||||
|
||||
public DubboServiceDiscoveryAutoConfiguration(
|
||||
DubboServiceMetadataRepository dubboServiceMetadataRepository,
|
||||
ApplicationEventPublisher applicationEventPublisher,
|
||||
@ -154,10 +158,12 @@ public class DubboServiceDiscoveryAutoConfiguration {
|
||||
* NotifyListener)
|
||||
*/
|
||||
private void dispatchServiceInstancesChangedEvent(String serviceName,
|
||||
Collection<ServiceInstance> serviceInstances) {
|
||||
if (!hasText(serviceName) || serviceInstances == null) {
|
||||
List<ServiceInstance> serviceInstances) {
|
||||
if (!hasText(serviceName) || Objects.equals(currentApplicationName, serviceName)
|
||||
|| serviceInstances == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent(serviceName,
|
||||
serviceInstances);
|
||||
if (logger.isInfoEnabled()) {
|
||||
|
@ -23,6 +23,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 com.alibaba.cloud.dubbo.util.DubboCloudConstants.DUBBO_CLOUD_REGISTRY_PROPERTY_VALUE;
|
||||
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
import static org.springframework.util.StringUtils.trimAllWhitespace;
|
||||
@ -48,6 +49,8 @@ public class DubboCloudProperties {
|
||||
*/
|
||||
private String subscribedServices = ALL_DUBBO_SERVICES;
|
||||
|
||||
private String registryType = DUBBO_CLOUD_REGISTRY_PROPERTY_VALUE;
|
||||
|
||||
public String getSubscribedServices() {
|
||||
return subscribedServices;
|
||||
}
|
||||
@ -80,4 +83,12 @@ public class DubboCloudProperties {
|
||||
return Collections.unmodifiableSet(subscribedServices);
|
||||
}
|
||||
|
||||
public String getRegistryType() {
|
||||
return registryType;
|
||||
}
|
||||
|
||||
public void setRegistryType(String registryType) {
|
||||
this.registryType = registryType;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,9 +22,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@ -38,6 +36,7 @@ import com.alibaba.cloud.dubbo.registry.event.SubscribedServicesChangedEvent;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataService;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataServiceExporter;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy;
|
||||
import com.alibaba.cloud.dubbo.util.DubboMetadataUtils;
|
||||
import com.alibaba.cloud.dubbo.util.JSONUtils;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
@ -61,15 +60,15 @@ import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static com.alibaba.cloud.dubbo.env.DubboCloudProperties.ALL_DUBBO_SERVICES;
|
||||
import static com.alibaba.cloud.dubbo.http.DefaultHttpRequest.builder;
|
||||
import static java.lang.String.format;
|
||||
import static java.lang.String.valueOf;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
|
||||
import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_PREFIX;
|
||||
import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME;
|
||||
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
@ -85,14 +84,15 @@ public class DubboServiceMetadataRepository
|
||||
/**
|
||||
* The prefix of {@link DubboMetadataService} : "dubbo.metadata-service.".
|
||||
*/
|
||||
public static final String DUBBO_METADATA_SERVICE_PREFIX = "dubbo.metadata-service.";
|
||||
@Deprecated
|
||||
public static final String DUBBO_METADATA_SERVICE_PREFIX = METADATA_SERVICE_PREFIX;
|
||||
|
||||
/**
|
||||
* The {@link URL URLs} property name of {@link DubboMetadataService} :
|
||||
* "dubbo.metadata-service.urls".
|
||||
*/
|
||||
public static final String DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME = DUBBO_METADATA_SERVICE_PREFIX
|
||||
+ "urls";
|
||||
@Deprecated
|
||||
public static final String DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME = METADATA_SERVICE_URLS_PROPERTY_NAME;
|
||||
|
||||
/**
|
||||
* The {@link String#format(String, Object...) pattern} of dubbo protocols port.
|
||||
@ -108,11 +108,6 @@ public class DubboServiceMetadataRepository
|
||||
*/
|
||||
private final Object monitor = new Object();
|
||||
|
||||
/**
|
||||
* A {@link Set} of service names that had been initialized.
|
||||
*/
|
||||
private final Set<String> initializedServices = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* All exported {@link URL urls} {@link Map} whose key is the return value of
|
||||
* {@link URL#getServiceKey()} method and value is the {@link List} of {@link URL
|
||||
@ -122,12 +117,6 @@ public class DubboServiceMetadataRepository
|
||||
|
||||
// =================================== Registration
|
||||
// =================================== //
|
||||
/**
|
||||
* The subscribed {@link URL urls} {@link Map} of {@link DubboMetadataService}, whose
|
||||
* key is the return value of {@link URL#getServiceKey()} method and value is the
|
||||
* {@link List} of {@link URL URLs}.
|
||||
*/
|
||||
private final MultiValueMap<String, URL> subscribedDubboMetadataServiceURLs = new LinkedMultiValueMap<>();
|
||||
|
||||
// ====================================================================================
|
||||
// //
|
||||
@ -172,7 +161,7 @@ public class DubboServiceMetadataRepository
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
@Autowired
|
||||
private MetadataServiceInstanceSelector metadataServiceInstanceSelector;
|
||||
private ServiceInstanceSelector serviceInstanceSelector;
|
||||
|
||||
@Autowired
|
||||
private JSONUtils jsonUtils;
|
||||
@ -180,6 +169,9 @@ public class DubboServiceMetadataRepository
|
||||
@Autowired
|
||||
private InetUtils inetUtils;
|
||||
|
||||
@Autowired
|
||||
private DubboMetadataUtils dubboMetadataUtils;
|
||||
|
||||
@Value("${spring.application.name}")
|
||||
private String currentApplicationName;
|
||||
|
||||
@ -275,28 +267,11 @@ public class DubboServiceMetadataRepository
|
||||
* @param serviceName service of name
|
||||
*/
|
||||
public void initializeMetadata(String serviceName) {
|
||||
synchronized (monitor) {
|
||||
if (initializedServices.contains(serviceName)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"The metadata of Dubbo service[name : {}] has been initialized",
|
||||
serviceName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(
|
||||
"The metadata of Dubbo service[name : {}] is about to be initialized",
|
||||
serviceName);
|
||||
}
|
||||
initDubboRestServiceMetadataRepository(serviceName);
|
||||
}
|
||||
|
||||
if (initSubscribedDubboMetadataService(serviceName)) {
|
||||
// mark this service name having been initialized
|
||||
initializedServices.add(serviceName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
private DubboMetadataService getProxy(String serviceName) {
|
||||
return dubboMetadataConfigServiceProxy.getProxy(serviceName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,15 +282,8 @@ public class DubboServiceMetadataRepository
|
||||
*/
|
||||
public void removeMetadataAndInitializedService(String serviceName, URL url) {
|
||||
synchronized (monitor) {
|
||||
initializedServices.remove(serviceName);
|
||||
dubboMetadataConfigServiceProxy.removeProxy(serviceName);
|
||||
dubboRestServiceMetadataRepository.remove(serviceName);
|
||||
// fix #1260 if the subscribedDubboMetadataServiceURLs removed fail,old meta
|
||||
// information will be retained
|
||||
if (DubboMetadataService.class.getName().equals(url.getServiceInterface())) {
|
||||
String serviceKey = url.getServiceKey();
|
||||
subscribedDubboMetadataServiceURLs.remove(serviceKey);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,8 +313,7 @@ public class DubboServiceMetadataRepository
|
||||
private void addDubboMetadataServiceURLsMetadata(Map<String, String> metadata,
|
||||
List<URL> dubboMetadataServiceURLs) {
|
||||
String dubboMetadataServiceURLsJSON = jsonUtils.toJSON(dubboMetadataServiceURLs);
|
||||
metadata.put(DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME,
|
||||
dubboMetadataServiceURLsJSON);
|
||||
metadata.put(METADATA_SERVICE_URLS_PROPERTY_NAME, dubboMetadataServiceURLsJSON);
|
||||
}
|
||||
|
||||
private void addDubboProtocolsPortMetadata(Map<String, String> metadata) {
|
||||
@ -359,15 +326,6 @@ public class DubboServiceMetadataRepository
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the property name of Dubbo Protocol.
|
||||
* @param protocol Dubbo Protocol
|
||||
* @return non-null
|
||||
*/
|
||||
public String getDubboProtocolPropertyName(String protocol) {
|
||||
return format(DUBBO_PROTOCOLS_PORT_PROPERTY_NAME_PATTERN, protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish the {@link Set} of {@link ServiceRestMetadata}.
|
||||
* @param serviceRestMetadataSet the {@link Set} of {@link ServiceRestMetadata}
|
||||
@ -389,25 +347,6 @@ public class DubboServiceMetadataRepository
|
||||
return unmodifiableSet(serviceRestMetadata);
|
||||
}
|
||||
|
||||
public List<URL> findSubscribedDubboMetadataServiceURLs(String serviceName,
|
||||
String group, String version, String protocol) {
|
||||
String serviceKey = URL.buildKey(serviceName, group, version);
|
||||
|
||||
List<URL> urls = null;
|
||||
|
||||
synchronized (monitor) {
|
||||
urls = subscribedDubboMetadataServiceURLs.get(serviceKey);
|
||||
}
|
||||
|
||||
if (isEmpty(urls)) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
return hasText(protocol) ? urls.stream()
|
||||
.filter(url -> url.getProtocol().equalsIgnoreCase(protocol))
|
||||
.collect(Collectors.toList()) : unmodifiableList(urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* The specified service is subscribe or not.
|
||||
* @param serviceName the service name
|
||||
@ -457,24 +396,13 @@ public class DubboServiceMetadataRepository
|
||||
return allExportedURLs.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link URL urls} that {@link DubboMetadataService} exported by the
|
||||
* specified {@link ServiceInstance}.
|
||||
* @param serviceInstance {@link ServiceInstance}
|
||||
* @return the mutable {@link URL urls}
|
||||
*/
|
||||
public List<URL> getDubboMetadataServiceURLs(ServiceInstance serviceInstance) {
|
||||
Map<String, String> metadata = serviceInstance.getMetadata();
|
||||
String dubboURLsJSON = metadata.get(DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME);
|
||||
return jsonUtils.toURLs(dubboURLsJSON);
|
||||
}
|
||||
|
||||
public Integer getDubboProtocolPort(ServiceInstance serviceInstance,
|
||||
String protocol) {
|
||||
String protocolProperty = getDubboProtocolPropertyName(protocol);
|
||||
Map<String, String> metadata = serviceInstance.getMetadata();
|
||||
String protocolPort = metadata.get(protocolProperty);
|
||||
return hasText(protocolPort) ? Integer.valueOf(protocolPort) : null;
|
||||
return dubboMetadataUtils.getDubboProtocolPort(serviceInstance, protocol);
|
||||
}
|
||||
|
||||
private String getDubboProtocolPropertyName(String protocol) {
|
||||
return dubboMetadataUtils.getDubboProtocolPropertyName(protocol);
|
||||
}
|
||||
|
||||
public List<URL> getExportedURLs(String serviceInterface, String group,
|
||||
@ -490,6 +418,11 @@ public class DubboServiceMetadataRepository
|
||||
protected void initDubboRestServiceMetadataRepository(String serviceName) {
|
||||
|
||||
if (dubboRestServiceMetadataRepository.containsKey(serviceName)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"The metadata of Dubbo service[name : {}] has been initialized",
|
||||
serviceName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -598,8 +531,7 @@ public class DubboServiceMetadataRepository
|
||||
|
||||
Set<ServiceRestMetadata> metadata = emptySet();
|
||||
|
||||
DubboMetadataService dubboMetadataService = dubboMetadataConfigServiceProxy
|
||||
.getProxy(serviceName);
|
||||
DubboMetadataService dubboMetadataService = getProxy(serviceName);
|
||||
|
||||
if (dubboMetadataService != null) {
|
||||
try {
|
||||
@ -624,68 +556,29 @@ public class DubboServiceMetadataRepository
|
||||
subscribedServices.remove(currentApplicationName);
|
||||
}
|
||||
|
||||
protected Boolean initSubscribedDubboMetadataService(String serviceName) {
|
||||
// this need to judge whether the initialization is successful or not. The failed
|
||||
// initialization will not change the initializedServices
|
||||
Optional<ServiceInstance> optionalServiceInstance = metadataServiceInstanceSelector
|
||||
.choose(discoveryClient.getInstances(serviceName));
|
||||
if (!((Optional) optionalServiceInstance).isPresent()) {
|
||||
return false;
|
||||
}
|
||||
ServiceInstance serviceInstance = optionalServiceInstance.get();
|
||||
if (null == serviceInstance) {
|
||||
return false;
|
||||
}
|
||||
List<URL> dubboMetadataServiceURLs = getDubboMetadataServiceURLs(serviceInstance);
|
||||
if (dubboMetadataServiceURLs.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (URL dubboMetadataServiceURL : dubboMetadataServiceURLs) {
|
||||
try {
|
||||
initSubscribedDubboMetadataServiceURL(dubboMetadataServiceURL);
|
||||
DubboMetadataService dubboMetadataService = dubboMetadataConfigServiceProxy
|
||||
.getProxy(serviceName);
|
||||
if (dubboMetadataService == null) {
|
||||
dubboMetadataService = initDubboMetadataServiceProxy(
|
||||
dubboMetadataServiceURL);
|
||||
}
|
||||
|
||||
if (dubboMetadataService == null) {
|
||||
removeMetadataAndInitializedService(serviceName,
|
||||
dubboMetadataServiceURL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
initDubboRestServiceMetadataRepository(serviceName);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initSubscribedDubboMetadataServiceURL(URL dubboMetadataServiceURL) {
|
||||
// add subscriptions
|
||||
String serviceKey = dubboMetadataServiceURL.getServiceKey();
|
||||
subscribedDubboMetadataServiceURLs.add(serviceKey, dubboMetadataServiceURL);
|
||||
}
|
||||
|
||||
private DubboMetadataService initDubboMetadataServiceProxy(
|
||||
URL dubboMetadataServiceURL) {
|
||||
String serviceName = dubboMetadataServiceURL.getParameter(APPLICATION_KEY);
|
||||
String version = dubboMetadataServiceURL.getParameter(VERSION_KEY);
|
||||
// Initialize DubboMetadataService with right version
|
||||
return dubboMetadataConfigServiceProxy.initProxy(serviceName, version);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
public List<URL> findSubscribedDubboMetadataServiceURLs(URL subscribedURL) {
|
||||
// The parameter of "group" as the service name
|
||||
String serviceInterface = subscribedURL.getServiceInterface();
|
||||
String group = subscribedURL.getParameter(GROUP_KEY);
|
||||
String version = subscribedURL.getParameter(VERSION_KEY);
|
||||
String protocol = subscribedURL.getParameter(PROTOCOL_KEY);
|
||||
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(group);
|
||||
List<URL> urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances,
|
||||
serviceInterface, version, protocol);
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(
|
||||
"The DubboMetadataService of service [name : {} , instances : {}] URLs[protocol : {} , size : {}] has been subscribed.",
|
||||
group, serviceInstances.size(), protocol, urls.size());
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.metadata.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
|
||||
import static java.util.Optional.of;
|
||||
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
|
||||
/**
|
||||
* Random {@link ServiceInstanceSelector}.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public class RandomServiceInstanceSelector implements ServiceInstanceSelector {
|
||||
|
||||
@Override
|
||||
public Optional<ServiceInstance> select(List<ServiceInstance> serviceInstances) {
|
||||
if (isEmpty(serviceInstances)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
return of(serviceInstances.get(random.nextInt(serviceInstances.size())));
|
||||
}
|
||||
|
||||
}
|
@ -26,13 +26,13 @@ import org.springframework.cloud.client.ServiceInstance;
|
||||
*
|
||||
* @author <a href="mailto:liuxx-u@outlook.com">liuxx</a>
|
||||
*/
|
||||
public interface MetadataServiceInstanceSelector {
|
||||
public interface ServiceInstanceSelector {
|
||||
|
||||
/**
|
||||
* choose a service instance to get metadata.
|
||||
* Select a service instance to get metadata.
|
||||
* @param serviceInstances all service instance
|
||||
* @return the service instance to get metadata
|
||||
*/
|
||||
Optional<ServiceInstance> choose(List<ServiceInstance> serviceInstances);
|
||||
Optional<ServiceInstance> select(List<ServiceInstance> serviceInstances);
|
||||
|
||||
}
|
@ -63,6 +63,7 @@ import static org.springframework.util.StringUtils.hasText;
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractSpringCloudRegistry extends FailbackRegistry {
|
||||
|
||||
/**
|
||||
@ -370,12 +371,7 @@ public abstract class AbstractSpringCloudRegistry extends FailbackRegistry {
|
||||
}
|
||||
|
||||
private void subscribeDubboMetadataServiceURLs(URL url, NotifyListener listener) {
|
||||
String serviceInterface = url.getServiceInterface();
|
||||
String group = url.getParameter(GROUP_KEY);
|
||||
String version = url.getParameter(VERSION_KEY);
|
||||
String protocol = url.getParameter(PROTOCOL_KEY);
|
||||
List<URL> urls = repository.findSubscribedDubboMetadataServiceURLs(
|
||||
serviceInterface, group, version, protocol);
|
||||
List<URL> urls = repository.findSubscribedDubboMetadataServiceURLs(url);
|
||||
listener.notify(urls);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,511 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.registry;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||
import com.alibaba.cloud.dubbo.registry.event.ServiceInstancesChangedEvent;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataService;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy;
|
||||
import com.alibaba.cloud.dubbo.util.DubboMetadataUtils;
|
||||
import com.alibaba.cloud.dubbo.util.JSONUtils;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.URLBuilder;
|
||||
import org.apache.dubbo.registry.NotifyListener;
|
||||
import org.apache.dubbo.registry.support.FailbackRegistry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.stream.StreamSupport.stream;
|
||||
import static org.apache.dubbo.common.URLBuilder.from;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
|
||||
import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
|
||||
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
|
||||
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
|
||||
import static org.apache.dubbo.registry.Constants.ADMIN_PROTOCOL;
|
||||
import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* Dubbo Cloud {@link FailbackRegistry} is based on Spring Cloud {@link DiscoveryClient}.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public class DubboCloudRegistry extends FailbackRegistry {
|
||||
|
||||
/**
|
||||
* The parameter name of {@link #servicesLookupInterval}.
|
||||
*/
|
||||
public static final String SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.services.lookup.interval";
|
||||
|
||||
protected static final String DUBBO_METADATA_SERVICE_CLASS_NAME = DubboMetadataService.class
|
||||
.getName();
|
||||
|
||||
/**
|
||||
* Caches the IDs of {@link ApplicationListener}.
|
||||
*/
|
||||
private static final Set<String> registerListeners = new HashSet<>();
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final DiscoveryClient discoveryClient;
|
||||
|
||||
private final DubboServiceMetadataRepository repository;
|
||||
|
||||
private final DubboMetadataServiceProxy dubboMetadataConfigServiceProxy;
|
||||
|
||||
private final JSONUtils jsonUtils;
|
||||
|
||||
private final DubboGenericServiceFactory dubboGenericServiceFactory;
|
||||
|
||||
private final DubboMetadataUtils dubboMetadataUtils;
|
||||
|
||||
/**
|
||||
* The interval in second of lookup service names(only for Dubbo-OPS).
|
||||
*/
|
||||
private final long servicesLookupInterval;
|
||||
|
||||
private final ConfigurableApplicationContext applicationContext;
|
||||
|
||||
private final String currentApplicationName;
|
||||
|
||||
public DubboCloudRegistry(URL url, DiscoveryClient discoveryClient,
|
||||
DubboServiceMetadataRepository repository,
|
||||
DubboMetadataServiceProxy dubboMetadataConfigServiceProxy,
|
||||
JSONUtils jsonUtils, DubboGenericServiceFactory dubboGenericServiceFactory,
|
||||
ConfigurableApplicationContext applicationContext) {
|
||||
|
||||
super(url);
|
||||
this.servicesLookupInterval = url
|
||||
.getParameter(SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 60L);
|
||||
this.discoveryClient = discoveryClient;
|
||||
this.repository = repository;
|
||||
this.dubboMetadataConfigServiceProxy = dubboMetadataConfigServiceProxy;
|
||||
this.jsonUtils = jsonUtils;
|
||||
this.dubboGenericServiceFactory = dubboGenericServiceFactory;
|
||||
this.applicationContext = applicationContext;
|
||||
this.dubboMetadataUtils = getBean(DubboMetadataUtils.class);
|
||||
this.currentApplicationName = dubboMetadataUtils.getCurrentApplicationName();
|
||||
}
|
||||
|
||||
private <T> T getBean(Class<T> beanClass) {
|
||||
return this.applicationContext.getBean(beanClass);
|
||||
}
|
||||
|
||||
protected boolean shouldRegister(URL url) {
|
||||
String side = url.getParameter(SIDE_KEY);
|
||||
|
||||
boolean should = PROVIDER_SIDE.equals(side); // Only register the Provider.
|
||||
|
||||
if (!should) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("The URL[{}] should not be registered.", url.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return should;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void doRegister(URL url) {
|
||||
if (!shouldRegister(url)) {
|
||||
return;
|
||||
}
|
||||
repository.exportURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void doUnregister(URL url) {
|
||||
if (!shouldRegister(url)) {
|
||||
return;
|
||||
}
|
||||
repository.unexportURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void doSubscribe(URL url, NotifyListener listener) {
|
||||
|
||||
if (isAdminURL(url)) {
|
||||
// TODO in future
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("This feature about admin will be supported in the future.");
|
||||
}
|
||||
}
|
||||
else if (isDubboMetadataServiceURL(url)) { // for DubboMetadataService
|
||||
subscribeDubboMetadataServiceURLs(url, listener);
|
||||
}
|
||||
else { // for general Dubbo Services
|
||||
subscribeURLs(url, listener);
|
||||
}
|
||||
}
|
||||
|
||||
private void subscribeURLs(URL url, NotifyListener listener) {
|
||||
|
||||
// Sync subscription
|
||||
subscribeURLs(url, getServices(url), listener);
|
||||
|
||||
// Async subscription
|
||||
registerServiceInstancesChangedListener(url, event -> {
|
||||
|
||||
Set<String> serviceNames = getServices(url);
|
||||
|
||||
String serviceName = event.getServiceName();
|
||||
|
||||
if (serviceNames.contains(serviceName)) {
|
||||
subscribeURLs(url, serviceNames, listener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void subscribeURLs(URL url, Set<String> serviceNames,
|
||||
NotifyListener listener) {
|
||||
|
||||
List<URL> subscribedURLs = new LinkedList<>();
|
||||
|
||||
serviceNames.forEach(serviceName -> {
|
||||
|
||||
subscribeURLs(url, subscribedURLs, serviceName,
|
||||
() -> getServiceInstances(serviceName));
|
||||
|
||||
});
|
||||
|
||||
// Notify all
|
||||
notifyAllSubscribedURLs(url, subscribedURLs, listener);
|
||||
}
|
||||
|
||||
private void registerServiceInstancesChangedListener(URL url,
|
||||
ApplicationListener<ServiceInstancesChangedEvent> listener) {
|
||||
String listenerId = generateId(url);
|
||||
if (registerListeners.add(listenerId)) {
|
||||
applicationContext.addApplicationListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
private void subscribeURLs(URL subscribedURL, List<URL> subscribedURLs,
|
||||
String serviceName,
|
||||
Supplier<List<ServiceInstance>> serviceInstancesSupplier) {
|
||||
List<ServiceInstance> serviceInstances = serviceInstancesSupplier.get();
|
||||
subscribeURLs(subscribedURL, subscribedURLs, serviceName, serviceInstances);
|
||||
}
|
||||
|
||||
private void subscribeURLs(URL subscribedURL, List<URL> subscribedURLs,
|
||||
String serviceName, List<ServiceInstance> serviceInstances) {
|
||||
|
||||
if (CollectionUtils.isEmpty(serviceInstances)) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(format("There is no instance in service[name : %s]",
|
||||
serviceName));
|
||||
}
|
||||
}
|
||||
|
||||
List<URL> exportedURLs = getExportedURLs(subscribedURL, serviceName,
|
||||
serviceInstances);
|
||||
|
||||
/**
|
||||
* Add the exported URLs from {@link MetadataService}
|
||||
*/
|
||||
subscribedURLs.addAll(exportedURLs);
|
||||
}
|
||||
|
||||
private List<URL> getExportedURLs(URL subscribedURL, String serviceName,
|
||||
List<ServiceInstance> serviceInstances) {
|
||||
|
||||
List<ServiceInstance> validServiceInstances = filter(serviceInstances);
|
||||
|
||||
// If there is no valid ServiceInstance, return empty result
|
||||
if (isEmpty(validServiceInstances)) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(
|
||||
"There is no instance from service[name : {}], and then Dubbo Service[key : {}] will not be "
|
||||
+ "available , please make sure the further impact",
|
||||
serviceName, subscribedURL.getServiceKey());
|
||||
}
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
List<URL> subscribedURLs = cloneExportedURLs(subscribedURL, serviceInstances);
|
||||
|
||||
// clear local service instances, help GC
|
||||
validServiceInstances.clear();
|
||||
|
||||
return subscribedURLs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the subscribed URLs based on the template URLs.
|
||||
* @param subscribedURL the URL to be subscribed
|
||||
* @param serviceInstances the list of {@link ServiceInstance service instances}
|
||||
* @return non-null
|
||||
*/
|
||||
private List<URL> cloneExportedURLs(URL subscribedURL,
|
||||
List<ServiceInstance> serviceInstances) {
|
||||
|
||||
List<URL> clonedExportedURLs = new LinkedList<>();
|
||||
|
||||
serviceInstances.forEach(serviceInstance -> {
|
||||
|
||||
String host = serviceInstance.getHost();
|
||||
|
||||
getTemplateExportedURLs(subscribedURL, serviceInstances).stream()
|
||||
.map(templateURL -> templateURL.removeParameter(TIMESTAMP_KEY))
|
||||
.map(templateURL -> templateURL.removeParameter(PID_KEY))
|
||||
.map(templateURL -> {
|
||||
String protocol = templateURL.getProtocol();
|
||||
int port = repository.getDubboProtocolPort(serviceInstance,
|
||||
protocol);
|
||||
if (Objects.equals(templateURL.getHost(), host)
|
||||
&& Objects.equals(templateURL.getPort(), port)) { // use
|
||||
// templateURL
|
||||
// if
|
||||
// equals
|
||||
return templateURL;
|
||||
}
|
||||
|
||||
URLBuilder clonedURLBuilder = from(templateURL) // remove the
|
||||
// parameters from
|
||||
// the template
|
||||
// URL
|
||||
.setHost(host) // reset the host
|
||||
.setPort(port); // reset the port
|
||||
|
||||
return clonedURLBuilder.build();
|
||||
}).forEach(clonedExportedURLs::add);
|
||||
});
|
||||
return clonedExportedURLs;
|
||||
}
|
||||
|
||||
private List<URL> getTemplateExportedURLs(URL subscribedURL,
|
||||
List<ServiceInstance> serviceInstances) {
|
||||
|
||||
DubboMetadataService dubboMetadataService = getProxy(serviceInstances);
|
||||
|
||||
List<URL> templateExportedURLs = emptyList();
|
||||
|
||||
if (dubboMetadataService != null) {
|
||||
templateExportedURLs = getExportedURLs(dubboMetadataService, subscribedURL);
|
||||
}
|
||||
else {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(
|
||||
"The metadata of Dubbo service[key : {}] still can't be found, it could effect the further "
|
||||
+ "Dubbo service invocation",
|
||||
subscribedURL.getServiceKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return templateExportedURLs;
|
||||
}
|
||||
|
||||
private DubboMetadataService getProxy(List<ServiceInstance> serviceInstances) {
|
||||
return dubboMetadataConfigServiceProxy.getProxy(serviceInstances);
|
||||
}
|
||||
|
||||
private List<ServiceInstance> filter(Collection<ServiceInstance> serviceInstances) {
|
||||
return serviceInstances.stream().filter(this::isDubboServiceInstance)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean isDubboServiceInstance(ServiceInstance serviceInstance) {
|
||||
Map<String, String> metadata = serviceInstance.getMetadata();
|
||||
return metadata.containsKey(METADATA_SERVICE_URLS_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
private Set<String> getServices(URL url) {
|
||||
Set<String> subscribedServices = repository.getSubscribedServices();
|
||||
// TODO Add the filter feature
|
||||
return subscribedServices;
|
||||
}
|
||||
|
||||
private void notifyAllSubscribedURLs(URL url, List<URL> subscribedURLs,
|
||||
NotifyListener listener) {
|
||||
|
||||
if (isEmpty(subscribedURLs)) {
|
||||
// Add the EMPTY_PROTOCOL URL
|
||||
subscribedURLs.add(emptyURL(url));
|
||||
|
||||
if (isDubboMetadataServiceURL(url)) {
|
||||
// if meta service change, and serviceInstances is zero, will clean up
|
||||
// information about this client
|
||||
String serviceName = url.getParameter(GROUP_KEY);
|
||||
repository.removeMetadataAndInitializedService(serviceName, url);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("The subscribed URL[{}] will notify all URLs : {}", url,
|
||||
subscribedURLs);
|
||||
}
|
||||
|
||||
// Notify all
|
||||
listener.notify(subscribedURLs);
|
||||
}
|
||||
|
||||
private List<ServiceInstance> getServiceInstances(Iterable<String> serviceNames) {
|
||||
return stream(serviceNames.spliterator(), false).map(this::getServiceInstances)
|
||||
.flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<ServiceInstance> getServiceInstances(String serviceName) {
|
||||
return hasText(serviceName) ? doGetServiceInstances(serviceName) : emptyList();
|
||||
}
|
||||
|
||||
private List<ServiceInstance> doGetServiceInstances(String serviceName) {
|
||||
List<ServiceInstance> serviceInstances = emptyList();
|
||||
try {
|
||||
serviceInstances = discoveryClient.getInstances(serviceName);
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return serviceInstances;
|
||||
}
|
||||
|
||||
private String generateId(URL url) {
|
||||
return url.getServiceKey();
|
||||
}
|
||||
|
||||
private URL emptyURL(URL url) {
|
||||
// issue : When the last service provider is closed, the client still periodically
|
||||
// connects to the last provider.n
|
||||
// fix https://github.com/alibaba/spring-cloud-alibaba/issues/1259
|
||||
return from(url).setProtocol(EMPTY_PROTOCOL).removeParameter(CATEGORY_KEY)
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<URL> getExportedURLs(DubboMetadataService dubboMetadataService,
|
||||
URL subscribedURL) {
|
||||
String serviceInterface = subscribedURL.getServiceInterface();
|
||||
String group = subscribedURL.getParameter(GROUP_KEY);
|
||||
String version = subscribedURL.getParameter(VERSION_KEY);
|
||||
// The subscribed protocol may be null
|
||||
String subscribedProtocol = subscribedURL.getParameter(PROTOCOL_KEY);
|
||||
String exportedURLsJSON = dubboMetadataService.getExportedURLs(serviceInterface,
|
||||
group, version);
|
||||
return jsonUtils.toURLs(exportedURLsJSON).stream()
|
||||
.filter(exportedURL -> subscribedProtocol == null
|
||||
|| subscribedProtocol.equalsIgnoreCase(exportedURL.getProtocol()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void subscribeDubboMetadataServiceURLs(URL subscribedURL,
|
||||
NotifyListener listener) {
|
||||
|
||||
// Sync subscription
|
||||
subscribeDubboMetadataServiceURLs(subscribedURL, listener,
|
||||
getServiceName(subscribedURL));
|
||||
|
||||
// Sync subscription
|
||||
if (containsProviderCategory(subscribedURL)) {
|
||||
registerServiceInstancesChangedListener(subscribedURL, event -> {
|
||||
|
||||
String sourceServiceName = event.getServiceName();
|
||||
String serviceName = getServiceName(subscribedURL);
|
||||
|
||||
if (Objects.equals(sourceServiceName, serviceName)) {
|
||||
subscribeDubboMetadataServiceURLs(subscribedURL, listener,
|
||||
sourceServiceName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private String getServiceName(URL subscribedURL) {
|
||||
return subscribedURL.getParameter(GROUP_KEY);
|
||||
}
|
||||
|
||||
private void subscribeDubboMetadataServiceURLs(URL subscribedURL,
|
||||
NotifyListener listener, String serviceName) {
|
||||
|
||||
String serviceInterface = subscribedURL.getServiceInterface();
|
||||
String version = subscribedURL.getParameter(VERSION_KEY);
|
||||
String protocol = subscribedURL.getParameter(PROTOCOL_KEY);
|
||||
|
||||
List<ServiceInstance> serviceInstances = getServiceInstances(serviceName);
|
||||
|
||||
List<URL> urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances,
|
||||
serviceInterface, version, protocol);
|
||||
|
||||
notifyAllSubscribedURLs(subscribedURL, urls, listener);
|
||||
}
|
||||
|
||||
// private void subscribeDubboMetadataServiceURLs(URL subscribedURL,
|
||||
// NotifyListener listener, Set<String> serviceNames) {
|
||||
//
|
||||
// String serviceInterface = subscribedURL.getServiceInterface();
|
||||
// String version = subscribedURL.getParameter(VERSION_KEY);
|
||||
// String protocol = subscribedURL.getParameter(PROTOCOL_KEY);
|
||||
//
|
||||
// List<ServiceInstance> serviceInstances = getServiceInstances(serviceNames);
|
||||
//
|
||||
// List<URL> urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances,
|
||||
// serviceInterface, version, protocol);
|
||||
//
|
||||
// notifyAllSubscribedURLs(subscribedURL, urls, listener);
|
||||
// }
|
||||
|
||||
private boolean containsProviderCategory(URL subscribedURL) {
|
||||
String category = subscribedURL.getParameter(CATEGORY_KEY);
|
||||
return category == null ? false : category.contains(PROVIDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void doUnsubscribe(URL url, NotifyListener listener) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return !discoveryClient.getServices().isEmpty();
|
||||
}
|
||||
|
||||
protected boolean isAdminURL(URL url) {
|
||||
return ADMIN_PROTOCOL.equals(url.getProtocol());
|
||||
}
|
||||
|
||||
protected boolean isDubboMetadataServiceURL(URL url) {
|
||||
return DUBBO_METADATA_SERVICE_CLASS_NAME.equals(url.getServiceInterface());
|
||||
}
|
||||
|
||||
}
|
@ -31,7 +31,10 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
* protocol is "spring-cloud".
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
* @deprecated It's a legacy and not recommended implementation, being replacing to be
|
||||
* {@link DubboCloudRegistry}
|
||||
*/
|
||||
@Deprecated
|
||||
public class SpringCloudRegistry extends AbstractSpringCloudRegistry {
|
||||
|
||||
private final DubboServiceMetadataRepository dubboServiceMetadataRepository;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.cloud.dubbo.registry;
|
||||
|
||||
import com.alibaba.cloud.dubbo.env.DubboCloudProperties;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy;
|
||||
@ -28,7 +29,7 @@ import org.apache.dubbo.registry.support.AbstractRegistryFactory;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import static java.lang.System.getProperty;
|
||||
import static com.alibaba.cloud.dubbo.util.DubboCloudConstants.SPRING_CLOUD_REGISTRY_PROPERTY_VALUE;
|
||||
|
||||
/**
|
||||
* Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose
|
||||
@ -50,10 +51,6 @@ public class SpringCloudRegistryFactory extends AbstractRegistryFactory {
|
||||
*/
|
||||
public static String ADDRESS = "localhost";
|
||||
|
||||
private static String SERVICES_LOOKUP_SCHEDULER_THREAD_NAME_PREFIX = getProperty(
|
||||
"dubbo.services.lookup.scheduler.thread.name.prefix ",
|
||||
"dubbo-services-lookup-");
|
||||
|
||||
private static ConfigurableApplicationContext applicationContext;
|
||||
|
||||
private DiscoveryClient discoveryClient;
|
||||
@ -88,9 +85,26 @@ public class SpringCloudRegistryFactory extends AbstractRegistryFactory {
|
||||
@Override
|
||||
public Registry createRegistry(URL url) {
|
||||
init();
|
||||
return new SpringCloudRegistry(url, discoveryClient,
|
||||
dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy,
|
||||
jsonUtils, dubboGenericServiceFactory, applicationContext);
|
||||
|
||||
DubboCloudProperties dubboCloudProperties = applicationContext
|
||||
.getBean(DubboCloudProperties.class);
|
||||
|
||||
Registry registry = null;
|
||||
|
||||
switch (dubboCloudProperties.getRegistryType()) {
|
||||
case SPRING_CLOUD_REGISTRY_PROPERTY_VALUE:
|
||||
registry = new SpringCloudRegistry(url, discoveryClient,
|
||||
dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy,
|
||||
jsonUtils, dubboGenericServiceFactory, applicationContext);
|
||||
break;
|
||||
default:
|
||||
registry = new DubboCloudRegistry(url, discoveryClient,
|
||||
dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy,
|
||||
jsonUtils, dubboGenericServiceFactory, applicationContext);
|
||||
break;
|
||||
}
|
||||
|
||||
return registry;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
package com.alibaba.cloud.dubbo.registry.event;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.event.ApplicationEventMulticaster;
|
||||
import org.springframework.context.event.SimpleApplicationEventMulticaster;
|
||||
|
||||
import static java.util.Collections.unmodifiableCollection;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
|
||||
/**
|
||||
* An event raised after the {@link ServiceInstance instances} of one service has been
|
||||
@ -35,7 +35,7 @@ public class ServiceInstancesChangedEvent extends ApplicationEvent {
|
||||
|
||||
private final String serviceName;
|
||||
|
||||
private final Collection<ServiceInstance> serviceInstances;
|
||||
private final List<ServiceInstance> serviceInstances;
|
||||
|
||||
/**
|
||||
* Current event has been processed or not. Typically, Spring Event was based on sync
|
||||
@ -51,10 +51,10 @@ public class ServiceInstancesChangedEvent extends ApplicationEvent {
|
||||
* @throws IllegalArgumentException if source is null.
|
||||
*/
|
||||
public ServiceInstancesChangedEvent(String serviceName,
|
||||
Collection<ServiceInstance> serviceInstances) {
|
||||
List<ServiceInstance> serviceInstances) {
|
||||
super(serviceName);
|
||||
this.serviceName = serviceName;
|
||||
this.serviceInstances = unmodifiableCollection(serviceInstances);
|
||||
this.serviceInstances = unmodifiableList(serviceInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +67,7 @@ public class ServiceInstancesChangedEvent extends ApplicationEvent {
|
||||
/**
|
||||
* @return all {@link ServiceInstance service instances}.
|
||||
*/
|
||||
public Collection<ServiceInstance> getServiceInstances() {
|
||||
public List<ServiceInstance> getServiceInstances() {
|
||||
return serviceInstances;
|
||||
}
|
||||
|
||||
|
@ -95,10 +95,9 @@ public class DubboGenericServiceFactory {
|
||||
private ReferenceBean<GenericService> build(String interfaceName, String version,
|
||||
String group, Map<String, Object> dubboTranslatedAttributes) {
|
||||
|
||||
Integer key = Objects.hash(interfaceName, version, group,
|
||||
dubboTranslatedAttributes);
|
||||
String key = createKey(interfaceName, version, group, dubboTranslatedAttributes);
|
||||
|
||||
return cache.computeIfAbsent(group + key, k -> {
|
||||
return cache.computeIfAbsent(key, k -> {
|
||||
ReferenceBean<GenericService> referenceBean = new ReferenceBean<>();
|
||||
referenceBean.setGeneric(true);
|
||||
referenceBean.setInterface(interfaceName);
|
||||
@ -110,6 +109,12 @@ public class DubboGenericServiceFactory {
|
||||
});
|
||||
}
|
||||
|
||||
private String createKey(String interfaceName, String version, String group,
|
||||
Map<String, Object> dubboTranslatedAttributes) {
|
||||
return group + "#"
|
||||
+ Objects.hash(interfaceName, version, group, dubboTranslatedAttributes);
|
||||
}
|
||||
|
||||
private void bindReferenceBean(ReferenceBean<GenericService> referenceBean,
|
||||
Map<String, Object> dubboTranslatedAttributes) {
|
||||
DataBinder dataBinder = new DataBinder(referenceBean);
|
||||
@ -155,7 +160,7 @@ public class DubboGenericServiceFactory {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public synchronized void destroy(String serviceName) {
|
||||
public void destroy(String serviceName) {
|
||||
Set<String> removeGroups = new HashSet<>(cache.keySet());
|
||||
for (String key : removeGroups) {
|
||||
if (key.contains(serviceName)) {
|
||||
|
@ -16,13 +16,26 @@
|
||||
|
||||
package com.alibaba.cloud.dubbo.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.ServiceInstanceSelector;
|
||||
import com.alibaba.cloud.dubbo.util.DubboMetadataUtils;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
|
||||
import static java.lang.reflect.Proxy.newProxyInstance;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
|
||||
|
||||
/**
|
||||
* The proxy of {@link DubboMetadataService}.
|
||||
@ -31,26 +44,30 @@ import static java.lang.reflect.Proxy.newProxyInstance;
|
||||
*/
|
||||
public class DubboMetadataServiceProxy implements BeanClassLoaderAware, DisposableBean {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final DubboGenericServiceFactory dubboGenericServiceFactory;
|
||||
|
||||
private final DubboMetadataUtils dubboMetadataUtils;
|
||||
|
||||
private final ServiceInstanceSelector serviceInstanceSelector;
|
||||
|
||||
private final DiscoveryClient discoveryClient;
|
||||
|
||||
private final Map<String, DubboMetadataService> dubboMetadataServiceCache = new ConcurrentHashMap<>();
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
public DubboMetadataServiceProxy(
|
||||
DubboGenericServiceFactory dubboGenericServiceFactory) {
|
||||
DubboGenericServiceFactory dubboGenericServiceFactory,
|
||||
DubboServiceMetadataRepository dubboServiceMetadataRepository,
|
||||
DubboMetadataUtils dubboMetadataUtils,
|
||||
ServiceInstanceSelector serviceInstanceSelector,
|
||||
DiscoveryClient discoveryClient) {
|
||||
this.dubboGenericServiceFactory = dubboGenericServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes {@link DubboMetadataService}'s Proxy.
|
||||
* @param serviceName the service name
|
||||
* @param version the service version
|
||||
* @return a {@link DubboMetadataService} proxy
|
||||
*/
|
||||
public DubboMetadataService initProxy(String serviceName, String version) {
|
||||
return dubboMetadataServiceCache.computeIfAbsent(serviceName,
|
||||
name -> newProxy(name, version));
|
||||
this.dubboMetadataUtils = dubboMetadataUtils;
|
||||
this.serviceInstanceSelector = serviceInstanceSelector;
|
||||
this.discoveryClient = discoveryClient;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,6 +76,79 @@ public class DubboMetadataServiceProxy implements BeanClassLoaderAware, Disposab
|
||||
*/
|
||||
public void removeProxy(String serviceName) {
|
||||
dubboMetadataServiceCache.remove(serviceName);
|
||||
dubboGenericServiceFactory.destroy(serviceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the proxy of {@link DubboMetadataService} if possible.
|
||||
* @param serviceInstances the instances of {@link DubboMetadataService}
|
||||
* @return <code>null</code> if initialization can't be done
|
||||
*/
|
||||
public DubboMetadataService getProxy(List<ServiceInstance> serviceInstances) {
|
||||
|
||||
DubboMetadataService dubboMetadataService = null;
|
||||
|
||||
// attempt to get the proxy of DubboMetadataService in maximum times
|
||||
int attempts = serviceInstances.size();
|
||||
|
||||
for (int i = 0; i < attempts; i++) {
|
||||
Optional<ServiceInstance> serviceInstance = select(serviceInstances);
|
||||
|
||||
if (serviceInstance.isPresent()) {
|
||||
|
||||
List<URL> dubboMetadataServiceURLs = getDubboMetadataServiceURLs(
|
||||
serviceInstance.get());
|
||||
|
||||
for (URL dubboMetadataServiceURL : dubboMetadataServiceURLs) {
|
||||
dubboMetadataService = createProxyIfAbsent(dubboMetadataServiceURL);
|
||||
if (dubboMetadataService != null) {
|
||||
return dubboMetadataService;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dubboMetadataService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the {@link DubboMetadataService}'s Proxy initialized or not.
|
||||
* @param serviceName the service name
|
||||
* @return <code>true</code> if initialized , or return <code>false</code>
|
||||
*/
|
||||
public boolean isInitialized(String serviceName) {
|
||||
return dubboMetadataServiceCache.containsKey(serviceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link DubboMetadataService}'s Proxy If abstract.
|
||||
* @param dubboMetadataServiceURL the {@link URL} of {@link DubboMetadataService}
|
||||
* @return a {@link DubboMetadataService} proxy
|
||||
*/
|
||||
private DubboMetadataService createProxyIfAbsent(URL dubboMetadataServiceURL) {
|
||||
String serviceName = dubboMetadataServiceURL.getParameter(APPLICATION_KEY);
|
||||
String version = dubboMetadataServiceURL.getParameter(VERSION_KEY);
|
||||
// Initialize DubboMetadataService with right version
|
||||
return createProxyIfAbsent(serviceName, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes {@link DubboMetadataService}'s Proxy.
|
||||
* @param serviceName the service name
|
||||
* @param version the service version
|
||||
* @return a {@link DubboMetadataService} proxy
|
||||
*/
|
||||
private DubboMetadataService createProxyIfAbsent(String serviceName, String version) {
|
||||
return dubboMetadataServiceCache.computeIfAbsent(serviceName,
|
||||
name -> createProxy(name, version));
|
||||
}
|
||||
|
||||
private Optional<ServiceInstance> select(List<ServiceInstance> serviceInstances) {
|
||||
return serviceInstanceSelector.select(serviceInstances);
|
||||
}
|
||||
|
||||
private List<URL> getDubboMetadataServiceURLs(ServiceInstance serviceInstance) {
|
||||
return dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,7 +158,12 @@ public class DubboMetadataServiceProxy implements BeanClassLoaderAware, Disposab
|
||||
* @return a {@link DubboMetadataService} proxy
|
||||
*/
|
||||
public DubboMetadataService getProxy(String serviceName) {
|
||||
return dubboMetadataServiceCache.get(serviceName);
|
||||
return dubboMetadataServiceCache.getOrDefault(serviceName,
|
||||
getProxy0(serviceName));
|
||||
}
|
||||
|
||||
private DubboMetadataService getProxy0(String serviceName) {
|
||||
return getProxy(discoveryClient.getInstances(serviceName));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -88,7 +183,14 @@ public class DubboMetadataServiceProxy implements BeanClassLoaderAware, Disposab
|
||||
* @param version the service version
|
||||
* @return a {@link DubboMetadataService} proxy
|
||||
*/
|
||||
protected DubboMetadataService newProxy(String serviceName, String version) {
|
||||
protected DubboMetadataService createProxy(String serviceName, String version) {
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(
|
||||
"The metadata of Dubbo service[name : {}] is about to be initialized",
|
||||
serviceName);
|
||||
}
|
||||
|
||||
return (DubboMetadataService) newProxyInstance(classLoader,
|
||||
new Class[] { DubboMetadataService.class },
|
||||
new DubboMetadataServiceInvocationHandler(serviceName, version,
|
||||
|
@ -23,13 +23,29 @@ package com.alibaba.cloud.dubbo.util;
|
||||
*/
|
||||
public final class DubboCloudConstants {
|
||||
|
||||
private DubboCloudConstants() {
|
||||
throw new AssertionError("Must not instantiate constant utility class");
|
||||
}
|
||||
|
||||
/**
|
||||
* The property prefix of Configuration.
|
||||
*/
|
||||
public static final String CONFIG_PROPERTY_PREFIX = "dubbo.cloud";
|
||||
|
||||
/**
|
||||
* The property name of Registry type.
|
||||
*/
|
||||
public static final String REGISTRY_TYPE_PROPERTY_NAME = CONFIG_PROPERTY_PREFIX
|
||||
+ ".registry-type";
|
||||
|
||||
/**
|
||||
* The property value of Spring Cloud Registry.
|
||||
*/
|
||||
public static final String SPRING_CLOUD_REGISTRY_PROPERTY_VALUE = "spring-cloud";
|
||||
|
||||
/**
|
||||
* The property value of Dubbo Cloud Registry.
|
||||
*/
|
||||
public static final String DUBBO_CLOUD_REGISTRY_PROPERTY_VALUE = "dubbo-cloud";
|
||||
|
||||
private DubboCloudConstants() {
|
||||
throw new AssertionError("Must not instantiate constant utility class");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.alibaba.cloud.dubbo.service.DubboMetadataService;
|
||||
import org.apache.dubbo.common.URL;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
|
||||
import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* The utilities class of Dubbo Metadata.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public class DubboMetadataUtils {
|
||||
|
||||
/**
|
||||
* The {@link String#format(String, Object...) pattern} of dubbo protocols port.
|
||||
*/
|
||||
public static final String DUBBO_PROTOCOLS_PORT_PROPERTY_NAME_PATTERN = "dubbo.protocols.%s.port";
|
||||
|
||||
private final JSONUtils jsonUtils;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final String currentApplicationName;
|
||||
|
||||
public DubboMetadataUtils(JSONUtils jsonUtils, Environment environment) {
|
||||
this.jsonUtils = jsonUtils;
|
||||
this.environment = environment;
|
||||
this.currentApplicationName = environment.getProperty("spring.application.name",
|
||||
environment.getProperty("dubbo.application.name", "application"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current application name.
|
||||
* @return non-null
|
||||
*/
|
||||
public String getCurrentApplicationName() {
|
||||
return currentApplicationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link URL urls} that {@link DubboMetadataService} exported by the
|
||||
* specified {@link ServiceInstance}.
|
||||
* @param serviceInstance {@link ServiceInstance}
|
||||
* @return the mutable {@link URL urls}
|
||||
*/
|
||||
public List<URL> getDubboMetadataServiceURLs(ServiceInstance serviceInstance) {
|
||||
Map<String, String> metadata = serviceInstance.getMetadata();
|
||||
String dubboURLsJSON = metadata.get(METADATA_SERVICE_URLS_PROPERTY_NAME);
|
||||
return jsonUtils.toURLs(dubboURLsJSON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link URL urls} that {@link DubboMetadataService} exported by the
|
||||
* specified {@link ServiceInstance ServiceInstances}.
|
||||
* @param serviceInstances the list of {@link ServiceInstance ServiceInstances}
|
||||
* @param serviceInterface the interface name of Dubbo service
|
||||
* @param version the version of Dubbo service
|
||||
* @param protocol the protocol that Dubbo Service exports
|
||||
* @return the mutable {@link URL urls}
|
||||
*/
|
||||
public List<URL> getDubboMetadataServiceURLs(List<ServiceInstance> serviceInstances,
|
||||
String serviceInterface, String version, String protocol) {
|
||||
return serviceInstances.stream().map(this::getDubboMetadataServiceURLs)
|
||||
.flatMap(List::stream)
|
||||
.filter(url -> protocol == null
|
||||
|| Objects.equals(protocol, url.getProtocol()))
|
||||
.filter(url -> Objects.equals(serviceInterface,
|
||||
url.getServiceInterface()))
|
||||
.filter(url -> Objects.equals(version, url.getParameter(VERSION_KEY)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the property name of Dubbo Protocol.
|
||||
* @param protocol Dubbo Protocol
|
||||
* @return non-null
|
||||
*/
|
||||
public String getDubboProtocolPropertyName(String protocol) {
|
||||
return format(DUBBO_PROTOCOLS_PORT_PROPERTY_NAME_PATTERN, protocol);
|
||||
}
|
||||
|
||||
public Integer getDubboProtocolPort(ServiceInstance serviceInstance,
|
||||
String protocol) {
|
||||
String protocolProperty = getDubboProtocolPropertyName(protocol);
|
||||
Map<String, String> metadata = serviceInstance.getMetadata();
|
||||
String protocolPort = metadata.get(protocolProperty);
|
||||
return hasText(protocolPort) ? Integer.valueOf(protocolPort) : null;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
# Dubbo Endpoints Default Properties is loaded by @PropertySource with low order,
|
||||
# Set enabled for Dubbo Endpoints
|
||||
management.endpoint.dubborestmetadata.enabled = true
|
||||
|
||||
management.endpoint.dubborestmetadata.enabled=true
|
||||
# "management.endpoints.web.base-path" should not be configured in this file
|
||||
# Re-defines path-mapping of Dubbo Web Endpoints
|
||||
management.endpoints.web.path-mapping.dubborestmetadata = dubbo/rest/metadata
|
||||
management.endpoints.web.path-mapping.dubborestmetadata=dubbo/rest/metadata
|
||||
|
@ -6,12 +6,9 @@ com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationNonWebApplicationA
|
||||
com.alibaba.cloud.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\
|
||||
com.alibaba.cloud.dubbo.autoconfigure.DubboServiceAutoConfiguration,\
|
||||
com.alibaba.cloud.dubbo.autoconfigure.DubboServiceDiscoveryAutoConfiguration
|
||||
|
||||
org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=\
|
||||
com.alibaba.cloud.dubbo.actuate.DubboMetadataEndpointAutoConfiguration
|
||||
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
com.alibaba.cloud.dubbo.context.DubboServiceRegistrationApplicationContextInitializer
|
||||
|
||||
org.springframework.boot.env.EnvironmentPostProcessor=\
|
||||
com.alibaba.cloud.dubbo.env.DubboNonWebApplicationEnvironmentPostProcessor
|
@ -169,8 +169,8 @@ public class RocketMQMessageChannelBinder extends
|
||||
rocketMQTemplate, destination.getName(), producerGroup,
|
||||
producerProperties.getExtension().getTransactional(),
|
||||
instrumentationManager, producerProperties,
|
||||
((AbstractMessageChannel) channel).getInterceptors().stream()
|
||||
.filter(channelInterceptor -> channelInterceptor instanceof MessageConverterConfigurer.PartitioningInterceptor)
|
||||
((AbstractMessageChannel) channel).getInterceptors().stream().filter(
|
||||
channelInterceptor -> channelInterceptor instanceof MessageConverterConfigurer.PartitioningInterceptor)
|
||||
.map(channelInterceptor -> ((MessageConverterConfigurer.PartitioningInterceptor) channelInterceptor))
|
||||
.findFirst().orElse(null));
|
||||
messageHandler.setBeanFactory(this.getApplicationContext().getBeanFactory());
|
||||
|
Loading…
x
Reference in New Issue
Block a user