diff --git a/README-zh.md b/README-zh.md
index 5b5bdf636..ca01258e6 100644
--- a/README-zh.md
+++ b/README-zh.md
@@ -70,7 +70,7 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone
com.alibaba.cloud
spring-cloud-alibaba-dependencies
- 2.2.0.RELEASE
+ 2.2.2.RELEASE
pom
import
diff --git a/README.md b/README.md
index 4f946dc4c..7dd069c56 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ For more features, please refer to [Roadmap](https://github.com/alibaba/spring-c
**[Alibaba Cloud SMS](https://www.aliyun.com/product/sms)**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers.
-**[Alibaba Cloud SchedulerX](https://www.aliyun.com/product/SchedulerX)**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds..
+**[Alibaba Cloud SchedulerX](https://www.aliyun.com/aliware/schedulerx?spm=5176.10695662.784137.1.4b07363dej23L3)**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds..
For more features please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md).
@@ -71,7 +71,7 @@ These artifacts are available from Maven Central and Spring Release repository v
com.alibaba.cloud
spring-cloud-alibaba-dependencies
- 2.2.1.RELEASE
+ 2.2.2.RELEASE
pom
import
diff --git a/pom.xml b/pom.xml
index 13b06fdda..64b455188 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,7 +80,7 @@
- 2.2.2-SNAPSHOT
+ 2.2.2.RELEASE
2.2.5.RELEASE
diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml
index 222576d80..7a1870ce1 100644
--- a/spring-cloud-alibaba-dependencies/pom.xml
+++ b/spring-cloud-alibaba-dependencies/pom.xml
@@ -18,7 +18,7 @@
Spring Cloud Alibaba Dependencies
- 2.2.2-SNAPSHOT
+ 2.2.2.RELEASE
1.8.0
3.1.0
1.3.0
diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/dependency-management.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/dependency-management.adoc
index 834bf75c5..5a3dc3334 100644
--- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/dependency-management.adoc
+++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/dependency-management.adoc
@@ -10,7 +10,7 @@ Spring Cloud Alibaba BOM 包含了它所使用的所有依赖的版本。
com.alibaba.cloud
spring-cloud-alibaba-dependencies
- 2.2.0.RELEASE
+ 2.2.2.RELEASE
pom
import
diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc
index ee22c0e4c..789d1aed1 100644
--- a/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc
+++ b/spring-cloud-alibaba-docs/src/main/asciidoc/dependency-management.adoc
@@ -8,7 +8,7 @@ If you’re a Maven Central user, add our BOM to your pom.xml
com.alibaba.cloud
spring-cloud-alibaba-dependencies
- 2.2.0.RELEASE
+ 2.2.2.RELEASE
pom
import
diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OderApplication.java b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderApplication.java
similarity index 92%
rename from spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OderApplication.java
rename to spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderApplication.java
index b1233273f..33e31a71d 100644
--- a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OderApplication.java
+++ b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/java/com/alibaba/cloud/examples/OrderApplication.java
@@ -25,10 +25,10 @@ import org.springframework.web.client.RestTemplate;
* @author xiaojing
*/
@SpringBootApplication
-public class OderApplication {
+public class OrderApplication {
public static void main(String[] args) {
- SpringApplication.run(OderApplication.class, args);
+ SpringApplication.run(OrderApplication.class, args);
}
@Bean
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java
index 612345165..af722dda2 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosDiscoveryClientConfiguration.java
@@ -18,8 +18,8 @@ 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;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -31,7 +31,6 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.TaskScheduler;
/**
* @author xiaojing
@@ -56,9 +55,9 @@ public class NacosDiscoveryClientConfiguration {
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.watch.enabled",
matchIfMissing = true)
- public NacosWatch nacosWatch(NacosDiscoveryProperties nacosDiscoveryProperties,
- ObjectProvider taskScheduler) {
- return new NacosWatch(nacosDiscoveryProperties, taskScheduler);
+ public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager,
+ NacosDiscoveryProperties nacosDiscoveryProperties) {
+ return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties);
}
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java
index b5dfc8e3a..ff9040ae7 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/NacosWatch.java
@@ -16,67 +16,54 @@
package com.alibaba.cloud.nacos.discovery;
-import java.util.concurrent.ScheduledFuture;
+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.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;
-import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.SmartLifecycle;
-import org.springframework.scheduling.TaskScheduler;
-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 Map listenerMap = new ConcurrentHashMap<>(16);
- private final TaskScheduler taskScheduler;
+ private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicLong nacosWatchIndex = new AtomicLong(0);
- private final AtomicBoolean running = new AtomicBoolean(false);
-
private ApplicationEventPublisher publisher;
- private ScheduledFuture> watchFuture;
+ private NacosServiceManager nacosServiceManager;
- public NacosWatch(NacosDiscoveryProperties properties) {
- this(properties, getTaskScheduler());
- }
+ private final NacosDiscoveryProperties properties;
- public NacosWatch(NacosDiscoveryProperties properties, TaskScheduler taskScheduler) {
+ public NacosWatch(NacosServiceManager nacosServiceManager,
+ NacosDiscoveryProperties properties) {
+ this.nacosServiceManager = nacosServiceManager;
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,
- ObjectProvider taskScheduler) {
- this(properties, taskScheduler.getIfAvailable(NacosWatch::getTaskScheduler));
- }
-
- private static ThreadPoolTaskScheduler getTaskScheduler() {
- ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
- taskScheduler.setBeanName("Nacos-Watch-Task-Scheduler");
- taskScheduler.initialize();
- return taskScheduler;
}
@Override
@@ -98,19 +85,67 @@ public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycl
@Override
public void start() {
if (this.running.compareAndSet(false, true)) {
- this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(
- this::nacosServicesWatch, this.properties.getWatchDelay());
+ EventListener eventListener = listenerMap.computeIfAbsent(buildKey(),
+ event -> new EventListener() {
+ @Override
+ public void onEvent(Event event) {
+ if (event instanceof NamingEvent) {
+ List instances = ((NamingEvent) event)
+ .getInstances();
+ Optional instanceOptional = selectCurrentInstance(
+ instances);
+ instanceOptional.ifPresent(currentInstance -> {
+ resetIfNeeded(currentInstance);
+ });
+ publisher.publishEvent(new HeartbeatEvent(NacosWatch.this,
+ nacosWatchIndex.getAndIncrement()));
+ }
+ }
+ });
+
+ 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);
+ }
+ }
+ }
+
+ 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 selectCurrentInstance(List 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();
-
- this.watchFuture.cancel(true);
+ if (this.running.compareAndSet(true, false)) {
+ EventListener eventListener = listenerMap.get(buildKey());
+ NamingService namingService = nacosServiceManager
+ .getNamingService(properties.getNacosProperties());
+ try {
+ namingService.unsubscribe(properties.getService(), properties.getGroup(),
+ Arrays.asList(properties.getClusterName()), eventListener);
+ }
+ catch (NacosException e) {
+ log.error("namingService unsubscribe failed, properties:{}", properties,
+ e);
+ }
}
}
@@ -124,12 +159,4 @@ public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycl
return 0;
}
- public void nacosServicesWatch() {
-
- // nacos doesn't support watch now , publish an event every 30 seconds.
- this.publisher.publishEvent(
- new HeartbeatEvent(this, nacosWatchIndex.getAndIncrement()));
-
- }
-
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java
index 86d331b05..f7ec7659a 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-seata/src/main/java/com/alibaba/cloud/seata/web/SeataHandlerInterceptor.java
@@ -41,45 +41,46 @@ public class SeataHandlerInterceptor implements HandlerInterceptor {
.getLogger(SeataHandlerInterceptor.class);
@Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
- String xid = RootContext.getXID();
- String rpcXid = request.getHeader(RootContext.KEY_XID);
- if (log.isDebugEnabled()) {
- log.debug("xid in RootContext {} xid in RpcContext {}", xid, rpcXid);
- }
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
+ Object handler) {
+ String xid = RootContext.getXID();
+ String rpcXid = request.getHeader(RootContext.KEY_XID);
+ if (log.isDebugEnabled()) {
+ log.debug("xid in RootContext {} xid in RpcContext {}", xid, rpcXid);
+ }
- if (StringUtils.isBlank(xid) && rpcXid != null) {
- RootContext.bind(rpcXid);
- if (log.isDebugEnabled()) {
- log.debug("bind {} to RootContext", rpcXid);
- }
- }
+ if (StringUtils.isBlank(xid) && rpcXid != null) {
+ RootContext.bind(rpcXid);
+ if (log.isDebugEnabled()) {
+ log.debug("bind {} to RootContext", rpcXid);
+ }
+ }
- return true;
- }
+ return true;
+ }
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
+ Object handler, Exception e) {
+ if (StringUtils.isNotBlank(RootContext.getXID())) {
+ String rpcXid = request.getHeader(RootContext.KEY_XID);
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
- if (StringUtils.isNotBlank(RootContext.getXID())) {
- 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);
+ }
+ }
+ }
+ }
}