1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

Merge pull request #1759 from mercyblitz/finchley

[CodeBase] 2.0.3.RELEASE
This commit is contained in:
Mercy Ma 2020-09-21 22:17:44 +08:00 committed by GitHub
commit 9fc6a1d256
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 2089 additions and 1162 deletions

1
.gitignore vendored
View File

@ -31,4 +31,5 @@ hs_err_pid*
.settings
target
.DS_Store
.flattened-pom.xml

View File

@ -80,7 +80,7 @@
<properties>
<!-- Project revision -->
<revision>2.0.2.RELEASE</revision>
<revision>2.0.3.RELEASE</revision>
<!-- Dependency Versions -->
<spring-cloud-commons.version>2.0.4.RELEASE</spring-cloud-commons.version>

View File

@ -18,12 +18,13 @@
<description>Spring Cloud Alibaba Dependencies</description>
<properties>
<revision>2.0.2.RELEASE</revision>
<sentinel.version>1.7.1</sentinel.version>
<seata.version>1.1.0</seata.version>
<nacos.client.version>1.2.1</nacos.client.version>
<revision>2.0.3.RELEASE</revision>
<sentinel.version>1.8.0</sentinel.version>
<seata.version>1.3.0</seata.version>
<nacos.client.version>1.3.3</nacos.client.version>
<nacos.config.version>0.8.0</nacos.config.version>
<spring.context.support.version>1.0.6</spring.context.support.version>
<spring.context.support.version>1.0.10</spring.context.support.version>
<!-- Maven Plugin Versions -->
<maven-source-plugin.version>2.2.1</maven-source-plugin.version>

View File

@ -10,7 +10,7 @@ Spring Cloud Alibaba BOM 包含了它所使用的所有依赖的版本。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.0.2.RELEASE</version>
<version>2.0.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>

View File

@ -8,7 +8,7 @@ If youre a Maven Central user, add our BOM to your pom.xml <dependencyManagem
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.0.2.RELEASE</version>
<version>2.0.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>

View File

@ -32,6 +32,10 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties {
private String serverAddr;
private String username;
private String password;
@NotEmpty
private String groupId = "DEFAULT_GROUP";
@ -67,6 +71,22 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties {
this.serverAddr = serverAddr;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGroupId() {
return groupId;
}

View File

@ -93,7 +93,7 @@ public class RedisDataSourceProperties extends AbstractDataSourceProperties {
"RedisDataSource channel can not be empty");
}
if (!StringUtils.isEmpty(masterId) && StringUtils.isEmpty(masterId)) {
if (StringUtils.isEmpty(masterId)) {
throw new IllegalArgumentException(
"RedisDataSource sentinel modelmasterId can not be empty");
}

View File

@ -35,6 +35,10 @@ public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource>
private String serverAddr;
private String username;
private String password;
private String groupId;
private String dataId;
@ -63,6 +67,12 @@ public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource>
if (!StringUtils.isEmpty(this.namespace)) {
properties.setProperty(PropertyKeyConst.NAMESPACE, this.namespace);
}
if (!StringUtils.isEmpty(this.username)) {
properties.setProperty(PropertyKeyConst.USERNAME, this.username);
}
if (!StringUtils.isEmpty(this.password)) {
properties.setProperty(PropertyKeyConst.PASSWORD, this.password);
}
return new NacosDataSource(properties, groupId, dataId, converter);
}
@ -78,7 +88,23 @@ public class NacosDataSourceFactoryBean implements FactoryBean<NacosDataSource>
public void setServerAddr(String serverAddr) {
this.serverAddr = serverAddr;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGroupId() {
return groupId;
}

View File

@ -92,7 +92,8 @@ public class SentinelSCGAutoConfiguration {
}
private void initAppType() {
System.setProperty(SentinelConfig.APP_TYPE, ConfigConstants.APP_TYPE_SCG_GATEWAY);
System.setProperty(SentinelConfig.APP_TYPE_PROP_KEY,
ConfigConstants.APP_TYPE_SCG_GATEWAY);
}
private void initFallback() {

View File

@ -65,7 +65,7 @@ public class SentinelZuulAutoConfiguration {
private void init() {
requestOriginParserOptional
.ifPresent(ZuulGatewayCallbackManager::setOriginParser);
System.setProperty(SentinelConfig.APP_TYPE,
System.setProperty(SentinelConfig.APP_TYPE_PROP_KEY,
String.valueOf(ConfigConstants.APP_TYPE_ZUUL_GATEWAY));
}

View File

@ -22,7 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -487,8 +486,7 @@ public class NacosConfigProperties {
List<Config> result = new ArrayList<>();
configList.stream()
.collect(Collectors.groupingBy(cfg -> (cfg.getGroup() + cfg.getDataId()),
() -> new ConcurrentHashMap<>(new LinkedHashMap<>()),
Collectors.toList()))
LinkedHashMap::new, Collectors.toList()))
.forEach((key, list) -> {
list.stream()
.reduce((a, b) -> new Config(a.getDataId(), a.getGroup(),

View File

@ -55,7 +55,9 @@ public class NacosDataPropertiesParser extends AbstractNacosDataParser {
log.warn("the config data is invalid {}", dataLine);
continue;
}
result.put(dataLine.substring(0, index), dataLine.substring(index + 1));
String key = dataLine.substring(0, index);
String value = dataLine.substring(index + 1);
result.put(key.trim(), value.trim());
}
}
return result;

View File

@ -34,9 +34,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author <a href="mailto:lyuzb@lyuzb.com">lyuzb</a>
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = NacosConfigPropertiesServerAddressBothLevelTests.TestConfig.class,
properties = { "spring.cloud.nacos.config.server-addr=321,321,321,321:8848",
@SpringBootTest(classes = NacosConfigPropertiesServerAddressBothLevelTests.TestConfig.class, properties = {
"spring.cloud.nacos.config.server-addr=321,321,321,321:8848",
"spring.cloud.nacos.server-addr=123.123.123.123:8848" },
webEnvironment = RANDOM_PORT)
public class NacosConfigPropertiesServerAddressBothLevelTests {

View File

@ -34,10 +34,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author <a href="mailto:lyuzb@lyuzb.com">lyuzb</a>
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = NacosConfigPropertiesServerAddressTopLevelTests.TestConfig.class,
properties = { "spring.cloud.nacos.server-addr=123.123.123.123:8848" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosConfigPropertiesServerAddressTopLevelTests.TestConfig.class, properties = {
"spring.cloud.nacos.server-addr=123.123.123.123:8848" }, webEnvironment = RANDOM_PORT)
public class NacosConfigPropertiesServerAddressTopLevelTests {
@Autowired

View File

@ -50,9 +50,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosConfigService.class })
@SpringBootTest(classes = NacosConfigurationExtConfigTests.TestConfig.class,
properties = { "spring.application.name=myTestService1",
"spring.profiles.active=dev,test",
@SpringBootTest(classes = NacosConfigurationExtConfigTests.TestConfig.class, properties = {
"spring.application.name=myTestService1", "spring.profiles.active=dev,test",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.encode=utf-8",
"spring.cloud.nacos.config.timeout=1000",

View File

@ -49,8 +49,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosConfigService.class })
@SpringBootTest(classes = NacosFileExtensionTest.TestConfig.class,
properties = { "spring.application.name=test-name",
@SpringBootTest(classes = NacosFileExtensionTest.TestConfig.class, properties = {
"spring.application.name=test-name",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.file-extension=yaml" },
webEnvironment = NONE)

View File

@ -51,8 +51,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosConfigService.class })
@SpringBootTest(classes = NacosConfigEndpointTests.TestConfig.class,
properties = { "spring.application.name=test-name",
@SpringBootTest(classes = NacosConfigEndpointTests.TestConfig.class, properties = {
"spring.application.name=test-name",
"spring.cloud.nacos.config.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.config.file-extension=properties" },
webEnvironment = NONE)

View File

@ -25,8 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.enabled",
matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.enabled", matchIfMissing = true)
public @interface ConditionalOnNacosDiscoveryEnabled {
}

View File

@ -19,7 +19,6 @@ package com.alibaba.cloud.nacos;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@ -30,9 +29,7 @@ import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.naming.NamingMaintainFactory;
import com.alibaba.nacos.api.naming.NamingMaintainService;
import com.alibaba.cloud.nacos.event.NacosDiscoveryInfoChangedEvent;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
@ -44,6 +41,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
@ -64,19 +62,17 @@ import static com.alibaba.nacos.api.PropertyKeyConst.USERNAME;
* @author xiaojing
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @author <a href="mailto:lyuzb@lyuzb.com">lyuzb</a>
* @author <a href="mailto:78552423@qq.com">eshun</a>
*/
@ConfigurationProperties("spring.cloud.nacos.discovery")
public class NacosDiscoveryProperties {
private static final Logger log = LoggerFactory
.getLogger(NacosDiscoveryProperties.class);
/**
* Prefix of {@link NacosDiscoveryProperties}.
*/
public static final String PREFIX = "spring.cloud.nacos.discovery";
private static final Logger log = LoggerFactory
.getLogger(NacosDiscoveryProperties.class);
private static final Pattern PATTERN = Pattern.compile("-(\\w)");
/**
@ -199,18 +195,30 @@ public class NacosDiscoveryProperties {
*/
private Integer ipDeleteTimeout;
/**
* If instance is enabled to accept request. The default value is true.
*/
private boolean instanceEnabled = true;
/**
* If instance is ephemeral.The default value is true.
*/
private boolean ephemeral = true;
@Autowired
private InetUtils inetUtils;
@Autowired
private Environment environment;
private static NamingService namingService;
@Autowired
private NacosServiceManager nacosServiceManager;
private static NamingMaintainService namingMaintainService;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@PostConstruct
public void init() throws SocketException {
public void init() throws Exception {
metadata.put(PreservedMetadataKeys.REGISTER_SOURCE, "SPRING_CLOUD");
if (secure) {
@ -257,6 +265,19 @@ public class NacosDiscoveryProperties {
}
this.overrideFromEnv(environment);
if (nacosServiceManager.isNacosDiscoveryInfoChanged(this)) {
applicationEventPublisher
.publishEvent(new NacosDiscoveryInfoChangedEvent(this));
}
}
/**
* recommend to use {@link NacosServiceManager#getNamingService(Properties)}.
* @return NamingService
*/
@Deprecated
public NamingService namingServiceInstance() {
return nacosServiceManager.getNamingService(this.getNacosProperties());
}
public String getEndpoint() {
@ -447,6 +468,58 @@ public class NacosDiscoveryProperties {
this.password = password;
}
public boolean isInstanceEnabled() {
return instanceEnabled;
}
public void setInstanceEnabled(boolean instanceEnabled) {
this.instanceEnabled = instanceEnabled;
}
public boolean isEphemeral() {
return ephemeral;
}
public void setEphemeral(boolean ephemeral) {
this.ephemeral = ephemeral;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NacosDiscoveryProperties that = (NacosDiscoveryProperties) o;
return Objects.equals(serverAddr, that.serverAddr)
&& Objects.equals(username, that.username)
&& Objects.equals(password, that.password)
&& Objects.equals(endpoint, that.endpoint)
&& Objects.equals(namespace, that.namespace)
&& Objects.equals(logName, that.logName)
&& Objects.equals(service, that.service)
&& Objects.equals(clusterName, that.clusterName)
&& Objects.equals(group, that.group) && Objects.equals(ip, that.ip)
&& Objects.equals(port, that.port)
&& Objects.equals(networkInterface, that.networkInterface)
&& Objects.equals(accessKey, that.accessKey)
&& Objects.equals(secretKey, that.secretKey)
&& Objects.equals(heartBeatInterval, that.heartBeatInterval)
&& Objects.equals(heartBeatTimeout, that.heartBeatTimeout)
&& Objects.equals(ipDeleteTimeout, that.ipDeleteTimeout);
}
@Override
public int hashCode() {
return Objects.hash(serverAddr, username, password, endpoint, namespace,
watchDelay, logName, service, weight, clusterName, group,
namingLoadCacheAtStart, registerEnabled, ip, networkInterface, port,
secure, accessKey, secretKey, heartBeatInterval, heartBeatTimeout,
ipDeleteTimeout, instanceEnabled, ephemeral);
}
@Override
public String toString() {
return "NacosDiscoveryProperties{" + "serverAddr='" + serverAddr + '\''
@ -510,41 +583,7 @@ public class NacosDiscoveryProperties {
}
}
public NamingService namingServiceInstance() {
if (null != namingService) {
return namingService;
}
try {
namingService = NacosFactory.createNamingService(getNacosProperties());
}
catch (Exception e) {
log.error("create naming service error!properties={},e=,", this, e);
return null;
}
return namingService;
}
@Deprecated
public NamingMaintainService namingMaintainServiceInstance() {
if (null != namingMaintainService) {
return namingMaintainService;
}
try {
namingMaintainService = NamingMaintainFactory
.createMaintainService(getNacosProperties());
}
catch (Exception e) {
log.error("create naming service error!properties={},e=,", this, e);
return null;
}
return namingMaintainService;
}
private Properties getNacosProperties() {
public Properties getNacosProperties() {
Properties properties = new Properties();
properties.put(SERVER_ADDR, serverAddr);
properties.put(USERNAME, Objects.toString(username, ""));

View File

@ -0,0 +1,36 @@
/*
* 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.nacos;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author yuhuangbin
*/
@Configuration
@ConditionalOnDiscoveryEnabled
@ConditionalOnNacosDiscoveryEnabled
public class NacosServiceAutoConfiguration {
@Bean
public NacosServiceManager nacosServiceManager() {
return new NacosServiceManager();
}
}

View File

@ -42,21 +42,37 @@ public class NacosServiceInstance implements ServiceInstance {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
@Override
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
@Override
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
@Override
public boolean isSecure() {
return secure;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
@ -67,22 +83,6 @@ public class NacosServiceInstance implements ServiceInstance {
return metadata;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public void setHost(String host) {
this.host = host;
}
public void setPort(int port) {
this.port = port;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}

View File

@ -0,0 +1,134 @@
/*
* 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.nacos;
import java.util.Objects;
import java.util.Properties;
import com.alibaba.cloud.nacos.registry.NacosRegistration;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingMaintainService;
import com.alibaba.nacos.api.naming.NamingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.discovery.event.InstancePreRegisteredEvent;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.event.EventListener;
import static com.alibaba.nacos.api.NacosFactory.createMaintainService;
import static com.alibaba.nacos.api.NacosFactory.createNamingService;
import static org.springframework.beans.BeanUtils.copyProperties;
/**
* @author yuhuangbin
*/
public class NacosServiceManager {
private static final Logger log = LoggerFactory.getLogger(NacosServiceManager.class);
private NacosDiscoveryProperties nacosDiscoveryPropertiesCache;
private NamingService namingService;
private NamingMaintainService namingMaintainService;
public NamingService getNamingService(Properties properties) {
if (Objects.isNull(this.namingService)) {
buildNamingService(properties);
}
return namingService;
}
public NamingMaintainService getNamingMaintainService(Properties properties) {
if (Objects.isNull(namingMaintainService)) {
buildNamingMaintainService(properties);
}
return namingMaintainService;
}
public boolean isNacosDiscoveryInfoChanged(
NacosDiscoveryProperties nacosDiscoveryProperties) {
if (Objects.isNull(nacosDiscoveryPropertiesCache)
|| this.nacosDiscoveryPropertiesCache.equals(nacosDiscoveryProperties)) {
return false;
}
copyProperties(nacosDiscoveryProperties, nacosDiscoveryPropertiesCache);
return true;
}
private NamingMaintainService buildNamingMaintainService(Properties properties) {
if (Objects.isNull(namingMaintainService)) {
synchronized (NacosServiceManager.class) {
if (Objects.isNull(namingMaintainService)) {
namingMaintainService = createNamingMaintainService(properties);
}
}
}
return namingMaintainService;
}
private NamingService buildNamingService(Properties properties) {
if (Objects.isNull(namingService)) {
synchronized (NacosServiceManager.class) {
if (Objects.isNull(namingService)) {
namingService = createNewNamingService(properties);
}
}
}
return namingService;
}
private NamingService createNewNamingService(Properties properties) {
try {
return createNamingService(properties);
}
catch (NacosException e) {
throw new RuntimeException(e);
}
}
private NamingMaintainService createNamingMaintainService(Properties properties) {
try {
return createMaintainService(properties);
}
catch (NacosException e) {
throw new RuntimeException(e);
}
}
public void nacosServiceShutDown() throws NacosException {
this.namingService.shutDown();
namingService = null;
namingMaintainService = null;
}
@EventListener
public void onInstancePreRegisteredEvent(
InstancePreRegisteredEvent instancePreRegisteredEvent) {
Registration registration = instancePreRegisteredEvent.getRegistration();
if (Objects.isNull(nacosDiscoveryPropertiesCache)
&& registration instanceof NacosRegistration) {
NacosDiscoveryProperties nacosDiscoveryProperties = ((NacosRegistration) registration)
.getNacosDiscoveryProperties();
nacosDiscoveryPropertiesCache = new NacosDiscoveryProperties();
copyProperties(nacosDiscoveryProperties, nacosDiscoveryPropertiesCache);
}
}
}

View File

@ -18,6 +18,7 @@ package com.alibaba.cloud.nacos.discovery;
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
@ -41,8 +42,9 @@ public class NacosDiscoveryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public NacosServiceDiscovery nacosServiceDiscovery(
NacosDiscoveryProperties discoveryProperties) {
return new NacosServiceDiscovery(discoveryProperties);
NacosDiscoveryProperties discoveryProperties,
NacosServiceManager nacosServiceManager) {
return new NacosServiceDiscovery(discoveryProperties, nacosServiceManager);
}
}

View File

@ -32,13 +32,11 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
*/
public class NacosDiscoveryClient implements DiscoveryClient {
private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class);
/**
* Nacos Discovery Client Description.
*/
public static final String DESCRIPTION = "Spring Cloud Nacos Discovery Client";
private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class);
private NacosServiceDiscovery serviceDiscovery;
public NacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {

View File

@ -18,6 +18,7 @@ package com.alibaba.cloud.nacos.discovery;
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@ -38,9 +39,8 @@ import org.springframework.scheduling.TaskScheduler;
*/
@Configuration
@ConditionalOnDiscoveryEnabled
//@ConditionalOnBlockingDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.discovery.blocking.enabled",
matchIfMissing = true)
// @ConditionalOnBlockingDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.discovery.blocking.enabled", matchIfMissing = true)
@ConditionalOnNacosDiscoveryEnabled
@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class })
@ -55,11 +55,12 @@ public class NacosDiscoveryClientConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.watch.enabled",
matchIfMissing = true)
public NacosWatch nacosWatch(NacosDiscoveryProperties nacosDiscoveryProperties,
ObjectProvider<TaskScheduler> taskScheduler) {
return new NacosWatch(nacosDiscoveryProperties, taskScheduler);
@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.watch.enabled", matchIfMissing = true)
public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties,
ObjectProvider<TaskScheduler> taskExecutorObjectProvider) {
return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties,
taskExecutorObjectProvider);
}
}

View File

@ -23,7 +23,9 @@ import java.util.Map;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceInstance;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
@ -36,33 +38,12 @@ public class NacosServiceDiscovery {
private NacosDiscoveryProperties discoveryProperties;
public NacosServiceDiscovery(NacosDiscoveryProperties discoveryProperties) {
private NacosServiceManager nacosServiceManager;
public NacosServiceDiscovery(NacosDiscoveryProperties discoveryProperties,
NacosServiceManager nacosServiceManager) {
this.discoveryProperties = discoveryProperties;
}
/**
* Return all instances for the given service.
* @param serviceId id of service
* @return list of instances
* @throws NacosException nacosException
*/
public List<ServiceInstance> getInstances(String serviceId) throws NacosException {
String group = discoveryProperties.getGroup();
List<Instance> instances = discoveryProperties.namingServiceInstance()
.selectInstances(serviceId, group, true);
return hostToServiceInstanceList(instances, serviceId);
}
/**
* Return the names of all services.
* @return list of service names
* @throws NacosException nacosException
*/
public List<String> getServices() throws NacosException {
String group = discoveryProperties.getGroup();
ListView<String> services = discoveryProperties.namingServiceInstance()
.getServicesOfServer(1, Integer.MAX_VALUE, group);
return services.getData();
this.nacosServiceManager = nacosServiceManager;
}
public static List<ServiceInstance> hostToServiceInstanceList(
@ -92,7 +73,10 @@ public class NacosServiceDiscovery {
metadata.put("nacos.weight", instance.getWeight() + "");
metadata.put("nacos.healthy", instance.isHealthy() + "");
metadata.put("nacos.cluster", instance.getClusterName() + "");
metadata.putAll(instance.getMetadata());
if (instance.getMetadata() != null) {
metadata.putAll(instance.getMetadata());
}
metadata.put("nacos.ephemeral", String.valueOf(instance.isEphemeral()));
nacosServiceInstance.setMetadata(metadata);
if (metadata.containsKey("secure")) {
@ -102,4 +86,34 @@ public class NacosServiceDiscovery {
return nacosServiceInstance;
}
/**
* Return all instances for the given service.
* @param serviceId id of service
* @return list of instances
* @throws NacosException nacosException
*/
public List<ServiceInstance> getInstances(String serviceId) throws NacosException {
String group = discoveryProperties.getGroup();
List<Instance> instances = namingService().selectInstances(serviceId, group,
true);
return hostToServiceInstanceList(instances, serviceId);
}
/**
* Return the names of all services.
* @return list of service names
* @throws NacosException nacosException
*/
public List<String> getServices() throws NacosException {
String group = discoveryProperties.getGroup();
ListView<String> services = namingService().getServicesOfServer(1,
Integer.MAX_VALUE, group);
return services.getData();
}
private NamingService namingService() {
return nacosServiceManager
.getNamingService(discoveryProperties.getNacosProperties());
}
}

View File

@ -16,11 +16,23 @@
package com.alibaba.cloud.nacos.discovery;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -34,47 +46,31 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* @author xiaojing
* @author yuhuangbin
*/
public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle {
private static final Logger log = LoggerFactory.getLogger(NacosWatch.class);
private final NacosDiscoveryProperties properties;
private final TaskScheduler taskScheduler;
private final AtomicLong nacosWatchIndex = new AtomicLong(0);
private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicLong nacosWatchIndex = new AtomicLong(0);
private final NacosDiscoveryProperties properties;
private final TaskScheduler taskScheduler;
private Map<String, EventListener> listenerMap = new ConcurrentHashMap<>(16);
private ApplicationEventPublisher publisher;
private ScheduledFuture<?> watchFuture;
private NacosServiceManager nacosServiceManager;
public NacosWatch(NacosDiscoveryProperties properties) {
this(properties, getTaskScheduler());
}
public NacosWatch(NacosDiscoveryProperties properties, TaskScheduler taskScheduler) {
this.properties = properties;
this.taskScheduler = taskScheduler;
}
/**
* The constructor with {@link NacosDiscoveryProperties} bean and the optional.
* {@link TaskScheduler} bean
* @param properties {@link NacosDiscoveryProperties} bean
* @param taskScheduler the optional {@link TaskScheduler} bean
* @since 2.2.0
*/
public NacosWatch(NacosDiscoveryProperties properties,
public NacosWatch(NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties properties,
ObjectProvider<TaskScheduler> taskScheduler) {
this(properties, taskScheduler.getIfAvailable(NacosWatch::getTaskScheduler));
this.nacosServiceManager = nacosServiceManager;
this.properties = properties;
this.taskScheduler = taskScheduler.getIfAvailable(NacosWatch::getTaskScheduler);
}
private static ThreadPoolTaskScheduler getTaskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setBeanName("Nacso-Watch-Task-Scheduler");
taskScheduler.setBeanName("Nacos-Watch-Task-Scheduler");
taskScheduler.initialize();
return taskScheduler;
}
@ -98,19 +94,75 @@ public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycl
@Override
public void start() {
if (this.running.compareAndSet(false, true)) {
EventListener eventListener = listenerMap.computeIfAbsent(buildKey(),
event -> new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
List<Instance> instances = ((NamingEvent) event)
.getInstances();
Optional<Instance> instanceOptional = selectCurrentInstance(
instances);
instanceOptional.ifPresent(currentInstance -> {
resetIfNeeded(currentInstance);
});
}
}
});
NamingService namingService = nacosServiceManager
.getNamingService(properties.getNacosProperties());
try {
namingService.subscribe(properties.getService(), properties.getGroup(),
Arrays.asList(properties.getClusterName()), eventListener);
}
catch (Exception e) {
log.error("namingService subscribe failed, properties:{}", properties, e);
}
this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(
this::nacosServicesWatch, this.properties.getWatchDelay());
}
}
private String buildKey() {
return String.join(":", properties.getService(), properties.getGroup());
}
private void resetIfNeeded(Instance instance) {
if (!properties.getMetadata().equals(instance.getMetadata())) {
properties.setMetadata(instance.getMetadata());
}
}
private Optional<Instance> selectCurrentInstance(List<Instance> instances) {
return instances.stream()
.filter(instance -> properties.getIp().equals(instance.getIp())
&& properties.getPort() == instance.getPort())
.findFirst();
}
@Override
public void stop() {
if (this.running.compareAndSet(true, false) && this.watchFuture != null) {
// shutdown current user-thread,
// then the other daemon-threads will terminate automatic.
((ThreadPoolTaskScheduler) this.taskScheduler).shutdown();
if (this.running.compareAndSet(true, false)) {
if (this.watchFuture != null) {
// shutdown current user-thread,
// then the other daemon-threads will terminate automatic.
((ThreadPoolTaskScheduler) this.taskScheduler).shutdown();
this.watchFuture.cancel(true);
}
this.watchFuture.cancel(true);
EventListener eventListener = listenerMap.get(buildKey());
try {
NamingService namingService = nacosServiceManager
.getNamingService(properties.getNacosProperties());
namingService.unsubscribe(properties.getService(), properties.getGroup(),
Arrays.asList(properties.getClusterName()), eventListener);
}
catch (NacosException e) {
log.error("namingService unsubscribe failed, properties:{}", properties,
e);
}
}
}

View File

@ -26,7 +26,6 @@ import org.springframework.boot.actuate.health.HealthIndicator;
* The {@link HealthIndicator} for Nacos Discovery.
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.2.0
* @see HealthIndicator
*/
public class NacosDiscoveryHealthIndicator extends AbstractHealthIndicator {

View File

@ -31,11 +31,10 @@ import org.springframework.context.annotation.Configuration;
* @author JevonYang
*/
@ConditionalOnClass(ConfigServicePropertySourceLocator.class)
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled",
matchIfMissing = false)
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
@Configuration
@ImportAutoConfiguration({ NacosDiscoveryAutoConfiguration.class,
NacosDiscoveryClientConfiguration.class})
NacosDiscoveryClientConfiguration.class })
public class NacosDiscoveryClientConfigServiceBootstrapConfiguration {
}

View File

@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import org.slf4j.Logger;
@ -41,9 +42,13 @@ public class NacosDiscoveryEndpoint {
private static final Logger log = LoggerFactory
.getLogger(NacosDiscoveryEndpoint.class);
private NacosServiceManager nacosServiceManager;
private NacosDiscoveryProperties nacosDiscoveryProperties;
public NacosDiscoveryEndpoint(NacosDiscoveryProperties nacosDiscoveryProperties) {
public NacosDiscoveryEndpoint(NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
this.nacosServiceManager = nacosServiceManager;
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
}
@ -55,7 +60,8 @@ public class NacosDiscoveryEndpoint {
Map<String, Object> result = new HashMap<>();
result.put("NacosDiscoveryProperties", nacosDiscoveryProperties);
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
NamingService namingService = nacosServiceManager
.getNamingService(nacosDiscoveryProperties.getNacosProperties());
List<ServiceInfo> subscribe = Collections.emptyList();
try {

View File

@ -16,8 +16,11 @@
package com.alibaba.cloud.nacos.endpoint;
import java.util.Properties;
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.discovery.actuate.health.NacosDiscoveryHealthIndicator;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
@ -44,16 +47,19 @@ public class NacosDiscoveryEndpointAutoConfiguration {
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
public NacosDiscoveryEndpoint nacosDiscoveryEndpoint(
NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosDiscoveryEndpoint(nacosDiscoveryProperties);
return new NacosDiscoveryEndpoint(nacosServiceManager, nacosDiscoveryProperties);
}
@Bean
@ConditionalOnEnabledHealthIndicator("nacos-discovery")
public HealthIndicator nacosDiscoveryHealthIndicator(
NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
Properties nacosProperties = nacosDiscoveryProperties.getNacosProperties();
return new NacosDiscoveryHealthIndicator(
nacosDiscoveryProperties.namingServiceInstance());
nacosServiceManager.getNamingService(nacosProperties));
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.nacos.event;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import org.springframework.context.ApplicationEvent;
/**
* @author yuhuangbin
*/
public class NacosDiscoveryInfoChangedEvent extends ApplicationEvent {
public NacosDiscoveryInfoChangedEvent(
NacosDiscoveryProperties nacosDiscoveryProperties) {
super(nacosDiscoveryProperties);
}
@Override
public NacosDiscoveryProperties getSource() {
return (NacosDiscoveryProperties) super.getSource();
}
}

View File

@ -16,6 +16,7 @@
package com.alibaba.cloud.nacos.registry;
import com.alibaba.cloud.nacos.event.NacosDiscoveryInfoChangedEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -23,6 +24,7 @@ import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegis
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.event.EventListener;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -102,4 +104,14 @@ public class NacosAutoServiceRegistration
return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
}
@EventListener
public void onNacosDiscoveryInfoChangedEvent(NacosDiscoveryInfoChangedEvent event) {
restart();
}
private void restart() {
this.stop();
this.start();
}
}

View File

@ -17,12 +17,12 @@
package com.alibaba.cloud.nacos.registry;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
import org.springframework.cloud.client.DefaultServiceInstance;
@ -58,16 +58,30 @@ public class NacosRegistration implements Registration, ServiceInstance {
*/
public static final String MANAGEMENT_ENDPOINT_BASE_PATH = "management.endpoints.web.base-path";
private List<NacosRegistrationCustomizer> registrationCustomizers;
private NacosDiscoveryProperties nacosDiscoveryProperties;
private ApplicationContext context;
public NacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties,
public NacosRegistration(List<NacosRegistrationCustomizer> registrationCustomizers,
NacosDiscoveryProperties nacosDiscoveryProperties,
ApplicationContext context) {
this.registrationCustomizers = registrationCustomizers;
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.context = context;
}
private static void customize(
List<NacosRegistrationCustomizer> registrationCustomizers,
NacosRegistration registration) {
if (registrationCustomizers != null) {
for (NacosRegistrationCustomizer customizer : registrationCustomizers) {
customizer.customize(registration);
}
}
}
@PostConstruct
public void init() {
@ -105,6 +119,7 @@ public class NacosRegistration implements Registration, ServiceInstance {
metadata.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT,
nacosDiscoveryProperties.getIpDeleteTimeout().toString());
}
customize(registrationCustomizers, this);
}
@Override
@ -157,10 +172,6 @@ public class NacosRegistration implements Registration, ServiceInstance {
return nacosDiscoveryProperties;
}
public NamingService getNacosNamingService() {
return nacosDiscoveryProperties.namingServiceInstance();
}
@Override
public String toString() {
return "NacosRegistration{" + "nacosDiscoveryProperties="

View File

@ -0,0 +1,30 @@
/*
* 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.nacos.registry;
/**
* @author L.cm
*/
public interface NacosRegistrationCustomizer {
/**
* customize NacosRegistration.
* @param registration NacosRegistration
*/
void customize(NacosRegistration registration);
}

View File

@ -17,13 +17,17 @@
package com.alibaba.cloud.nacos.registry;
import java.util.List;
import java.util.Properties;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.util.StringUtils;
@ -33,6 +37,7 @@ import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/**
* @author xiaojing
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @author <a href="mailto:78552423@qq.com">eshun</a>
*/
public class NacosServiceRegistry implements ServiceRegistry<Registration> {
@ -40,11 +45,11 @@ public class NacosServiceRegistry implements ServiceRegistry<Registration> {
private final NacosDiscoveryProperties nacosDiscoveryProperties;
private final NamingService namingService;
@Autowired
private NacosServiceManager nacosServiceManager;
public NacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.namingService = nacosDiscoveryProperties.namingServiceInstance();
}
@Override
@ -55,6 +60,7 @@ public class NacosServiceRegistry implements ServiceRegistry<Registration> {
return;
}
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
@ -84,7 +90,7 @@ public class NacosServiceRegistry implements ServiceRegistry<Registration> {
return;
}
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
@ -102,7 +108,12 @@ public class NacosServiceRegistry implements ServiceRegistry<Registration> {
@Override
public void close() {
try {
nacosServiceManager.nacosServiceShutDown();
}
catch (NacosException e) {
log.error("Nacos namingService shutDown failed", e);
}
}
@Override
@ -125,7 +136,8 @@ public class NacosServiceRegistry implements ServiceRegistry<Registration> {
}
try {
nacosDiscoveryProperties.namingMaintainServiceInstance()
Properties nacosProperties = nacosDiscoveryProperties.getNacosProperties();
nacosServiceManager.getNamingMaintainService(nacosProperties)
.updateInstance(serviceId, instance);
}
catch (Exception e) {
@ -139,8 +151,7 @@ public class NacosServiceRegistry implements ServiceRegistry<Registration> {
String serviceName = registration.getServiceId();
try {
List<Instance> instances = nacosDiscoveryProperties.namingServiceInstance()
.getAllInstances(serviceName);
List<Instance> instances = namingService().getAllInstances(serviceName);
for (Instance instance : instances) {
if (instance.getIp().equalsIgnoreCase(nacosDiscoveryProperties.getIp())
&& instance.getPort() == nacosDiscoveryProperties.getPort()) {
@ -160,9 +171,15 @@ public class NacosServiceRegistry implements ServiceRegistry<Registration> {
instance.setPort(registration.getPort());
instance.setWeight(nacosDiscoveryProperties.getWeight());
instance.setClusterName(nacosDiscoveryProperties.getClusterName());
instance.setEnabled(nacosDiscoveryProperties.isInstanceEnabled());
instance.setMetadata(registration.getMetadata());
instance.setEphemeral(nacosDiscoveryProperties.isEphemeral());
return instance;
}
private NamingService namingService() {
return nacosServiceManager
.getNamingService(nacosDiscoveryProperties.getNacosProperties());
}
}

View File

@ -16,10 +16,13 @@
package com.alibaba.cloud.nacos.registry;
import java.util.List;
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -38,8 +41,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class,
NacosDiscoveryAutoConfiguration.class })
@ -54,9 +56,11 @@ public class NacosServiceRegistryAutoConfiguration {
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosRegistration nacosRegistration(
ObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers,
NacosDiscoveryProperties nacosDiscoveryProperties,
ApplicationContext context) {
return new NacosRegistration(nacosDiscoveryProperties, context);
return new NacosRegistration(registrationCustomizers.getIfAvailable(),
nacosDiscoveryProperties, context);
}
@Bean

View File

@ -21,6 +21,7 @@ import java.util.Objects;
import java.util.stream.Collectors;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
@ -47,16 +48,20 @@ public class NacosRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Autowired
private NacosServiceManager nacosServiceManager;
@Override
public Server choose(Object key) {
try {
String clusterName = this.nacosDiscoveryProperties.getClusterName();
String group = this.nacosDiscoveryProperties.getGroup();
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
String name = loadBalancer.getName();
NamingService namingService = nacosDiscoveryProperties
.namingServiceInstance();
List<Instance> instances = namingService.selectInstances(name, true);
NamingService namingService = nacosServiceManager
.getNamingService(nacosDiscoveryProperties.getNacosProperties());
List<Instance> instances = namingService.selectInstances(name, group, true);
if (CollectionUtils.isEmpty(instances)) {
LOGGER.warn("no instance in service {}", name);
return null;

View File

@ -24,6 +24,18 @@
"description": "enable nacos discovery or not."
},
{
"name": "spring.cloud.nacos.discovery.instance-enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "If instance is enabled to accept request. The default value is true."
},
{
"name": "spring.cloud.nacos.discovery.ephemeral",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "If instance is ephemeral.The default value is true."
},
{
"name": "spring.cloud.nacos.discovery.namingLoadCacheAtStart",
"type": "java.lang.Boolean",
"defaultValue": "false",

View File

@ -4,6 +4,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration

View File

@ -36,11 +36,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author <a href="mailto:lyuzb@lyuzb.com">lyuzb</a>
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = NacosDiscoveryPropertiesServerAddressBothLevelTests.TestConfig.class,
properties = { "spring.cloud.nacos.discovery.server-addr=321.321.321.321:8848",
"spring.cloud.nacos.server-addr=123.123.123.123:8848" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosDiscoveryPropertiesServerAddressBothLevelTests.TestConfig.class, properties = {
"spring.cloud.nacos.discovery.server-addr=321.321.321.321:8848",
"spring.cloud.nacos.server-addr=123.123.123.123:8848" }, webEnvironment = RANDOM_PORT)
public class NacosDiscoveryPropertiesServerAddressBothLevelTests {
@Autowired

View File

@ -37,10 +37,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = NacosDiscoveryPropertiesServerAddressTopLevelTests.TestConfig.class,
properties = { "spring.cloud.nacos.server-addr=123.123.123.123:8848" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosDiscoveryPropertiesServerAddressTopLevelTests.TestConfig.class, properties = {
"spring.cloud.nacos.server-addr=123.123.123.123:8848" }, webEnvironment = RANDOM_PORT)
public class NacosDiscoveryPropertiesServerAddressTopLevelTests {

View File

@ -22,6 +22,7 @@ import java.util.LinkedList;
import java.util.List;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
@ -60,16 +61,19 @@ public class NacosServiceDiscoveryTest {
NacosDiscoveryProperties nacosDiscoveryProperties = mock(
NacosDiscoveryProperties.class);
NacosServiceManager nacosServiceManager = mock(NacosServiceManager.class);
NamingService namingService = mock(NamingService.class);
when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService);
when(nacosServiceManager
.getNamingService(nacosDiscoveryProperties.getNacosProperties()))
.thenReturn(namingService);
when(nacosDiscoveryProperties.getGroup()).thenReturn("DEFAULT");
when(namingService.selectInstances(eq(serviceName), eq("DEFAULT"), eq(true)))
.thenReturn(instances);
NacosServiceDiscovery serviceDiscovery = new NacosServiceDiscovery(
nacosDiscoveryProperties);
nacosDiscoveryProperties, nacosServiceManager);
List<ServiceInstance> serviceInstances = serviceDiscovery
.getInstances(serviceName);
@ -99,16 +103,19 @@ public class NacosServiceDiscoveryTest {
NacosDiscoveryProperties nacosDiscoveryProperties = mock(
NacosDiscoveryProperties.class);
NacosServiceManager nacosServiceManager = mock(NacosServiceManager.class);
NamingService namingService = mock(NamingService.class);
when(nacosDiscoveryProperties.namingServiceInstance()).thenReturn(namingService);
when(nacosServiceManager
.getNamingService(nacosDiscoveryProperties.getNacosProperties()))
.thenReturn(namingService);
when(nacosDiscoveryProperties.getGroup()).thenReturn("DEFAULT");
when(namingService.getServicesOfServer(eq(1), eq(Integer.MAX_VALUE),
eq("DEFAULT"))).thenReturn(nacosServices);
NacosServiceDiscovery serviceDiscovery = new NacosServiceDiscovery(
nacosDiscoveryProperties);
nacosDiscoveryProperties, nacosServiceManager);
List<String> services = serviceDiscovery.getServices();

View File

@ -328,4 +328,9 @@ public class MockNamingService implements NamingService {
return null;
}
@Override
public void shutDown() throws NacosException {
}
}

View File

@ -56,25 +56,11 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosFactory.class })
@SpringBootTest(
classes = NacosAutoServiceRegistrationIpNetworkInterfaceTests.TestConfig.class,
properties = { "spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosAutoServiceRegistrationIpNetworkInterfaceTests.TestConfig.class, properties = {
"spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848" }, webEnvironment = RANDOM_PORT)
public class NacosAutoServiceRegistrationIpNetworkInterfaceTests {
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
@Autowired
private InetUtils inetUtils;
static {
try {
Method method = PowerMockito.method(NacosFactory.class, "createNamingService",
@ -92,6 +78,15 @@ public class NacosAutoServiceRegistrationIpNetworkInterfaceTests {
}
}
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
@Autowired
private InetUtils inetUtils;
@Test
public void contextLoads() throws Exception {
assertThat(registration).isNotNull();

View File

@ -51,22 +51,12 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosFactory.class })
@SpringBootTest(classes = NacosAutoServiceRegistrationIpTests.TestConfig.class,
properties = { "spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.ip=123.123.123.123" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosAutoServiceRegistrationIpTests.TestConfig.class, properties = {
"spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.ip=123.123.123.123" }, webEnvironment = RANDOM_PORT)
public class NacosAutoServiceRegistrationIpTests {
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
static {
try {
Method method = PowerMockito.method(NacosFactory.class, "createNamingService",
@ -84,6 +74,13 @@ public class NacosAutoServiceRegistrationIpTests {
}
}
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
@Test
public void contextLoads() throws Exception {
assertThat(registration).isNotNull();

View File

@ -51,25 +51,13 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosFactory.class })
@SpringBootTest(
classes = NacosAutoServiceRegistrationManagementPortTests.TestConfig.class,
properties = { "spring.application.name=myTestService1",
"management.server.port=8888",
"management.server.servlet.context-path=/test-context-path",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.port=8888" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosAutoServiceRegistrationManagementPortTests.TestConfig.class, properties = {
"spring.application.name=myTestService1", "management.server.port=8888",
"management.server.servlet.context-path=/test-context-path",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.port=8888" }, webEnvironment = RANDOM_PORT)
public class NacosAutoServiceRegistrationManagementPortTests {
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
static {
try {
Method method = PowerMockito.method(NacosFactory.class, "createNamingService",
@ -87,6 +75,13 @@ public class NacosAutoServiceRegistrationManagementPortTests {
}
}
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
@Test
public void contextLoads() throws Exception {
assertThat(registration).isNotNull();

View File

@ -51,22 +51,12 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosFactory.class })
@SpringBootTest(classes = NacosAutoServiceRegistrationPortTests.TestConfig.class,
properties = { "spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.port=8888" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosAutoServiceRegistrationPortTests.TestConfig.class, properties = {
"spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.port=8888" }, webEnvironment = RANDOM_PORT)
public class NacosAutoServiceRegistrationPortTests {
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
static {
try {
Method method = PowerMockito.method(NacosFactory.class, "createNamingService",
@ -84,6 +74,13 @@ public class NacosAutoServiceRegistrationPortTests {
}
}
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@Autowired
private NacosDiscoveryProperties properties;
@Test
public void contextLoads() throws Exception {
assertThat(registration).isNotNull();

View File

@ -22,6 +22,7 @@ import java.util.Map;
import java.util.Properties;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration;
import com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpoint;
import com.alibaba.nacos.api.NacosFactory;
@ -55,40 +56,24 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@PowerMockIgnore("javax.management.*")
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({ NacosFactory.class })
@SpringBootTest(classes = NacosAutoServiceRegistrationTests.TestConfig.class,
properties = { "spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.endpoint=test-endpoint",
"spring.cloud.nacos.discovery.namespace=test-namespace",
"spring.cloud.nacos.discovery.log-name=test-logName",
"spring.cloud.nacos.discovery.weight=2",
"spring.cloud.nacos.discovery.clusterName=test-cluster",
"spring.cloud.nacos.discovery.namingLoadCacheAtStart=true",
"spring.cloud.nacos.discovery.secure=true",
"spring.cloud.nacos.discovery.accessKey=test-accessKey",
"spring.cloud.nacos.discovery.ip=8.8.8.8",
"spring.cloud.nacos.discovery.secretKey=test-secretKey",
"spring.cloud.nacos.discovery.heart-beat-interval=3",
"spring.cloud.nacos.discovery.heart-beat-timeout=6",
"spring.cloud.nacos.discovery.ip-delete-timeout=9" },
webEnvironment = RANDOM_PORT)
@SpringBootTest(classes = NacosAutoServiceRegistrationTests.TestConfig.class, properties = {
"spring.application.name=myTestService1",
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.endpoint=test-endpoint",
"spring.cloud.nacos.discovery.namespace=test-namespace",
"spring.cloud.nacos.discovery.log-name=test-logName",
"spring.cloud.nacos.discovery.weight=2",
"spring.cloud.nacos.discovery.clusterName=test-cluster",
"spring.cloud.nacos.discovery.namingLoadCacheAtStart=true",
"spring.cloud.nacos.discovery.secure=true",
"spring.cloud.nacos.discovery.accessKey=test-accessKey",
"spring.cloud.nacos.discovery.ip=8.8.8.8",
"spring.cloud.nacos.discovery.secretKey=test-secretKey",
"spring.cloud.nacos.discovery.heart-beat-interval=3",
"spring.cloud.nacos.discovery.heart-beat-timeout=6",
"spring.cloud.nacos.discovery.ip-delete-timeout=9" }, webEnvironment = RANDOM_PORT)
public class NacosAutoServiceRegistrationTests {
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@LocalServerPort
private int port;
@Autowired
private NacosDiscoveryProperties properties;
@Autowired
private InetUtils inetUtils;
static {
try {
Method method = PowerMockito.method(NacosFactory.class, "createNamingService",
@ -106,6 +91,19 @@ public class NacosAutoServiceRegistrationTests {
}
}
@Autowired
private NacosRegistration registration;
@Autowired
private NacosAutoServiceRegistration nacosAutoServiceRegistration;
@LocalServerPort
private int port;
@Autowired
private NacosDiscoveryProperties properties;
@Autowired
private NacosServiceManager nacosServiceManager;
@Autowired
private InetUtils inetUtils;
@Test
public void contextLoads() throws Exception {
assertThat(registration).isNotNull();
@ -207,7 +205,7 @@ public class NacosAutoServiceRegistrationTests {
private void checkoutEndpoint() throws Exception {
NacosDiscoveryEndpoint nacosDiscoveryEndpoint = new NacosDiscoveryEndpoint(
properties);
nacosServiceManager, properties);
Map<String, Object> map = nacosDiscoveryEndpoint.nacosDiscovery();
assertThat(properties).isEqualTo(map.get("NacosDiscoveryProperties"));

View File

@ -39,14 +39,14 @@ import org.springframework.test.context.junit4.SpringRunner;
* @author liujunjie
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = NacosRibbonClientPropertyOverrideTests.TestConfiguration.class,
properties = { "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.port=18080",
"spring.cloud.nacos.discovery.service=remoteApp",
"localApp.ribbon.NIWSServerListClassName="
+ "com.netflix.loadbalancer.ConfigurationBasedServerList",
"localApp.ribbon.listOfServers=127.0.0.1:19090",
"localApp.ribbon.ServerListRefreshInterval=15000" })
@SpringBootTest(classes = NacosRibbonClientPropertyOverrideTests.TestConfiguration.class, properties = {
"spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848",
"spring.cloud.nacos.discovery.port=18080",
"spring.cloud.nacos.discovery.service=remoteApp",
"localApp.ribbon.NIWSServerListClassName="
+ "com.netflix.loadbalancer.ConfigurationBasedServerList",
"localApp.ribbon.listOfServers=127.0.0.1:19090",
"localApp.ribbon.ServerListRefreshInterval=15000" })
public class NacosRibbonClientPropertyOverrideTests {
@Autowired

View File

@ -36,15 +36,13 @@ import org.springframework.util.StringUtils;
*/
public class SeataFeignClient implements Client {
private final Client delegate;
private final BeanFactory beanFactory;
private static final int MAP_SIZE = 16;
private final Client delegate;
private final BeanFactory beanFactory;
SeataFeignClient(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
this.delegate = new Client.Default(null, null);
this.delegate = new Default(null, null);
}
SeataFeignClient(BeanFactory beanFactory, Client delegate) {

View File

@ -46,6 +46,7 @@ public class SeataHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
private final Logger logger = LoggerFactory
.getLogger(SeataHystrixConcurrencyStrategy.class);
private HystrixConcurrencyStrategy delegate;
public SeataHystrixConcurrencyStrategy() {

View File

@ -35,17 +35,16 @@ import org.springframework.web.client.RestTemplate;
@Configuration
public class SeataRestTemplateAutoConfiguration {
@Autowired(required = false)
private Collection<RestTemplate> restTemplates;
@Autowired
private SeataRestTemplateInterceptor seataRestTemplateInterceptor;
@Bean
public SeataRestTemplateInterceptor seataRestTemplateInterceptor() {
return new SeataRestTemplateInterceptor();
}
@Autowired(required = false)
private Collection<RestTemplate> restTemplates;
@Autowired
private SeataRestTemplateInterceptor seataRestTemplateInterceptor;
@PostConstruct
public void init() {
if (this.restTemplates != null) {

View File

@ -19,21 +19,21 @@ package com.alibaba.cloud.seata.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import io.seata.common.util.StringUtils;
import io.seata.core.context.RootContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* @author xiaojing
*
* Seata HandlerInterceptor, Convert Seata information into
* @see io.seata.core.context.RootContext from http request's header in
* {@link org.springframework.web.servlet.HandlerInterceptor#preHandle(HttpServletRequest , HttpServletResponse , Object )},
* @see RootContext from http request's header in
* {@link HandlerInterceptor#preHandle(HttpServletRequest, HttpServletResponse, Object )},
* And clean up Seata information after servlet method invocation in
* {@link org.springframework.web.servlet.HandlerInterceptor#afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception)}
* {@link HandlerInterceptor#afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception)}
*/
public class SeataHandlerInterceptor implements HandlerInterceptor {
@ -50,7 +50,7 @@ public class SeataHandlerInterceptor implements HandlerInterceptor {
log.debug("xid in RootContext {} xid in RpcContext {}", xid, rpcXid);
}
if (xid == null && rpcXid != null) {
if (StringUtils.isBlank(xid) && rpcXid != null) {
RootContext.bind(rpcXid);
if (log.isDebugEnabled()) {
log.debug("bind {} to RootContext", rpcXid);
@ -62,22 +62,23 @@ public class SeataHandlerInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception e) {
if (StringUtils.isNotBlank(RootContext.getXID())) {
String rpcXid = request.getHeader(RootContext.KEY_XID);
String rpcXid = request.getHeader(RootContext.KEY_XID);
if (StringUtils.isEmpty(rpcXid)) {
return;
}
if (StringUtils.isEmpty(rpcXid)) {
return;
}
String unbindXid = RootContext.unbind();
if (log.isDebugEnabled()) {
log.debug("unbind {} from RootContext", unbindXid);
}
if (!rpcXid.equalsIgnoreCase(unbindXid)) {
log.warn("xid in change during RPC from {} to {}", rpcXid, unbindXid);
if (unbindXid != null) {
RootContext.bind(unbindXid);
log.warn("bind {} back to RootContext", unbindXid);
String unbindXid = RootContext.unbind();
if (log.isDebugEnabled()) {
log.debug("unbind {} from RootContext", unbindXid);
}
if (!rpcXid.equalsIgnoreCase(unbindXid)) {
log.warn("xid in change during RPC from {} to {}", rpcXid, unbindXid);
if (unbindXid != null) {
RootContext.bind(unbindXid);
log.warn("bind {} back to RootContext", unbindXid);
}
}
}
}

View File

@ -102,6 +102,20 @@ public class SentinelProperties {
*/
private Boolean httpMethodSpecify = false;
/**
* Specify whether unify web context(i.e. use the default context name), and is true
* by default.
*/
private Boolean webContextUnify = true;
public Boolean getWebContextUnify() {
return webContextUnify;
}
public void setWebContextUnify(Boolean webContextUnify) {
this.webContextUnify = webContextUnify;
}
public boolean isEager() {
return eager;
}
@ -218,9 +232,8 @@ public class SentinelProperties {
private String blockPage;
@Deprecated
@DeprecatedConfigurationProperty(
reason = "replaced to SentinelProperties#blockPage.",
replacement = SentinelConstants.PROPERTY_PREFIX + ".block-page")
@DeprecatedConfigurationProperty(reason = "replaced to SentinelProperties#blockPage.", replacement = SentinelConstants.PROPERTY_PREFIX
+ ".block-page")
public String getBlockPage() {
return blockPage;
}

View File

@ -83,19 +83,18 @@ public class SentinelWebAutoConfiguration implements WebMvcConfigurer {
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled",
matchIfMissing = true)
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true)
public SentinelWebInterceptor sentinelWebInterceptor(
SentinelWebMvcConfig sentinelWebMvcConfig) {
return new SentinelWebInterceptor(sentinelWebMvcConfig);
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled",
matchIfMissing = true)
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true)
public SentinelWebMvcConfig sentinelWebMvcConfig() {
SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig();
sentinelWebMvcConfig.setHttpMethodSpecify(properties.getHttpMethodSpecify());
sentinelWebMvcConfig.setWebContextUnify(properties.getWebContextUnify());
if (blockExceptionHandlerOptional.isPresent()) {
blockExceptionHandlerOptional

View File

@ -77,16 +77,14 @@ public class SentinelWebFluxAutoConfiguration {
@Bean
@Order(-2)
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled",
matchIfMissing = true)
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true)
public SentinelBlockExceptionHandler sentinelBlockExceptionHandler() {
return new SentinelBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(-1)
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled",
matchIfMissing = true)
@ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true)
public SentinelWebFluxFilter sentinelWebFluxFilter() {
log.info("[Sentinel Starter] register Sentinel SentinelWebFluxFilter");
return new SentinelWebFluxFilter();

View File

@ -27,16 +27,14 @@ import com.alibaba.csp.sentinel.util.StringUtil;
*/
final class BlockClassRegistry {
private static final Map<String, Method> FALLBACK_MAP = new ConcurrentHashMap<>();
private static final Map<String, Method> BLOCK_HANDLER_MAP = new ConcurrentHashMap<>();
private static final Map<String, Method> URL_CLEANER_MAP = new ConcurrentHashMap<>();
private BlockClassRegistry() {
}
private static final Map<String, Method> FALLBACK_MAP = new ConcurrentHashMap<>();
private static final Map<String, Method> BLOCK_HANDLER_MAP = new ConcurrentHashMap<>();
private static final Map<String, Method> URL_CLEANER_MAP = new ConcurrentHashMap<>();
static Method lookupFallback(Class<?> clazz, String name) {
return FALLBACK_MAP.get(getKey(clazz, name));
}

View File

@ -31,7 +31,6 @@ import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import com.alibaba.csp.sentinel.util.AppNameUtil;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
@ -79,9 +78,9 @@ public class SentinelAutoConfiguration {
System.setProperty(LogBase.LOG_NAME_USE_PID,
String.valueOf(properties.getLog().isSwitchPid()));
}
if (StringUtils.isEmpty(System.getProperty(AppNameUtil.APP_NAME))
if (StringUtils.isEmpty(System.getProperty(SentinelConfig.APP_NAME_PROP_KEY))
&& StringUtils.hasText(projectName)) {
System.setProperty(AppNameUtil.APP_NAME, projectName);
System.setProperty(SentinelConfig.APP_NAME_PROP_KEY, projectName);
}
if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT))
&& StringUtils.hasText(properties.getTransport().getPort())) {
@ -146,8 +145,7 @@ public class SentinelAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
@ConditionalOnProperty(name = "resttemplate.sentinel.enabled", havingValue = "true",
matchIfMissing = true)
@ConditionalOnProperty(name = "resttemplate.sentinel.enabled", havingValue = "true", matchIfMissing = true)
public SentinelBeanPostProcessor sentinelBeanPostProcessor(
ApplicationContext applicationContext) {
return new SentinelBeanPostProcessor(applicationContext);

View File

@ -56,13 +56,12 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
.getLogger(SentinelBeanPostProcessor.class);
private final ApplicationContext applicationContext;
private ConcurrentHashMap<String, SentinelRestTemplate> cache = new ConcurrentHashMap<>();
public SentinelBeanPostProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
private ConcurrentHashMap<String, SentinelRestTemplate> cache = new ConcurrentHashMap<>();
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class<?> beanType, String beanName) {

View File

@ -52,20 +52,13 @@ public class SentinelDataSourceHandler implements SmartInitializingSingleton {
private static final Logger log = LoggerFactory
.getLogger(SentinelDataSourceHandler.class);
private List<String> dataTypeList = Arrays.asList("json", "xml");
private final String DATA_TYPE_FIELD = "dataType";
private final String CUSTOM_DATA_TYPE = "custom";
private final String CONVERTER_CLASS_FIELD = "converterClass";
private final DefaultListableBeanFactory beanFactory;
private final SentinelProperties sentinelProperties;
private final Environment env;
private List<String> dataTypeList = Arrays.asList("json", "xml");
public SentinelDataSourceHandler(DefaultListableBeanFactory beanFactory,
SentinelProperties sentinelProperties, Environment env) {

View File

@ -61,7 +61,7 @@ public class SentinelEndpoint {
result.put("metricsFileSize", SentinelConfig.singleMetricFileSize());
result.put("metricsFileCharset", SentinelConfig.charset());
result.put("totalMetricsFileCount", SentinelConfig.totalMetricFileCount());
result.put("consoleServer", TransportConfig.getConsoleServer());
result.put("consoleServer", TransportConfig.getConsoleServerList());
result.put("clientIp", TransportConfig.getHeartbeatClientIp());
result.put("heartbeatIntervalMs", TransportConfig.getHeartbeatIntervalMs());
result.put("clientPort", TransportConfig.getPort());

View File

@ -17,6 +17,7 @@
package com.alibaba.cloud.sentinel.endpoint;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.cloud.sentinel.SentinelProperties;
@ -24,13 +25,14 @@ import com.alibaba.csp.sentinel.datasource.AbstractDataSource;
import com.alibaba.csp.sentinel.heartbeat.HeartbeatSenderProvider;
import com.alibaba.csp.sentinel.transport.HeartbeatSender;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import com.alibaba.csp.sentinel.util.function.Tuple2;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.util.StringUtils;
import org.springframework.util.CollectionUtils;
/**
* A {@link HealthIndicator} for Sentinel, which checks the status of Sentinel Dashboard
@ -82,8 +84,9 @@ public class SentinelHealthIndicator extends AbstractHealthIndicator {
// Check health of Dashboard
boolean dashboardUp = true;
String consoleServer = TransportConfig.getConsoleServer();
if (StringUtils.isEmpty(consoleServer)) {
List<Tuple2<String, Integer>> consoleServerList = TransportConfig
.getConsoleServerList();
if (CollectionUtils.isEmpty(consoleServerList)) {
// If Dashboard isn't configured, it's OK and mark the status of Dashboard
// with UNKNOWN.
detailMap.put("dashboard",
@ -101,8 +104,10 @@ public class SentinelHealthIndicator extends AbstractHealthIndicator {
else {
// If failed to send heartbeat message, means that the Dashboard is DOWN
dashboardUp = false;
detailMap.put("dashboard", new Status(Status.DOWN.getCode(),
consoleServer + " can't be connected"));
detailMap.put("dashboard",
new Status(Status.UNKNOWN.getCode(), String.format(
"the dashboard servers [%s] one of them can't be connected",
consoleServerList)));
}
}
@ -133,7 +138,7 @@ public class SentinelHealthIndicator extends AbstractHealthIndicator {
// DOWN
dataSourceUp = false;
dataSourceDetailMap.put(dataSourceBeanName,
new Status(Status.DOWN.getCode(), e.getMessage()));
new Status(Status.UNKNOWN.getCode(), e.getMessage()));
}
}
@ -142,7 +147,7 @@ public class SentinelHealthIndicator extends AbstractHealthIndicator {
withDetails(builder.up(), detailMap);
}
else {
withDetails(builder.down(), detailMap);
withDetails(builder.unknown(), detailMap);
}
}

View File

@ -32,13 +32,12 @@ import feign.MethodMetadata;
*/
public class SentinelContractHolder implements Contract {
private final Contract delegate;
/**
* map key is constructed by ClassFullName + configKey. configKey is constructed by
* {@link feign.Feign#configKey}
*/
public final static Map<String, MethodMetadata> METADATA_MAP = new HashMap<>();
private final Contract delegate;
public SentinelContractHolder(Contract delegate) {
this.delegate = delegate;

View File

@ -33,6 +33,7 @@ import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* {@link Feign.Builder} like {@link HystrixFeign.Builder}.
@ -86,7 +87,11 @@ public final class SentinelFeign {
"fallback");
Class fallbackFactory = (Class) getFieldValue(feignClientFactoryBean,
"fallbackFactory");
String beanName = (String) getFieldValue(feignClientFactoryBean, "name");
String beanName = (String) getFieldValue(feignClientFactoryBean,
"contextId");
if (!StringUtils.hasText(beanName)) {
beanName = (String) getFieldValue(feignClientFactoryBean, "name");
}
Object fallbackInstance;
FallbackFactory fallbackFactoryInstance;
@ -132,12 +137,14 @@ public final class SentinelFeign {
private Object getFieldValue(Object instance, String fieldName) {
Field field = ReflectionUtils.findField(instance.getClass(), fieldName);
field.setAccessible(true);
try {
return field.get(instance);
}
catch (IllegalAccessException e) {
// ignore
if (field != null) {
field.setAccessible(true);
try {
return field.get(instance);
}
catch (IllegalAccessException e) {
// ignore
}
}
return null;
}

View File

@ -65,13 +65,23 @@ public class SentinelInvocationHandler implements InvocationHandler {
this.dispatch = checkNotNull(dispatch, "dispatch");
}
static Map<Method, Method> toFallbackMethod(Map<Method, MethodHandler> dispatch) {
Map<Method, Method> result = new LinkedHashMap<>();
for (Method method : dispatch.keySet()) {
method.setAccessible(true);
result.put(method, method);
}
return result;
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable {
if ("equals".equals(method.getName())) {
try {
Object otherHandler = args.length > 0 && args[0] != null
? Proxy.getInvocationHandler(args[0]) : null;
? Proxy.getInvocationHandler(args[0])
: null;
return equals(otherHandler);
}
catch (IllegalArgumentException e) {
@ -166,13 +176,4 @@ public class SentinelInvocationHandler implements InvocationHandler {
return target.toString();
}
static Map<Method, Method> toFallbackMethod(Map<Method, MethodHandler> dispatch) {
Map<Method, Method> result = new LinkedHashMap<>();
for (Method method : dispatch.keySet()) {
method.setAccessible(true);
result.put(method, method);
}
return result;
}
}

View File

@ -19,7 +19,12 @@
"description": "earlier initialize heart-beat when the spring container starts when the transport dependency is on classpath, the configuration is effective."
},
{
"name": "spring.cloud.sentinel.transport.port",
"name": "spring.cloud.sentinel.web-context-unify",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "Specify whether unify web context(i.e. use the default context name), and is true by default."
},
{ "name": "spring.cloud.sentinel.transport.port",
"type": "java.lang.String",
"defaultValue": "8719",
"description": "sentinel api port."

View File

@ -1,136 +0,0 @@
///*
// * 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.sentinel;
//
//import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
//import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.cloud.openfeign.EnableFeignClients;
//import org.springframework.cloud.openfeign.FeignClient;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.test.context.junit4.SpringRunner;
//import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.PathVariable;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestParam;
//
//import static org.assertj.core.api.Assertions.assertThat;
//
///**
// * Add this unit test to verify https://github.com/alibaba/spring-cloud-alibaba/pull/838.
// *
// * @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
// */
//@RunWith(SpringRunner.class)
//@SpringBootTest(classes = { ContextIdSentinelFeignTests.TestConfig.class },
// properties = { "feign.sentinel.enabled=true" })
//public class ContextIdSentinelFeignTests {
//
// @Autowired
// private EchoService echoService;
//
// @Autowired
// private FooService fooService;
//
// @Test
// public void testFeignClient() {
// assertThat(echoService.echo("test")).isEqualTo("echo fallback");
// assertThat(fooService.echo("test")).isEqualTo("foo fallback");
// assertThat(fooService.toString()).isNotEqualTo(echoService.toString());
// assertThat(fooService.hashCode()).isNotEqualTo(echoService.hashCode());
// assertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE);
// }
//
// @Configuration
// @EnableAutoConfiguration
// @ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class })
// @EnableFeignClients
// public static class TestConfig {
//
// }
//
// @FeignClient(name = "service-provider",
// fallback = EchoServiceFallback.class,
// configuration = FeignConfiguration.class)
// public interface EchoService {
//
// @GetMapping("/echo/{str}")
// String echo(@PathVariable("str") String str);
//
// }
//
// @FeignClient(value = "foo-service",
// fallbackFactory = CustomFallbackFactory.class,
// configuration = FeignConfiguration.class)
// public interface FooService {
//
// @RequestMapping(path = "echo/{str}")
// String echo(@RequestParam("str") String param);
//
// }
//
// public static class FeignConfiguration {
//
// @Bean
// public EchoServiceFallback echoServiceFallback() {
// return new EchoServiceFallback();
// }
//
// @Bean
// public CustomFallbackFactory customFallbackFactory() {
// return new CustomFallbackFactory();
// }
//
// }
//
// public static class EchoServiceFallback implements EchoService {
//
// @Override
// public String echo(@RequestParam("str") String param) {
// return "echo fallback";
// }
//
// }
//
// public static class FooServiceFallback implements FooService {
//
// @Override
// public String echo(@RequestParam("str") String param) {
// return "foo fallback";
// }
//
// }
//
// public static class CustomFallbackFactory
// implements feign.hystrix.FallbackFactory<FooService> {
//
// private FooService fooService = new FooServiceFallback();
//
// @Override
// public FooService create(Throwable throwable) {
// return fooService;
// }
//
// }
//
//}

View File

@ -28,11 +28,10 @@ import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.log.LogBase;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import com.alibaba.csp.sentinel.util.function.Tuple2;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -64,8 +63,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author jiashuai.xie
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SentinelAutoConfigurationTests.TestConfig.class },
properties = { "spring.cloud.sentinel.filter.order=123",
@SpringBootTest(classes = {
SentinelAutoConfigurationTests.TestConfig.class }, properties = {
"spring.cloud.sentinel.filter.order=123",
"spring.cloud.sentinel.filter.urlPatterns=/*,/test",
"spring.cloud.sentinel.metric.fileSingleSize=9999",
"spring.cloud.sentinel.metric.fileTotalCount=100",
@ -73,11 +73,10 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
"spring.cloud.sentinel.flow.coldFactor=3",
"spring.cloud.sentinel.eager=true",
"spring.cloud.sentinel.log.switchPid=true",
"spring.cloud.sentinel.transport.dashboard=http://localhost:8080",
"spring.cloud.sentinel.transport.dashboard=http://localhost:8080,http://localhost:8081",
"spring.cloud.sentinel.transport.port=9999",
"spring.cloud.sentinel.transport.clientIp=1.1.1.1",
"spring.cloud.sentinel.transport.heartbeatIntervalMs=20000" },
webEnvironment = RANDOM_PORT)
"spring.cloud.sentinel.transport.heartbeatIntervalMs=20000" }, webEnvironment = RANDOM_PORT)
public class SentinelAutoConfigurationTests {
@Autowired
@ -115,13 +114,6 @@ public class SentinelAutoConfigurationTests {
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
FlowRuleManager.loadRules(Arrays.asList(rule));
DegradeRule degradeRule = new DegradeRule();
degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
degradeRule.setResource("GET:" + degradeUrl);
degradeRule.setCount(0);
degradeRule.setTimeWindow(60);
DegradeRuleManager.loadRules(Arrays.asList(degradeRule));
}
@Test
@ -142,7 +134,9 @@ public class SentinelAutoConfigurationTests {
Map<String, Object> map = sentinelEndpoint.invoke();
assertThat(map.get("logUsePid")).isEqualTo(Boolean.TRUE);
assertThat(map.get("consoleServer")).isEqualTo("http://localhost:8080");
assertThat(map.get("consoleServer").toString()).isEqualTo(
Arrays.asList(Tuple2.of("localhost", 8080), Tuple2.of("localhost", 8081))
.toString());
assertThat(map.get("clientPort")).isEqualTo("9999");
assertThat(map.get("heartbeatIntervalMs")).isEqualTo(20000L);
assertThat(map.get("clientIp")).isEqualTo("1.1.1.1");
@ -174,7 +168,7 @@ public class SentinelAutoConfigurationTests {
private void checkSentinelTransport() {
assertThat(sentinelProperties.getTransport().getPort()).isEqualTo("9999");
assertThat(sentinelProperties.getTransport().getDashboard())
.isEqualTo("http://localhost:8080");
.isEqualTo("http://localhost:8080,http://localhost:8081");
assertThat(sentinelProperties.getTransport().getClientIp()).isEqualTo("1.1.1.1");
assertThat(sentinelProperties.getTransport().getHeartbeatIntervalMs())
.isEqualTo("20000");
@ -191,7 +185,9 @@ public class SentinelAutoConfigurationTests {
@Test
public void testSentinelSystemProperties() {
assertThat(LogBase.isLogNameUsePid()).isEqualTo(true);
assertThat(TransportConfig.getConsoleServer()).isEqualTo("http://localhost:8080");
assertThat(TransportConfig.getConsoleServerList().toString()).isEqualTo(
Arrays.asList(Tuple2.of("localhost", 8080), Tuple2.of("localhost", 8081))
.toString());
assertThat(TransportConfig.getPort()).isEqualTo("9999");
assertThat(TransportConfig.getHeartbeatIntervalMs().longValue())
.isEqualTo(20000L);
@ -203,7 +199,7 @@ public class SentinelAutoConfigurationTests {
}
@Test
public void testFlowRestTemplate() {
public void testRestTemplateBlockHandler() {
assertThat(restTemplate.getInterceptors().size()).isEqualTo(2);
assertThat(restTemplateWithBlockClass.getInterceptors().size()).isEqualTo(1);
@ -231,15 +227,6 @@ public class SentinelAutoConfigurationTests {
}).isInstanceOf(RestClientException.class);
}
@Test
public void testFallbackRestTemplate() {
ResponseEntity responseEntity = restTemplateWithFallbackClass
.getForEntity(degradeUrl, String.class);
assertThat(responseEntity.getBody()).isEqualTo("Oops fallback");
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@Configuration
static class SentinelTestConfiguration {
@ -252,15 +239,13 @@ public class SentinelAutoConfigurationTests {
}
@Bean
@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class,
blockHandler = "handleException")
@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException")
RestTemplate restTemplateWithBlockClass() {
return new RestTemplate();
}
@Bean
@SentinelRestTemplate(fallbackClass = ExceptionUtil.class,
fallback = "fallbackException")
@SentinelRestTemplate(fallbackClass = ExceptionUtil.class, fallback = "fallbackException")
RestTemplate restTemplateWithFallbackClass() {
return new RestTemplate();
}

View File

@ -41,8 +41,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SentinelBeanAutowiredTests.TestConfig.class },
properties = { "spring.cloud.sentinel.filter.order=111" })
@SpringBootTest(classes = { SentinelBeanAutowiredTests.TestConfig.class }, properties = {
"spring.cloud.sentinel.filter.order=111" })
public class SentinelBeanAutowiredTests {
@Autowired

View File

@ -45,8 +45,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SentinelFeignTests.TestConfig.class },
properties = { "feign.sentinel.enabled=true" })
@SpringBootTest(classes = { SentinelFeignTests.TestConfig.class }, properties = {
"feign.sentinel.enabled=true" })
public class SentinelFeignTests {
@Autowired
@ -118,24 +118,6 @@ public class SentinelFeignTests {
assertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE);
}
@Configuration
@EnableAutoConfiguration
@ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class })
@EnableFeignClients
public static class TestConfig {
@Bean
public EchoServiceFallback echoServiceFallback() {
return new EchoServiceFallback();
}
@Bean
public CustomFallbackFactory customFallbackFactory() {
return new CustomFallbackFactory();
}
}
@FeignClient(value = "test-service", fallback = EchoServiceFallback.class)
public interface EchoService {
@ -172,6 +154,24 @@ public class SentinelFeignTests {
}
@Configuration
@EnableAutoConfiguration
@ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class })
@EnableFeignClients
public static class TestConfig {
@Bean
public EchoServiceFallback echoServiceFallback() {
return new EchoServiceFallback();
}
@Bean
public CustomFallbackFactory customFallbackFactory() {
return new CustomFallbackFactory();
}
}
public static class EchoServiceFallback implements EchoService {
@Override

View File

@ -188,13 +188,7 @@ public class SentinelRestTemplateTests {
}
@Bean
@SentinelRestTemplate(
blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,
blockHandler = "handleException",
fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,
fallback = "fallbackException",
urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,
urlCleaner = "clean")
@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException", fallbackClass = ExceptionUtil.class, fallback = "fallbackException", urlCleanerClass = UrlCleanUtil.class, urlCleaner = "clean")
RestTemplate restTemplate() {
return new RestTemplate();
}
@ -211,9 +205,7 @@ public class SentinelRestTemplateTests {
}
@Bean
@SentinelRestTemplate(
blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,
blockHandler = "handleException1")
@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException1")
RestTemplate restTemplate() {
return new RestTemplate();
}
@ -230,9 +222,7 @@ public class SentinelRestTemplateTests {
}
@Bean
@SentinelRestTemplate(
fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,
fallback = "fallbackException1")
@SentinelRestTemplate(fallbackClass = ExceptionUtil.class, fallback = "fallbackException1")
RestTemplate restTemplate() {
return new RestTemplate();
}
@ -249,9 +239,7 @@ public class SentinelRestTemplateTests {
}
@Bean
@SentinelRestTemplate(
blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,
blockHandler = "handleException2")
@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class, blockHandler = "handleException2")
RestTemplate restTemplate() {
return new RestTemplate();
}
@ -268,9 +256,7 @@ public class SentinelRestTemplateTests {
}
@Bean
@SentinelRestTemplate(
fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,
fallback = "fallbackException2")
@SentinelRestTemplate(fallbackClass = ExceptionUtil.class, fallback = "fallbackException2")
RestTemplate restTemplate() {
return new RestTemplate();
}
@ -344,9 +330,7 @@ public class SentinelRestTemplateTests {
}
@Bean
@SentinelRestTemplate(
urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,
urlCleaner = "clean1")
@SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class, urlCleaner = "clean1")
RestTemplate restTemplate() {
return new RestTemplate();
}
@ -363,9 +347,7 @@ public class SentinelRestTemplateTests {
}
@Bean
@SentinelRestTemplate(
urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,
urlCleaner = "clean2")
@SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class, urlCleaner = "clean2")
RestTemplate restTemplate() {
return new RestTemplate();
}

View File

@ -109,9 +109,9 @@ public class SentinelHealthIndicatorTests {
Health health = sentinelHealthIndicator.health();
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
assertThat(health.getDetails().get("dashboard")).isEqualTo(
new Status(Status.DOWN.getCode(), "localhost:8080 can't be connected"));
assertThat(health.getStatus()).isEqualTo(Status.UNKNOWN);
assertThat(health.getDetails().get("dashboard")).isEqualTo(new Status(
Status.UNKNOWN.getCode(), "localhost:8080 can't be connected"));
}
@Test
@ -163,13 +163,13 @@ public class SentinelHealthIndicatorTests {
Health health = sentinelHealthIndicator.health();
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
assertThat(health.getStatus()).isEqualTo(Status.UNKNOWN);
Map<String, Status> dataSourceDetailMap = (Map<String, Status>) health
.getDetails().get("dataSource");
assertThat(dataSourceDetailMap.get("ds1-sentinel-file-datasource"))
.isEqualTo(Status.UP);
assertThat(dataSourceDetailMap.get("ds2-sentinel-file-datasource"))
.isEqualTo(new Status(Status.DOWN.getCode(), "fileDataSource2 error"));
.isEqualTo(new Status(Status.UNKNOWN.getCode(), "fileDataSource2 error"));
}
}

View File

@ -18,7 +18,6 @@ package com.alibaba.cloud.sidecar;
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
@ -28,7 +27,6 @@ import org.springframework.web.client.RestTemplate;
* @author www.itmuch.com
*/
@Configuration
@EnableConfigurationProperties(SidecarProperties.class)
public class SidecarAutoConfiguration {
@Bean

View File

@ -16,6 +16,9 @@
package com.alibaba.cloud.sidecar;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
@ -28,11 +31,14 @@ import org.springframework.core.env.ConfigurableEnvironment;
/**
* @author www.itmuch.com
* @author yuhuangbin
*/
public class SidecarHealthChecker {
private static final Logger log = LoggerFactory.getLogger(SidecarHealthChecker.class);
private final Map<String, SidecarInstanceCache> sidecarInstanceCacheMap = new ConcurrentHashMap<>();
private final SidecarDiscoveryClient sidecarDiscoveryClient;
private final HealthIndicator healthIndicator;
@ -52,26 +58,59 @@ public class SidecarHealthChecker {
public void check() {
Schedulers.single().schedulePeriodically(() -> {
String applicationName = environment.getProperty("spring.application.name");
String ip = sidecarProperties.getIp();
Integer port = sidecarProperties.getPort();
Status status = healthIndicator.health().getStatus();
String applicationName = environment.getProperty("spring.application.name");
instanceCache(applicationName, ip, port, status);
if (status.equals(Status.UP)) {
this.sidecarDiscoveryClient.registerInstance(applicationName, ip, port);
log.debug(
"Health check success. register this instance. applicationName = {}, ip = {}, port = {}, status = {}",
applicationName, ip, port, status);
if (needRegister(applicationName, ip, port, status)) {
this.sidecarDiscoveryClient.registerInstance(applicationName, ip,
port);
log.info(
"Polyglot service changed and Health check success. register the new instance. applicationName = {}, ip = {}, port = {}, status = {}",
applicationName, ip, port, status);
}
}
else {
log.warn(
"Health check failed. unregister this instance. applicationName = {}, ip = {}, port = {}, status = {}",
applicationName, ip, port, status);
this.sidecarDiscoveryClient.deregisterInstance(applicationName, ip, port);
sidecarInstanceCacheMap.put(applicationName,
buildCache(ip, port, status));
}
}, 0, sidecarProperties.getHealthCheckInterval(), TimeUnit.MILLISECONDS);
}
private void instanceCache(String applicationName, String ip, Integer port,
Status status) {
sidecarInstanceCacheMap.putIfAbsent(applicationName,
buildCache(ip, port, status));
}
private boolean needRegister(String applicationName, String ip, Integer port,
Status status) {
SidecarInstanceCache cacheRecord = sidecarInstanceCacheMap.get(applicationName);
SidecarInstanceCache cache = buildCache(ip, port, status);
if (!Objects.equals(cache, cacheRecord)) {
// modify the cache info
sidecarInstanceCacheMap.put(applicationName, cache);
return true;
}
return false;
}
private SidecarInstanceCache buildCache(String ip, Integer port, Status status) {
SidecarInstanceCache cache = new SidecarInstanceCache();
cache.setIp(ip);
cache.setPort(port);
cache.setStatus(status);
return cache;
}
}

View File

@ -0,0 +1,76 @@
/*
* 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.sidecar;
import java.util.Objects;
import org.springframework.boot.actuate.health.Status;
/**
* @author yuhuangbin
*/
public class SidecarInstanceCache {
private String ip;
private Integer port;
private Status status;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SidecarInstanceCache that = (SidecarInstanceCache) o;
return Objects.equals(ip, that.ip) && Objects.equals(port, that.port)
&& Objects.equals(status, that.status);
}
@Override
public int hashCode() {
return Objects.hash(ip, port, status);
}
}

View File

@ -1,71 +0,0 @@
/*
* 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.sidecar.consul;
import java.util.List;
import com.alibaba.cloud.sidecar.SidecarAutoConfiguration;
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
import com.alibaba.cloud.sidecar.SidecarProperties;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration;
import org.springframework.cloud.consul.serviceregistry.ConsulRegistrationCustomizer;
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author www.itmuch.com
*/
@Configuration
@ConditionalOnClass(ConsulServiceRegistryAutoConfiguration.class)
@AutoConfigureBefore({ ConsulAutoServiceRegistrationAutoConfiguration.class,
SidecarAutoConfiguration.class })
public class SidecarConsulAutoConfiguration {
@Bean
public ConsulAutoRegistration consulRegistration(
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ConsulDiscoveryProperties properties, ApplicationContext applicationContext,
ObjectProvider<List<ConsulRegistrationCustomizer>> registrationCustomizers,
HeartbeatProperties heartbeatProperties,
SidecarProperties sidecarProperties) {
return SidecarConsulAutoRegistration.registration(
autoServiceRegistrationProperties, properties, applicationContext,
registrationCustomizers.getIfAvailable(),
heartbeatProperties,
sidecarProperties);
}
@Bean
public SidecarDiscoveryClient sidecarDiscoveryClient(
ConsulDiscoveryProperties properties, ConsulServiceRegistry serviceRegistry,
ConsulAutoRegistration registration) {
return new SidecarConsulDiscoveryClient(properties, serviceRegistry,
registration);
}
}

View File

@ -1,84 +0,0 @@
/*
* 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.sidecar.consul;
import java.util.List;
import com.alibaba.cloud.sidecar.SidecarProperties;
import com.ecwid.consul.v1.agent.model.NewService;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
import org.springframework.cloud.consul.serviceregistry.ConsulRegistrationCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
/**
* @author www.itmuch.com
*/
public class SidecarConsulAutoRegistration extends ConsulAutoRegistration {
public SidecarConsulAutoRegistration(NewService service,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ConsulDiscoveryProperties properties, ApplicationContext context,
HeartbeatProperties heartbeatProperties) {
super(service, autoServiceRegistrationProperties, properties, context,
heartbeatProperties);
}
public static ConsulAutoRegistration registration(
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ConsulDiscoveryProperties properties, ApplicationContext context,
List<ConsulRegistrationCustomizer> registrationCustomizers,
HeartbeatProperties heartbeatProperties,
SidecarProperties sidecarProperties) {
NewService service = new NewService();
String appName = getAppName(properties, context.getEnvironment());
service.setId(getInstanceId(sidecarProperties, context.getEnvironment()));
if (!properties.isPreferAgentAddress()) {
service.setAddress(sidecarProperties.getIp());
}
service.setName(normalizeForDns(appName));
service.setTags(createTags(properties));
// set health check, use alibaba sidecar self's port rather than polyglot app's
// port.
service.setPort(
Integer.valueOf(context.getEnvironment().getProperty("server.port")));
setCheck(service, autoServiceRegistrationProperties, properties, context,
heartbeatProperties);
service.setPort(sidecarProperties.getPort());
ConsulAutoRegistration registration = new ConsulAutoRegistration(service,
autoServiceRegistrationProperties, properties, context,
heartbeatProperties);
customize(registrationCustomizers, registration);
return registration;
}
public static String getInstanceId(SidecarProperties sidecarProperties,
Environment environment) {
return String.format("%s-%s-%s",
environment.getProperty("spring.application.name"),
sidecarProperties.getIp(), sidecarProperties.getPort());
}
}

View File

@ -1,68 +0,0 @@
/*
* 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.sidecar.consul;
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;
/**
* @author www.itmuch.com
*/
public class SidecarConsulDiscoveryClient implements SidecarDiscoveryClient {
private static final Logger log = LoggerFactory
.getLogger(SidecarConsulDiscoveryClient.class);
private final ConsulDiscoveryProperties properties;
private final ConsulServiceRegistry serviceRegistry;
private final ConsulAutoRegistration registration;
public SidecarConsulDiscoveryClient(ConsulDiscoveryProperties properties,
ConsulServiceRegistry serviceRegistry, ConsulAutoRegistration registration) {
this.properties = properties;
this.serviceRegistry = serviceRegistry;
this.registration = registration;
}
@Override
public void registerInstance(String applicationName, String ip, Integer port) {
if (!this.properties.isRegister()) {
log.debug("Registration disabled.");
return;
}
serviceRegistry.register(registration);
}
@Override
public void deregisterInstance(String applicationName, String ip, Integer port) {
if (!this.properties.isRegister() || !this.properties.isDeregister()) {
return;
}
serviceRegistry.deregister(registration);
}
}

View File

@ -17,6 +17,7 @@
package com.alibaba.cloud.sidecar.nacos;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;
import com.alibaba.cloud.sidecar.SidecarAutoConfiguration;
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
@ -25,6 +26,7 @@ import com.alibaba.cloud.sidecar.SidecarProperties;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -35,6 +37,7 @@ import org.springframework.context.annotation.Configuration;
@AutoConfigureBefore({ NacosDiscoveryAutoConfiguration.class,
SidecarAutoConfiguration.class })
@ConditionalOnClass(NacosDiscoveryProperties.class)
@EnableConfigurationProperties(SidecarProperties.class)
public class SidecarNacosAutoConfiguration {
@Bean
@ -47,8 +50,10 @@ public class SidecarNacosAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SidecarDiscoveryClient sidecarDiscoveryClient(
NacosServiceManager nacosServiceManager,
SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) {
return new SidecarNacosDiscoveryClient(sidecarNacosDiscoveryProperties);
return new SidecarNacosDiscoveryClient(nacosServiceManager,
sidecarNacosDiscoveryProperties);
}
}

View File

@ -16,8 +16,10 @@
package com.alibaba.cloud.sidecar.nacos;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -28,10 +30,10 @@ public class SidecarNacosDiscoveryClient implements SidecarDiscoveryClient {
private static final Logger log = LoggerFactory
.getLogger(SidecarNacosDiscoveryClient.class);
private final SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties;
private NacosServiceManager nacosServiceManager;
public SidecarNacosDiscoveryClient(
public SidecarNacosDiscoveryClient(NacosServiceManager nacosServiceManager,
SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) {
this.sidecarNacosDiscoveryProperties = sidecarNacosDiscoveryProperties;
}
@ -39,8 +41,8 @@ public class SidecarNacosDiscoveryClient implements SidecarDiscoveryClient {
@Override
public void registerInstance(String applicationName, String ip, Integer port) {
try {
this.sidecarNacosDiscoveryProperties.namingServiceInstance()
.registerInstance(applicationName, ip, port);
this.namingService().registerInstance(applicationName,
sidecarNacosDiscoveryProperties.getGroup(), ip, port);
}
catch (NacosException e) {
log.warn("nacos exception happens", e);
@ -50,12 +52,17 @@ public class SidecarNacosDiscoveryClient implements SidecarDiscoveryClient {
@Override
public void deregisterInstance(String applicationName, String ip, Integer port) {
try {
this.sidecarNacosDiscoveryProperties.namingServiceInstance()
.deregisterInstance(applicationName, ip, port);
this.namingService().deregisterInstance(applicationName,
sidecarNacosDiscoveryProperties.getGroup(), ip, port);
}
catch (NacosException e) {
log.warn("nacos exception happens", e);
}
}
private NamingService namingService() {
return nacosServiceManager
.getNamingService(sidecarNacosDiscoveryProperties.getNacosProperties());
}
}

View File

@ -16,29 +16,29 @@
package com.alibaba.cloud.sidecar.nacos;
import java.net.SocketException;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.sidecar.SidecarProperties;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StringUtils;
/**
* @author itmuch.com
* @author yuhuangbin
*/
public class SidecarNacosDiscoveryProperties extends NacosDiscoveryProperties {
private final SidecarProperties sidecarProperties;
SidecarProperties sidecarProperties;
public SidecarNacosDiscoveryProperties(SidecarProperties sidecarProperties) {
this.sidecarProperties = sidecarProperties;
}
@Override
public void init() throws SocketException {
public void init() throws Exception {
super.init();
String ip = sidecarProperties.getIp();
if (StringUtils.isNotBlank(ip)) {
if (!StringUtils.isEmpty(ip)) {
this.setIp(ip);
}

View File

@ -31,8 +31,7 @@ import org.springframework.context.annotation.PropertySource;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@ConditionalOnClass(
name = "org.springframework.boot.actuate.endpoint.annotation.Endpoint")
@ConditionalOnClass(name = "org.springframework.boot.actuate.endpoint.annotation.Endpoint")
@PropertySource("classpath:/META-INF/dubbo/default/actuator-endpoints.properties")
@ManagementContextConfiguration
public class DubboMetadataEndpointAutoConfiguration {

View File

@ -37,12 +37,16 @@ import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RETRIES;
* Spring Cloud Service-to-Service call is transported by Dubbo under the hood, there are
* two main scenarios:
* <ol>
* <li>{@link FeignClient @FeignClient} annotated classes: If
* {@link DubboTransported @DubboTransported} annotated classes, the invocation of all
* <li>{@link FeignClient @FeignClient} annotated classes:
* <ul>
* If {@link DubboTransported @DubboTransported} annotated classes, the invocation of all
* methods of {@link FeignClient @FeignClient} annotated classes.
*
* </ul>
* <ul>
* If {@link DubboTransported @DubboTransported} annotated methods of
* {@link FeignClient @FeignClient} annotated classes.</li>
* {@link FeignClient @FeignClient} annotated classes.
* </ul>
* </li>
* <li>{@link LoadBalanced @LoadBalanced} {@link RestTemplate} annotated field, method and
* parameters</li>
* </ol>

View File

@ -111,7 +111,8 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements
@Override
public void afterSingletonsInstantiated() {
loadBalancerInterceptorBean = retryLoadBalancerInterceptor != null
? retryLoadBalancerInterceptor : loadBalancerInterceptor;
? retryLoadBalancerInterceptor
: loadBalancerInterceptor;
}
/**
@ -145,7 +146,7 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements
* Gets the annotation attributes {@link RestTemplate} bean being annotated
* {@link DubboTransported @DubboTransported}.
* @param beanName the bean name of {@link LoadBalanced @LoadBalanced}
* {@link RestTemplate}
* {@link RestTemplate}
* @param attributesResolver {@link DubboTransportedAttributesResolver}
* @return non-null {@link Map}
*/
@ -170,8 +171,8 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements
* {@link LoadBalancerInterceptor} Bean.
* @param restTemplate {@link LoadBalanced @LoadBalanced} {@link RestTemplate} Bean
* @param dubboTranslatedAttributes the annotation dubboTranslatedAttributes
* {@link RestTemplate} bean being annotated
* {@link DubboTransported @DubboTransported}
* {@link RestTemplate} bean being annotated
* {@link DubboTransported @DubboTransported}
*/
private void adaptRestTemplate(RestTemplate restTemplate,
Map<String, Object> dubboTranslatedAttributes) {

View File

@ -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
@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();

View File

@ -35,8 +35,8 @@ import static com.alibaba.cloud.dubbo.autoconfigure.DubboOpenFeignAutoConfigurat
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@ConditionalOnClass(name = { "feign.Feign", TARGETER_CLASS_NAME })
@AutoConfigureAfter(
name = { "org.springframework.cloud.openfeign.FeignAutoConfiguration" })
@AutoConfigureAfter(name = {
"org.springframework.cloud.openfeign.FeignAutoConfiguration" })
@Configuration
public class DubboOpenFeignAutoConfiguration {

View File

@ -24,15 +24,11 @@ import com.alibaba.cloud.dubbo.service.parameter.RequestBodyServiceParameterReso
import com.alibaba.cloud.dubbo.service.parameter.RequestHeaderServiceParameterResolver;
import com.alibaba.cloud.dubbo.service.parameter.RequestParamServiceParameterResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
/**
* Spring Boot Auto-Configuration class for Dubbo Service.
@ -49,17 +45,6 @@ public class DubboServiceAutoConfiguration {
return new DubboGenericServiceFactory();
}
/**
* Build a primary {@link PropertyResolver} bean to {@link Autowired @Autowired}.
* @param environment {@link Environment}
* @return alias bean for {@link Environment}
*/
@Bean
@Primary
public PropertyResolver primaryPropertyResolver(Environment environment) {
return environment;
}
@Configuration
@Import({ DubboGenericServiceExecutionContextFactory.class,
RequestParamServiceParameterResolver.class,

View File

@ -33,6 +33,7 @@ import com.alibaba.cloud.dubbo.registry.AbstractSpringCloudRegistry;
import com.alibaba.cloud.dubbo.registry.event.ServiceInstancesChangedEvent;
import com.alibaba.cloud.dubbo.registry.event.SubscribedServicesChangedEvent;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.discovery.NacosWatch;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
@ -56,6 +57,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;
@ -97,12 +99,11 @@ import static org.springframework.util.StringUtils.hasText;
@Configuration
@ConditionalOnClass(name = "org.springframework.cloud.client.discovery.DiscoveryClient")
@ConditionalOnProperty(name = "spring.cloud.discovery.enabled", matchIfMissing = true)
@AutoConfigureAfter(
name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME,
ZOOKEEPER_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME,
CONSUL_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME,
NACOS_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME },
value = { DubboServiceRegistrationAutoConfiguration.class })
@AutoConfigureAfter(name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME,
ZOOKEEPER_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME,
CONSUL_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME,
NACOS_DISCOVERY_AUTO_CONFIGURATION_CLASS_NAME }, value = {
DubboServiceRegistrationAutoConfiguration.class })
public class DubboServiceDiscoveryAutoConfiguration {
/**
@ -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()) {
@ -512,8 +518,10 @@ public class DubboServiceDiscoveryAutoConfiguration {
*/
private final Set<String> listeningServices;
NacosConfiguration(NacosDiscoveryProperties nacosDiscoveryProperties) {
this.namingService = nacosDiscoveryProperties.namingServiceInstance();
NacosConfiguration(NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
this.namingService = nacosServiceManager
.getNamingService(nacosDiscoveryProperties.getNacosProperties());
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.listeningServices = new ConcurrentSkipListSet<>();
}

View File

@ -66,12 +66,11 @@ import static org.springframework.util.ObjectUtils.isEmpty;
*/
@Configuration
@Import({ DubboServiceRegistrationEventPublishingAspect.class })
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter(name = { EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME,
CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME,
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" },
value = { DubboMetadataAutoConfiguration.class })
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" }, value = {
DubboMetadataAutoConfiguration.class })
public class DubboServiceRegistrationAutoConfiguration {
/**

View File

@ -53,8 +53,7 @@ import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAuto
*/
@Configuration
@ConditionalOnNotWebApplication
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter(DubboServiceRegistrationAutoConfiguration.class)
@Aspect
public class DubboServiceRegistrationNonWebApplicationAutoConfiguration {
@ -76,12 +75,17 @@ public class DubboServiceRegistrationNonWebApplicationAutoConfiguration {
@Around("execution(* org.springframework.cloud.client.serviceregistry.Registration.getPort())")
public Object getPort(ProceedingJoinPoint pjp) throws Throwable {
/**
* move setServerPort from onApplicationStarted() to here for this issue :
* https://github.com/alibaba/spring-cloud-alibaba/issues/1383
* @author <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
*/
setServerPort();
return serverPort != null ? serverPort : pjp.proceed();
}
@EventListener(ApplicationStartedEvent.class)
public void onApplicationStarted() {
setServerPort();
register();
}
@ -99,18 +103,22 @@ public class DubboServiceRegistrationNonWebApplicationAutoConfiguration {
*/
private void setServerPort() {
if (serverPort == null) {
for (List<URL> urls : repository.getAllExportedUrls().values()) {
urls.stream()
.filter(url -> REST_PROTOCOL.equalsIgnoreCase(url.getProtocol()))
.findFirst().ifPresent(url -> {
serverPort = url.getPort();
});
// If REST protocol is not present, use any applied port.
synchronized (this) {
if (serverPort == null) {
urls.stream().findAny().ifPresent(url -> {
serverPort = url.getPort();
});
for (List<URL> urls : repository.getAllExportedUrls().values()) {
urls.stream().filter(
url -> REST_PROTOCOL.equalsIgnoreCase(url.getProtocol()))
.findFirst().ifPresent(url -> {
serverPort = url.getPort();
});
// If REST protocol is not present, use any applied port.
if (serverPort == null) {
urls.stream().findAny().ifPresent(url -> {
serverPort = url.getPort();
});
}
}
}
}
}
@ -126,6 +134,7 @@ public class DubboServiceRegistrationNonWebApplicationAutoConfiguration {
@EventListener(ServiceInstancePreRegisteredEvent.class)
public void onServiceInstancePreRegistered(
ServiceInstancePreRegisteredEvent event) {
setServerPort();
registration.setPort(serverPort);
}

View File

@ -22,6 +22,8 @@ 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;
@ -31,7 +33,7 @@ import static org.springframework.util.StringUtils.trimAllWhitespace;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@ConfigurationProperties(prefix = "dubbo.cloud")
@ConfigurationProperties(prefix = CONFIG_PROPERTY_PREFIX)
public class DubboCloudProperties {
/**
@ -47,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;
}
@ -79,4 +83,12 @@ public class DubboCloudProperties {
return Collections.unmodifiableSet(subscribedServices);
}
public String getRegistryType() {
return registryType;
}
public void setRegistryType(String registryType) {
this.registryType = registryType;
}
}

View File

@ -34,8 +34,8 @@ import org.springframework.core.env.PropertySource;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL;
import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL;
/**
* Dubbo {@link WebApplicationType#NONE Non-Web Application}
@ -141,7 +141,8 @@ public class DubboNonWebApplicationEnvironmentPostProcessor
DEFAULT_PROTOCOL);
return isRestProtocol(protocol)
? environment.getProperty(PROTOCOL_PORT_PROPERTY_NAME) : null;
? environment.getProperty(PROTOCOL_PORT_PROPERTY_NAME)
: null;
}
private String getRestPortFromProtocolsProperties(

View File

@ -41,7 +41,7 @@ public class HttpRequestConsumersMatcher extends AbstractHttpRequestMatcher {
/**
* Creates a new instance from 0 or more "consumes" expressions.
* @param consumes consumes expressions if 0 expressions are provided, the condition
* will match to every request
* will match to every request
*/
public HttpRequestConsumersMatcher(String... consumes) {
this(consumes, null);

View File

@ -34,10 +34,10 @@ public class HttpRequestParamsMatcher extends AbstractHttpRequestMatcher {
/**
* @param params The pattern of params :
* <ul>
* <li>name=value</li>
* <li>name</li>
* </ul>
* <ul>
* <li>name=value</li>
* <li>name</li>
* </ul>
*/
public HttpRequestParamsMatcher(String... params) {
this.expressions = parseExpressions(params);

View File

@ -65,7 +65,6 @@ public class DubboProtocolConfigSupplier implements Supplier<ProtocolConfig> {
if (protocolConfig == null) {
protocolConfig = new ProtocolConfig();
protocolConfig.setName(DEFAULT_PROTOCOL);
protocolConfig.setPort(-1);
}
return protocolConfig;

View File

@ -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 failold 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,27 +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
@ -459,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,
@ -492,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;
}
@ -600,8 +531,7 @@ public class DubboServiceMetadataRepository
Set<ServiceRestMetadata> metadata = emptySet();
DubboMetadataService dubboMetadataService = dubboMetadataConfigServiceProxy
.getProxy(serviceName);
DubboMetadataService dubboMetadataService = getProxy(serviceName);
if (dubboMetadataService != null) {
try {
@ -626,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;
}
}

View File

@ -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())));
}
}

View File

@ -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);
}

View File

@ -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);
}
@ -398,4 +394,4 @@ public abstract class AbstractSpringCloudRegistry extends FailbackRegistry {
return DUBBO_METADATA_SERVICE_CLASS_NAME.equals(url.getServiceInterface());
}
}
}

Some files were not shown because too many files have changed in this diff Show More