From a42bd2e3a9f8e3080630dbe242f8d807fa092a60 Mon Sep 17 00:00:00 2001 From: Roger3581321 Date: Wed, 7 Oct 2020 12:15:08 +0800 Subject: [PATCH 01/99] explicitly use standalone mode in windows explicitly use standalone mode otherwise cluster mode in windows batch environment --- .../nacos-example/nacos-config-example/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md index 797c09cc1..d93464ece 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md @@ -46,7 +46,7 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl 2. Unzip the downloaded file and go to the nacos/bin folder(), And according to the actual situation of the operating system, execute the following command。[see reference for more detail](https://nacos.io/en-us/docs/quick-start.html)。 1. Linux/Unix/Mac , execute `sh startup.sh -m standalone` - 2. Windows , execute `cmd startup.cmd` + 2. Windows , execute `cmd startup.cmd -m standalone` 3. Execute the following command to add a configuration to Nacos Server. From 3e5d5a98e1d9bfe1c54d87a9a917db9abcda9033 Mon Sep 17 00:00:00 2001 From: roger Date: Thu, 8 Oct 2020 19:31:22 +0800 Subject: [PATCH 02/99] explicitly add nacos service discovery option, handle divide zero error case --- .../cloud/examples/ProviderApplication.java | 156 +++++++++--------- .../src/main/resources/application.properties | 21 +-- 2 files changed, 91 insertions(+), 86 deletions(-) mode change 100644 => 100755 spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java index 94a842598..0325055c2 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java @@ -1,76 +1,80 @@ -/* - * 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.examples; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author xiaojing - */ -@EnableDiscoveryClient -@SpringBootApplication -public class ProviderApplication { - - public static void main(String[] args) { - SpringApplication.run(ProviderApplication.class, args); - } - - @RestController - class EchoController { - - @GetMapping("/") - public ResponseEntity index() { - return new ResponseEntity("index error", HttpStatus.INTERNAL_SERVER_ERROR); - } - - @GetMapping("/test") - public ResponseEntity test() { - return new ResponseEntity("error", HttpStatus.INTERNAL_SERVER_ERROR); - } - - @GetMapping("/sleep") - public String sleep() { - try { - Thread.sleep(1000L); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - return "ok"; - } - - @GetMapping("/echo/{string}") - public String echo(@PathVariable String string) { - return "hello Nacos Discovery " + string; - } - - @GetMapping("/divide") - public String divide(@RequestParam Integer a, @RequestParam Integer b) { - return String.valueOf(a / b); - } - - } - -} +/* + * 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.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author xiaojing + */ +@EnableDiscoveryClient +@SpringBootApplication +public class ProviderApplication { + + public static void main(String[] args) { + SpringApplication.run(ProviderApplication.class, args); + } + + @RestController + class EchoController { + + @GetMapping("/") + public ResponseEntity index() { + return new ResponseEntity("index error", HttpStatus.INTERNAL_SERVER_ERROR); + } + + @GetMapping("/test") + public ResponseEntity test() { + return new ResponseEntity("error", HttpStatus.INTERNAL_SERVER_ERROR); + } + + @GetMapping("/sleep") + public String sleep() { + try { + Thread.sleep(1000L); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + return "ok"; + } + + @GetMapping("/echo/{string}") + public String echo(@PathVariable String string) { + return "hello Nacos Discovery " + string; + } + + @GetMapping("/divide") + public String divide(@RequestParam Integer a, @RequestParam Integer b) { + if(b == 0) { + return String.valueOf(0); + } else { + return String.valueOf(a / b); + } + } + + } + +} diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties old mode 100644 new mode 100755 index 16c0acc9d..e967cd12f --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties @@ -1,10 +1,11 @@ -server.port=18082 -spring.application.name=service-provider -spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 -#spring.cloud.nacos.discovery.instance-enabled=true - -spring.cloud.nacos.username=nacos -spring.cloud.nacos.password=nacos - -management.endpoints.web.exposure.include=* -management.endpoint.health.show-details=always +server.port=18082 +spring.application.name=service-provider +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 +spring.cloud.nacos.discovery.enabled=true +#spring.cloud.nacos.discovery.instance-enabled=true + +spring.cloud.nacos.username=nacos +spring.cloud.nacos.password=nacos + +management.endpoints.web.exposure.include=* +management.endpoint.health.show-details=always From 770382b36afd5180f4c77b02830683f4283bd659 Mon Sep 17 00:00:00 2001 From: wangmin Date: Tue, 8 Dec 2020 20:04:19 +0800 Subject: [PATCH 03/99] Fix ConcurrentModificationException while EventDispatcher.run after 'received push data' from Nacos --- .../metadata/repository/DubboServiceMetadataRepository.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java index a5be34df8..81751a618 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -237,9 +237,6 @@ public class DubboServiceMetadataRepository dispatchEvent(new SubscribedServicesChangedEvent(this, oldSubscribedServices, newSubscribedServices)); - // clear old one, help GC - oldSubscribedServices.clear(); - return newSubscribedServices.stream(); } From 1ecf526b5cfb85b06d181281bd76623cc6f37a34 Mon Sep 17 00:00:00 2001 From: yangying <2505594512@qq.com> Date: Tue, 15 Dec 2020 15:18:06 +0800 Subject: [PATCH 04/99] =?UTF-8?q?sentinel=E7=A4=BA=E4=BE=8B=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0sentinel=E9=85=8D=E7=BD=AE=EF=BC=8C=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0sentinel=E7=A4=BA=E4=BE=8B=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E8=BF=90=E8=A1=8C=E8=AF=B4=E6=98=8E=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sentinel-example/sentinel-feign-example/readme-zh.md | 4 ++++ .../src/main/resources/application.yml | 3 +++ 2 files changed, 7 insertions(+) diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/readme-zh.md index 542d9ef78..06bc694e7 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/readme-zh.md @@ -114,6 +114,8 @@ public class EchoController { - 启动nacos 注册中心 +- 启动sentinel + - 启动服务提供方: 1. IDE直接启动:找到主类 `ProviderApplication`,执行 main 方法启动应用。 @@ -123,3 +125,5 @@ public class EchoController { 1. IDE直接启动:找到主类 `ConsumerApplication`,执行 main 方法启动应用。 2. 打包编译后启动:首先执行 `mvn clean package` 将工程编译打包,然后执行 `java -jar sentinel-feign-consumer-example.jar`启动应用。 + +- 启动之后,Sentinel Dashboard可能看不见service-consumer服务的详细信息,多请求几次接口即可。 diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/resources/application.yml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/resources/application.yml index 219c38d02..c981dca1e 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/resources/application.yml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/sentinel-feign-consumer-example/src/main/resources/application.yml @@ -8,6 +8,9 @@ spring: nacos: discovery: server-addr: 127.0.0.1:8848 + sentinel: + transport: + dashboard: 127.0.0.1:8081 feign: sentinel: From 441bcb9124098f781e9c24535945f1e0c4d7b6fb Mon Sep 17 00:00:00 2001 From: "mai.jh" Date: Tue, 19 Jan 2021 15:45:45 +0800 Subject: [PATCH 05/99] for: #1931 ,Add a reset Nacos Log Config listener. --- .../nacos/logging/NacosLoggingListener.java | 54 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 4 +- .../logging/NacosLoggingListener.java | 54 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 2 + 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/logging/NacosLoggingListener.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/logging/NacosLoggingListener.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/logging/NacosLoggingListener.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/logging/NacosLoggingListener.java new file mode 100644 index 000000000..41d5842ec --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/logging/NacosLoggingListener.java @@ -0,0 +1,54 @@ +/* + * 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.logging; + +import com.alibaba.nacos.client.logging.NacosLogging; + +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.event.GenericApplicationListener; +import org.springframework.core.Ordered; +import org.springframework.core.ResolvableType; + +/** + * Reload nacos log configuration file, after + * {@link org.springframework.boot.context.logging.LoggingApplicationListener}. + * + * @author mai.jh + */ +public class NacosLoggingListener implements GenericApplicationListener { + + @Override + public boolean supportsEventType(ResolvableType resolvableType) { + Class type = resolvableType.getRawClass(); + if (type != null) { + return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(type); + } + return false; + } + + @Override + public void onApplicationEvent(ApplicationEvent applicationEvent) { + NacosLogging.getInstance().loadConfiguration(); + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE + 21; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories index aa6bf0d92..a7ee06a44 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/spring.factories @@ -7,4 +7,6 @@ org.springframework.boot.diagnostics.FailureAnalyzer=\ com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer org.springframework.boot.env.PropertySourceLoader=\ com.alibaba.cloud.nacos.parser.NacosJsonPropertySourceLoader,\ -com.alibaba.cloud.nacos.parser.NacosXmlPropertySourceLoader \ No newline at end of file +com.alibaba.cloud.nacos.parser.NacosXmlPropertySourceLoader +org.springframework.context.ApplicationListener=\ +com.alibaba.cloud.nacos.logging.NacosLoggingListener \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/logging/NacosLoggingListener.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/logging/NacosLoggingListener.java new file mode 100644 index 000000000..91822ace6 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/logging/NacosLoggingListener.java @@ -0,0 +1,54 @@ +/* + * 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.discovery.logging; + +import com.alibaba.nacos.client.logging.NacosLogging; + +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.event.GenericApplicationListener; +import org.springframework.core.Ordered; +import org.springframework.core.ResolvableType; + +/** + * Reload nacos log configuration file, after + * {@link org.springframework.boot.context.logging.LoggingApplicationListener}. + * + * @author mai.jh + */ +public class NacosLoggingListener implements GenericApplicationListener { + + @Override + public boolean supportsEventType(ResolvableType resolvableType) { + Class type = resolvableType.getRawClass(); + if (type != null) { + return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(type); + } + return false; + } + + @Override + public void onApplicationEvent(ApplicationEvent applicationEvent) { + NacosLogging.getInstance().loadConfiguration(); + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE + 21; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories index 80befe757..dad08529a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories @@ -9,3 +9,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.cloud.nacos.NacosServiceAutoConfiguration org.springframework.cloud.bootstrap.BootstrapConfiguration=\ com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration +org.springframework.context.ApplicationListener=\ + com.alibaba.cloud.nacos.discovery.logging.NacosLoggingListener From cbd64061cecc394a9467a7c98b4dd52c1f4c2061 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 1 Feb 2021 11:23:10 +0800 Subject: [PATCH 06/99] Code refactoring and some new feature support --- pom.xml | 15 +- .../pom.xml | 7 +- .../binder/rocketmq/RocketMQBinderUtils.java | 89 -- .../RocketMQMessageChannelBinder.java | 295 ++---- .../RocketMQBinderHealthIndicator.java | 10 +- .../RocketMQListenerBindingContainer.java | 935 +++++++++--------- .../RocketMQInboundChannelAdapter.java | 176 ---- .../integration/RocketMQMessageHandler.java | 302 ------ .../integration/RocketMQMessageSource.java | 382 ------- .../rocketmq/metrics/Instrumentation.java | 21 + .../metrics/InstrumentationManager.java | 35 +- ...RocketMQBinderConfigurationProperties.java | 81 +- .../properties/RocketMQBindingProperties.java | 49 - .../RocketMQConsumerProperties.java | 429 ++++++-- .../RocketMQExtendedBindingProperties.java | 12 +- .../RocketMQProducerProperties.java | 201 ++-- .../PartitionMessageQueueSelector.java | 2 +- 17 files changed, 1111 insertions(+), 1930 deletions(-) delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageSource.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBindingProperties.java diff --git a/pom.xml b/pom.xml index 7f9f0f88b..3fd389aca 100644 --- a/pom.xml +++ b/pom.xml @@ -98,6 +98,7 @@ 4.0.1 + 4.6.1 2.0.2 @@ -258,10 +259,20 @@ + + + + + org.apache.rocketmq - rocketmq-spring-boot-starter - ${rocketmq.starter.version} + rocketmq-client + ${rocketmq.version} + + + org.apache.rocketmq + rocketmq-acl + ${rocketmq.version} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml index ec44c9d7a..ca5c22391 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml @@ -50,9 +50,12 @@ org.apache.rocketmq - rocketmq-spring-boot-starter + rocketmq-client + + + org.apache.rocketmq + rocketmq-acl - org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java deleted file mode 100644 index c7daff0ef..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java +++ /dev/null @@ -1,89 +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.stream.binder.rocketmq; - -import java.util.Arrays; -import java.util.List; - -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; -import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties; - -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -/** - * @author Jim - */ -public final class RocketMQBinderUtils { - - private RocketMQBinderUtils() { - - } - - public static RocketMQBinderConfigurationProperties mergeProperties( - RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties, - RocketMQProperties rocketMQProperties) { - RocketMQBinderConfigurationProperties result = new RocketMQBinderConfigurationProperties(); - if (StringUtils.isEmpty(rocketMQProperties.getNameServer())) { - result.setNameServer(rocketBinderConfigurationProperties.getNameServer()); - } - else { - result.setNameServer( - Arrays.asList(rocketMQProperties.getNameServer().split(";"))); - } - if (rocketMQProperties.getProducer() == null - || StringUtils.isEmpty(rocketMQProperties.getProducer().getAccessKey())) { - result.setAccessKey(rocketBinderConfigurationProperties.getAccessKey()); - } - else { - result.setAccessKey(rocketMQProperties.getProducer().getAccessKey()); - } - if (rocketMQProperties.getProducer() == null - || StringUtils.isEmpty(rocketMQProperties.getProducer().getSecretKey())) { - result.setSecretKey(rocketBinderConfigurationProperties.getSecretKey()); - } - else { - result.setSecretKey(rocketMQProperties.getProducer().getSecretKey()); - } - if (rocketMQProperties.getProducer() == null || StringUtils - .isEmpty(rocketMQProperties.getProducer().getCustomizedTraceTopic())) { - result.setCustomizedTraceTopic( - rocketBinderConfigurationProperties.getCustomizedTraceTopic()); - } - else { - result.setCustomizedTraceTopic( - rocketMQProperties.getProducer().getCustomizedTraceTopic()); - } - if (rocketMQProperties.getProducer() != null - && rocketMQProperties.getProducer().isEnableMsgTrace()) { - result.setEnableMsgTrace(Boolean.TRUE); - } - else { - result.setEnableMsgTrace( - rocketBinderConfigurationProperties.isEnableMsgTrace()); - } - return result; - } - - public static String getNameServerStr(List nameServerList) { - if (CollectionUtils.isEmpty(nameServerList)) { - return null; - } - return String.join(";", nameServerList); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java index e5a2e24b1..5683bff68 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java @@ -1,11 +1,11 @@ /* - * Copyright 2013-2018 the original author or authors. + * Copyright (C) 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,34 +16,18 @@ package com.alibaba.cloud.stream.binder.rocketmq; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.alibaba.cloud.stream.binder.rocketmq.consuming.RocketMQListenerBindingContainer; -import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQInboundChannelAdapter; -import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQMessageHandler; -import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQMessageSource; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; +import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache; +import com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler; +import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQInboundChannelAdapter; +import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull.DefaultErrorAcknowledgeHandler; +import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull.RocketMQMessageSource; +import com.alibaba.cloud.stream.binder.rocketmq.integration.outbound.RocketMQProducerMessageHandler; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties; import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner; -import com.alibaba.cloud.stream.binder.rocketmq.provisioning.selector.PartitionMessageQueueSelector; -import com.alibaba.cloud.stream.binder.rocketmq.support.JacksonRocketMQHeaderMapper; -import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.rocketmq.acl.common.AclClientRPCHook; -import org.apache.rocketmq.acl.common.SessionCredentials; -import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.common.UtilAll; -import org.apache.rocketmq.remoting.RPCHook; -import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties; -import org.apache.rocketmq.spring.core.RocketMQTemplate; -import org.apache.rocketmq.spring.support.RocketMQUtil; +import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils; import org.springframework.cloud.stream.binder.AbstractMessageChannelBinder; import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; @@ -55,15 +39,19 @@ import org.springframework.cloud.stream.provisioning.ConsumerDestination; import org.springframework.cloud.stream.provisioning.ProducerDestination; import org.springframework.integration.StaticMessageHeaderAccessor; import org.springframework.integration.acks.AcknowledgmentCallback; -import org.springframework.integration.acks.AcknowledgmentCallback.Status; import org.springframework.integration.channel.AbstractMessageChannel; import org.springframework.integration.core.MessageProducer; +import org.springframework.integration.support.DefaultErrorMessageStrategy; +import org.springframework.integration.support.ErrorMessageStrategy; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; import org.springframework.util.StringUtils; /** + * A {@link org.springframework.cloud.stream.binder.Binder} that uses RocketMQ as the + * underlying middleware. + * * @author Jim */ public class RocketMQMessageChannelBinder extends @@ -71,120 +59,44 @@ public class RocketMQMessageChannelBinder extends implements ExtendedPropertiesBinder { - private RocketMQExtendedBindingProperties extendedBindingProperties = new RocketMQExtendedBindingProperties(); - - private final RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties; - - private final RocketMQProperties rocketMQProperties; - - private final InstrumentationManager instrumentationManager; - - private Map topicInUse = new HashMap<>(); + private final RocketMQExtendedBindingProperties extendedBindingProperties; + private final RocketMQBinderConfigurationProperties binderConfigurationProperties; - public RocketMQMessageChannelBinder(RocketMQTopicProvisioner provisioningProvider, + public RocketMQMessageChannelBinder( + RocketMQBinderConfigurationProperties binderConfigurationProperties, RocketMQExtendedBindingProperties extendedBindingProperties, - RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties, - RocketMQProperties rocketMQProperties, - InstrumentationManager instrumentationManager) { - super(null, provisioningProvider); + RocketMQTopicProvisioner provisioningProvider) { + super(new String[0], provisioningProvider); this.extendedBindingProperties = extendedBindingProperties; - this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties; - this.rocketMQProperties = rocketMQProperties; - this.instrumentationManager = instrumentationManager; + this.binderConfigurationProperties = binderConfigurationProperties; } @Override protected MessageHandler createProducerMessageHandler(ProducerDestination destination, - ExtendedProducerProperties producerProperties, + ExtendedProducerProperties extendedProducerProperties, MessageChannel channel, MessageChannel errorChannel) throws Exception { - if (producerProperties.getExtension().getEnabled()) { - - // if producerGroup is empty, using destination - String extendedProducerGroup = producerProperties.getExtension().getGroup(); - String producerGroup = StringUtils.isEmpty(extendedProducerGroup) - ? destination.getName() : extendedProducerGroup; - - RocketMQBinderConfigurationProperties mergedProperties = RocketMQBinderUtils - .mergeProperties(rocketBinderConfigurationProperties, - rocketMQProperties); - - RocketMQTemplate rocketMQTemplate; - if (producerProperties.getExtension().getTransactional()) { - Map rocketMQTemplates = getBeanFactory() - .getBeansOfType(RocketMQTemplate.class); - if (rocketMQTemplates.size() == 0) { - throw new IllegalStateException( - "there is no RocketMQTemplate in Spring BeanFactory"); - } - else if (rocketMQTemplates.size() > 1) { - throw new IllegalStateException( - "there is more than 1 RocketMQTemplates in Spring BeanFactory"); - } - rocketMQTemplate = rocketMQTemplates.values().iterator().next(); - } - else { - rocketMQTemplate = new RocketMQTemplate(); - rocketMQTemplate.setObjectMapper(this.getApplicationContext() - .getBeansOfType(ObjectMapper.class).values().iterator().next()); - DefaultMQProducer producer; - String ak = mergedProperties.getAccessKey(); - String sk = mergedProperties.getSecretKey(); - if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { - RPCHook rpcHook = new AclClientRPCHook( - new SessionCredentials(ak, sk)); - producer = new DefaultMQProducer(producerGroup, rpcHook, - mergedProperties.isEnableMsgTrace(), - mergedProperties.getCustomizedTraceTopic()); - producer.setVipChannelEnabled(false); - producer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, - destination.getName() + "|" + UtilAll.getPid())); - } - else { - producer = new DefaultMQProducer(producerGroup); - producer.setVipChannelEnabled( - producerProperties.getExtension().getVipChannelEnabled()); - } - producer.setNamesrvAddr(RocketMQBinderUtils - .getNameServerStr(mergedProperties.getNameServer())); - producer.setSendMsgTimeout( - producerProperties.getExtension().getSendMessageTimeout()); - producer.setRetryTimesWhenSendFailed( - producerProperties.getExtension().getRetryTimesWhenSendFailed()); - producer.setRetryTimesWhenSendAsyncFailed(producerProperties - .getExtension().getRetryTimesWhenSendAsyncFailed()); - producer.setCompressMsgBodyOverHowmuch(producerProperties.getExtension() - .getCompressMessageBodyThreshold()); - producer.setRetryAnotherBrokerWhenNotStoreOK( - producerProperties.getExtension().isRetryNextServer()); - producer.setMaxMessageSize( - producerProperties.getExtension().getMaxMessageSize()); - rocketMQTemplate.setProducer(producer); - if (producerProperties.isPartitioned()) { - rocketMQTemplate - .setMessageQueueSelector(new PartitionMessageQueueSelector()); - } - } - - RocketMQMessageHandler messageHandler = new RocketMQMessageHandler( - rocketMQTemplate, destination.getName(), producerGroup, - producerProperties.getExtension().getTransactional(), - instrumentationManager, producerProperties, - ((AbstractMessageChannel) channel).getInterceptors().stream().filter( - channelInterceptor -> channelInterceptor instanceof MessageConverterConfigurer.PartitioningInterceptor) - .map(channelInterceptor -> ((MessageConverterConfigurer.PartitioningInterceptor) channelInterceptor)) - .findFirst().orElse(null)); - messageHandler.setBeanFactory(this.getApplicationContext().getBeanFactory()); - messageHandler.setSync(producerProperties.getExtension().getSync()); - messageHandler.setHeaderMapper(createHeaderMapper(producerProperties)); - if (errorChannel != null) { - messageHandler.setSendFailureChannel(errorChannel); - } - return messageHandler; - } - else { + if (!extendedProducerProperties.getExtension().getEnabled()) { throw new RuntimeException("Binding for channel " + destination.getName() + " has been disabled, message can't be delivered"); } + RocketMQProducerProperties mqProducerProperties = RocketMQUtils + .mergeRocketMQProperties(binderConfigurationProperties, + extendedProducerProperties.getExtension()); + RocketMQProducerMessageHandler messageHandler = new RocketMQProducerMessageHandler( + destination, extendedProducerProperties, mqProducerProperties); + messageHandler.setApplicationContext(this.getApplicationContext()); + if (errorChannel != null) { + messageHandler.setSendFailureChannel(errorChannel); + } + MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor = ((AbstractMessageChannel) channel) + .getInterceptors().stream() + .filter(channelInterceptor -> channelInterceptor instanceof MessageConverterConfigurer.PartitioningInterceptor) + .map(channelInterceptor -> ((MessageConverterConfigurer.PartitioningInterceptor) channelInterceptor)) + .findFirst().orElse(null); + messageHandler.setPartitioningInterceptor(partitioningInterceptor); + messageHandler.setBeanFactory(this.getApplicationContext().getBeanFactory()); + messageHandler.setErrorMessageStrategy(this.getErrorMessageStrategy()); + return messageHandler; } @Override @@ -198,56 +110,43 @@ public class RocketMQMessageChannelBinder extends @Override protected MessageProducer createConsumerEndpoint(ConsumerDestination destination, String group, - ExtendedConsumerProperties consumerProperties) + ExtendedConsumerProperties extendedConsumerProperties) throws Exception { - if (group == null || "".equals(group)) { + // todo support anymous consumer + if (StringUtils.isEmpty(group)) { throw new RuntimeException( "'group must be configured for channel " + destination.getName()); } + RocketMQUtils.mergeRocketMQProperties(binderConfigurationProperties, + extendedConsumerProperties.getExtension()); + extendedConsumerProperties.getExtension().setGroup(group); - RocketMQListenerBindingContainer listenerContainer = new RocketMQListenerBindingContainer( - consumerProperties, rocketBinderConfigurationProperties, this); - listenerContainer.setConsumerGroup(group); - listenerContainer.setTopic(destination.getName()); - listenerContainer.setConsumeThreadMax(consumerProperties.getConcurrency()); - listenerContainer.setSuspendCurrentQueueTimeMillis( - consumerProperties.getExtension().getSuspendCurrentQueueTimeMillis()); - listenerContainer.setDelayLevelWhenNextConsume( - consumerProperties.getExtension().getDelayLevelWhenNextConsume()); - listenerContainer - .setNameServer(rocketBinderConfigurationProperties.getNameServer()); - listenerContainer.setHeaderMapper(createHeaderMapper(consumerProperties)); - - RocketMQInboundChannelAdapter rocketInboundChannelAdapter = new RocketMQInboundChannelAdapter( - listenerContainer, consumerProperties, instrumentationManager); - - topicInUse.put(destination.getName(), group); - + RocketMQInboundChannelAdapter inboundChannelAdapter = new RocketMQInboundChannelAdapter( + destination.getName(), extendedConsumerProperties); ErrorInfrastructure errorInfrastructure = registerErrorInfrastructure(destination, - group, consumerProperties); - if (consumerProperties.getMaxAttempts() > 1) { - rocketInboundChannelAdapter - .setRetryTemplate(buildRetryTemplate(consumerProperties)); - rocketInboundChannelAdapter - .setRecoveryCallback(errorInfrastructure.getRecoverer()); + group, extendedConsumerProperties); + if (extendedConsumerProperties.getMaxAttempts() > 1) { + inboundChannelAdapter + .setRetryTemplate(buildRetryTemplate(extendedConsumerProperties)); + inboundChannelAdapter.setRecoveryCallback(errorInfrastructure.getRecoverer()); } else { - rocketInboundChannelAdapter - .setErrorChannel(errorInfrastructure.getErrorChannel()); + inboundChannelAdapter.setErrorChannel(errorInfrastructure.getErrorChannel()); } - - return rocketInboundChannelAdapter; + return inboundChannelAdapter; } @Override protected PolledConsumerResources createPolledConsumerResources(String name, String group, ConsumerDestination destination, - ExtendedConsumerProperties consumerProperties) { - RocketMQMessageSource rocketMQMessageSource = new RocketMQMessageSource( - rocketBinderConfigurationProperties, consumerProperties, name, group); - return new PolledConsumerResources(rocketMQMessageSource, - registerErrorInfrastructure(destination, group, consumerProperties, - true)); + ExtendedConsumerProperties extendedConsumerProperties) { + RocketMQUtils.mergeRocketMQProperties(binderConfigurationProperties, + extendedConsumerProperties.getExtension()); + extendedConsumerProperties.getExtension().setGroup(group); + RocketMQMessageSource messageSource = new RocketMQMessageSource(name, + extendedConsumerProperties); + return new PolledConsumerResources(messageSource, registerErrorInfrastructure( + destination, group, extendedConsumerProperties, true)); } @Override @@ -261,67 +160,47 @@ public class RocketMQMessageChannelBinder extends ((MessagingException) message.getPayload()) .getFailedMessage()); if (ack != null) { - if (properties.getExtension().shouldRequeue()) { - ack.acknowledge(Status.REQUEUE); - } - else { - ack.acknowledge(Status.REJECT); - } + ErrorAcknowledgeHandler handler = RocketMQBeanContainerCache.getBean( + properties.getExtension().getPull().getErrAcknowledge(), + ErrorAcknowledgeHandler.class, + new DefaultErrorAcknowledgeHandler()); + ack.acknowledge( + handler.handler(((MessagingException) message.getPayload()) + .getFailedMessage())); } } }; } + /** + * Binders can return an {@link ErrorMessageStrategy} for building error messages; + * binder implementations typically might add extra headers to the error message. + * + * @return the implementation - may be null. + */ @Override - public RocketMQConsumerProperties getExtendedConsumerProperties(String channelName) { - return extendedBindingProperties.getExtendedConsumerProperties(channelName); + protected ErrorMessageStrategy getErrorMessageStrategy() { + // It can be extended to custom if necessary. + return new DefaultErrorMessageStrategy(); } @Override - public RocketMQProducerProperties getExtendedProducerProperties(String channelName) { - return extendedBindingProperties.getExtendedProducerProperties(channelName); + public RocketMQConsumerProperties getExtendedConsumerProperties(String channelName) { + return this.extendedBindingProperties.getExtendedConsumerProperties(channelName); } - public Map getTopicInUse() { - return topicInUse; + @Override + public RocketMQProducerProperties getExtendedProducerProperties(String channelName) { + return this.extendedBindingProperties.getExtendedProducerProperties(channelName); } @Override public String getDefaultsPrefix() { - return extendedBindingProperties.getDefaultsPrefix(); + return this.extendedBindingProperties.getDefaultsPrefix(); } @Override public Class getExtendedPropertiesEntryClass() { - return extendedBindingProperties.getExtendedPropertiesEntryClass(); + return this.extendedBindingProperties.getExtendedPropertiesEntryClass(); } - - public void setExtendedBindingProperties( - RocketMQExtendedBindingProperties extendedBindingProperties) { - this.extendedBindingProperties = extendedBindingProperties; - } - - private RocketMQHeaderMapper createHeaderMapper( - final ExtendedConsumerProperties extendedConsumerProperties) { - Set trustedPackages = extendedConsumerProperties.getExtension() - .getTrustedPackages(); - return createHeaderMapper(trustedPackages); - } - - private RocketMQHeaderMapper createHeaderMapper( - final ExtendedProducerProperties producerProperties) { - return createHeaderMapper(Collections.emptyList()); - } - - private RocketMQHeaderMapper createHeaderMapper(Collection trustedPackages) { - ObjectMapper objectMapper = this.getApplicationContext() - .getBeansOfType(ObjectMapper.class).values().iterator().next(); - JacksonRocketMQHeaderMapper headerMapper = new JacksonRocketMQHeaderMapper( - objectMapper); - if (!StringUtils.isEmpty(trustedPackages)) { - headerMapper.addTrustedPackages(trustedPackages); - } - return headerMapper; - } - } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java index 1c49359ea..6e704250a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java @@ -19,7 +19,6 @@ package com.alibaba.cloud.stream.binder.rocketmq.actuator; import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.Health; @@ -29,23 +28,20 @@ import org.springframework.boot.actuate.health.Health; */ public class RocketMQBinderHealthIndicator extends AbstractHealthIndicator { - @Autowired - private InstrumentationManager instrumentationManager; - @Override protected void doHealthCheck(Health.Builder builder) throws Exception { - if (instrumentationManager.getHealthInstrumentations().stream() + if (InstrumentationManager.getHealthInstrumentations().stream() .allMatch(Instrumentation::isUp)) { builder.up(); return; } - if (instrumentationManager.getHealthInstrumentations().stream() + if (InstrumentationManager.getHealthInstrumentations().stream() .allMatch(Instrumentation::isOutOfService)) { builder.outOfService(); return; } builder.down(); - instrumentationManager.getHealthInstrumentations().stream() + InstrumentationManager.getHealthInstrumentations().stream() .filter(instrumentation -> !instrumentation.isStarted()) .forEach(instrumentation1 -> builder .withException(instrumentation1.getStartException())); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java index fb167c697..7bd875f33 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java @@ -1,465 +1,470 @@ -/* - * 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.stream.binder.rocketmq.consuming; - -import java.util.List; -import java.util.Objects; - -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderUtils; -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; -import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; -import org.apache.rocketmq.acl.common.AclClientRPCHook; -import org.apache.rocketmq.acl.common.SessionCredentials; -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; -import org.apache.rocketmq.client.consumer.MessageSelector; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; -import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; -import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; -import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.common.UtilAll; -import org.apache.rocketmq.common.message.MessageExt; -import org.apache.rocketmq.remoting.RPCHook; -import org.apache.rocketmq.spring.annotation.ConsumeMode; -import org.apache.rocketmq.spring.annotation.MessageModel; -import org.apache.rocketmq.spring.annotation.SelectorType; -import org.apache.rocketmq.spring.core.RocketMQListener; -import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener; -import org.apache.rocketmq.spring.support.RocketMQListenerContainer; -import org.apache.rocketmq.spring.support.RocketMQUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; -import org.springframework.context.SmartLifecycle; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -import static com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants.ROCKETMQ_RECONSUME_TIMES; - -/** - * A class that Listen on rocketmq message. - *

- * this class will delegate {@link RocketMQListener} to handle message - * - * @author Jim - * @author Xiejiashuai - * @see RocketMQListener - */ -public class RocketMQListenerBindingContainer - implements InitializingBean, RocketMQListenerContainer, SmartLifecycle { - - private final static Logger log = LoggerFactory - .getLogger(RocketMQListenerBindingContainer.class); - - private long suspendCurrentQueueTimeMillis = 1000; - - /** - * Message consume retry strategy
- * -1,no retry,put into DLQ directly
- * 0,broker control retry frequency
- * >0,client control retry frequency. - */ - private int delayLevelWhenNextConsume = 0; - - private List nameServer; - - private String consumerGroup; - - private String topic; - - private int consumeThreadMax = 64; - - private String charset = "UTF-8"; - - private RocketMQListener rocketMQListener; - - private RocketMQHeaderMapper headerMapper; - - private DefaultMQPushConsumer consumer; - - private boolean running; - - private final ExtendedConsumerProperties rocketMQConsumerProperties; - - private final RocketMQMessageChannelBinder rocketMQMessageChannelBinder; - - private final RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties; - - // The following properties came from RocketMQConsumerProperties. - private ConsumeMode consumeMode; - - private SelectorType selectorType; - - private String selectorExpression; - - private MessageModel messageModel; - - public RocketMQListenerBindingContainer( - ExtendedConsumerProperties rocketMQConsumerProperties, - RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties, - RocketMQMessageChannelBinder rocketMQMessageChannelBinder) { - this.rocketMQConsumerProperties = rocketMQConsumerProperties; - this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties; - this.rocketMQMessageChannelBinder = rocketMQMessageChannelBinder; - this.consumeMode = rocketMQConsumerProperties.getExtension().getOrderly() - ? ConsumeMode.ORDERLY : ConsumeMode.CONCURRENTLY; - if (StringUtils.isEmpty(rocketMQConsumerProperties.getExtension().getSql())) { - this.selectorType = SelectorType.TAG; - this.selectorExpression = rocketMQConsumerProperties.getExtension().getTags(); - } - else { - this.selectorType = SelectorType.SQL92; - this.selectorExpression = rocketMQConsumerProperties.getExtension().getSql(); - } - this.messageModel = rocketMQConsumerProperties.getExtension().getBroadcasting() - ? MessageModel.BROADCASTING : MessageModel.CLUSTERING; - } - - @Override - public void setupMessageListener(RocketMQListener rocketMQListener) { - this.rocketMQListener = rocketMQListener; - } - - @Override - public void destroy() throws Exception { - this.setRunning(false); - if (Objects.nonNull(consumer)) { - consumer.shutdown(); - } - log.info("container destroyed, {}", this.toString()); - } - - @Override - public void afterPropertiesSet() throws Exception { - initRocketMQPushConsumer(); - } - - @Override - public boolean isAutoStartup() { - return true; - } - - @Override - public void stop(Runnable callback) { - stop(); - callback.run(); - } - - @Override - public void start() { - if (this.isRunning()) { - throw new IllegalStateException( - "container already running. " + this.toString()); - } - - try { - consumer.start(); - } - catch (MQClientException e) { - throw new IllegalStateException("Failed to start RocketMQ push consumer", e); - } - this.setRunning(true); - - log.info("running container: {}", this.toString()); - } - - @Override - public void stop() { - if (this.isRunning()) { - if (Objects.nonNull(consumer)) { - consumer.shutdown(); - } - setRunning(false); - } - } - - @Override - public boolean isRunning() { - return running; - } - - private void setRunning(boolean running) { - this.running = running; - } - - @Override - public int getPhase() { - return Integer.MAX_VALUE; - } - - private void initRocketMQPushConsumer() throws MQClientException { - Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); - Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); - Assert.notNull(nameServer, "Property 'nameServer' is required"); - Assert.notNull(topic, "Property 'topic' is required"); - - String ak = rocketBinderConfigurationProperties.getAccessKey(); - String sk = rocketBinderConfigurationProperties.getSecretKey(); - if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { - RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk)); - consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook, - new AllocateMessageQueueAveragely(), - rocketBinderConfigurationProperties.isEnableMsgTrace(), - rocketBinderConfigurationProperties.getCustomizedTraceTopic()); - consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, - topic + "|" + UtilAll.getPid())); - consumer.setVipChannelEnabled(false); - } - else { - consumer = new DefaultMQPushConsumer(consumerGroup, - rocketBinderConfigurationProperties.isEnableMsgTrace(), - rocketBinderConfigurationProperties.getCustomizedTraceTopic()); - } - - consumer.setNamesrvAddr(RocketMQBinderUtils.getNameServerStr(nameServer)); - consumer.setConsumeThreadMax(rocketMQConsumerProperties.getConcurrency()); - consumer.setConsumeThreadMin(rocketMQConsumerProperties.getConcurrency()); - - switch (messageModel) { - case BROADCASTING: - consumer.setMessageModel( - org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING); - break; - case CLUSTERING: - consumer.setMessageModel( - org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING); - break; - default: - throw new IllegalArgumentException("Property 'messageModel' was wrong."); - } - - switch (selectorType) { - case TAG: - consumer.subscribe(topic, selectorExpression); - break; - case SQL92: - consumer.subscribe(topic, MessageSelector.bySql(selectorExpression)); - break; - default: - throw new IllegalArgumentException("Property 'selectorType' was wrong."); - } - - switch (consumeMode) { - case ORDERLY: - consumer.setMessageListener(new DefaultMessageListenerOrderly()); - break; - case CONCURRENTLY: - consumer.setMessageListener(new DefaultMessageListenerConcurrently()); - break; - default: - throw new IllegalArgumentException("Property 'consumeMode' was wrong."); - } - - if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { - ((RocketMQPushConsumerLifecycleListener) rocketMQListener) - .prepareStart(consumer); - } - - } - - @Override - public String toString() { - return "RocketMQListenerBindingContainer{" + "consumerGroup='" + consumerGroup - + '\'' + ", nameServer='" + nameServer + '\'' + ", topic='" + topic + '\'' - + ", consumeMode=" + consumeMode + ", selectorType=" + selectorType - + ", selectorExpression='" + selectorExpression + '\'' + ", messageModel=" - + messageModel + '}'; - } - - public long getSuspendCurrentQueueTimeMillis() { - return suspendCurrentQueueTimeMillis; - } - - public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) { - this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis; - } - - public int getDelayLevelWhenNextConsume() { - return delayLevelWhenNextConsume; - } - - public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) { - this.delayLevelWhenNextConsume = delayLevelWhenNextConsume; - } - - public List getNameServer() { - return nameServer; - } - - public void setNameServer(List nameServer) { - this.nameServer = nameServer; - } - - public String getConsumerGroup() { - return consumerGroup; - } - - public void setConsumerGroup(String consumerGroup) { - this.consumerGroup = consumerGroup; - } - - public String getTopic() { - return topic; - } - - public void setTopic(String topic) { - this.topic = topic; - } - - public int getConsumeThreadMax() { - return consumeThreadMax; - } - - public void setConsumeThreadMax(int consumeThreadMax) { - this.consumeThreadMax = consumeThreadMax; - } - - public String getCharset() { - return charset; - } - - public void setCharset(String charset) { - this.charset = charset; - } - - public RocketMQListener getRocketMQListener() { - return rocketMQListener; - } - - public void setRocketMQListener(RocketMQListener rocketMQListener) { - this.rocketMQListener = rocketMQListener; - } - - public DefaultMQPushConsumer getConsumer() { - return consumer; - } - - public void setConsumer(DefaultMQPushConsumer consumer) { - this.consumer = consumer; - } - - public ExtendedConsumerProperties getRocketMQConsumerProperties() { - return rocketMQConsumerProperties; - } - - public ConsumeMode getConsumeMode() { - return consumeMode; - } - - public SelectorType getSelectorType() { - return selectorType; - } - - public String getSelectorExpression() { - return selectorExpression; - } - - public MessageModel getMessageModel() { - return messageModel; - } - - public RocketMQHeaderMapper getHeaderMapper() { - return headerMapper; - } - - public void setHeaderMapper(RocketMQHeaderMapper headerMapper) { - this.headerMapper = headerMapper; - } - - /** - * Convert rocketmq {@link MessageExt} to Spring {@link Message}. - * @param messageExt the rocketmq message - * @return the converted Spring {@link Message} - */ - @SuppressWarnings("unchecked") - private Message convertToSpringMessage(MessageExt messageExt) { - - // add reconsume-times header to messageExt - int reconsumeTimes = messageExt.getReconsumeTimes(); - messageExt.putUserProperty(ROCKETMQ_RECONSUME_TIMES, - String.valueOf(reconsumeTimes)); - Message message = RocketMQUtil.convertToSpringMessage(messageExt); - return MessageBuilder.fromMessage(message) - .copyHeaders(headerMapper.toHeaders(messageExt.getProperties())).build(); - } - - public class DefaultMessageListenerConcurrently - implements MessageListenerConcurrently { - - @SuppressWarnings({ "unchecked", "Duplicates" }) - @Override - public ConsumeConcurrentlyStatus consumeMessage(List msgs, - ConsumeConcurrentlyContext context) { - for (MessageExt messageExt : msgs) { - log.debug("received msg: {}", messageExt); - try { - long now = System.currentTimeMillis(); - rocketMQListener.onMessage(convertToSpringMessage(messageExt)); - long costTime = System.currentTimeMillis() - now; - log.debug("consume {} message key:[{}] cost: {} ms", - messageExt.getMsgId(), messageExt.getKeys(), costTime); - } - catch (Exception e) { - log.warn("consume message failed. messageExt:{}", messageExt, e); - context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); - return ConsumeConcurrentlyStatus.RECONSUME_LATER; - } - } - - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - - } - - public class DefaultMessageListenerOrderly implements MessageListenerOrderly { - - @SuppressWarnings({ "unchecked", "Duplicates" }) - @Override - public ConsumeOrderlyStatus consumeMessage(List msgs, - ConsumeOrderlyContext context) { - for (MessageExt messageExt : msgs) { - log.debug("received msg: {}", messageExt); - try { - long now = System.currentTimeMillis(); - rocketMQListener.onMessage(convertToSpringMessage(messageExt)); - long costTime = System.currentTimeMillis() - now; - log.info("consume {} message key:[{}] cost: {} ms", - messageExt.getMsgId(), messageExt.getKeys(), costTime); - } - catch (Exception e) { - log.warn("consume message failed. messageExt:{}", messageExt, e); - context.setSuspendCurrentQueueTimeMillis( - suspendCurrentQueueTimeMillis); - return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; - } - } - - return ConsumeOrderlyStatus.SUCCESS; - } - - } - -} +/// * +// * 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.stream.binder.rocketmq.consuming; +// +// import java.util.List; +// import java.util.Objects; +// +// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderUtils; +// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder; +// import +/// com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; +// import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; +// import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; +// import org.apache.rocketmq.acl.common.AclClientRPCHook; +// import org.apache.rocketmq.acl.common.SessionCredentials; +// import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +// import org.apache.rocketmq.client.consumer.MessageSelector; +// import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +// import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +// import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +// import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +// import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +// import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; +// import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; +// import org.apache.rocketmq.client.exception.MQClientException; +// import org.apache.rocketmq.common.UtilAll; +// import org.apache.rocketmq.common.message.MessageExt; +// import org.apache.rocketmq.remoting.RPCHook; +// import org.apache.rocketmq.spring.annotation.ConsumeMode; +// import org.apache.rocketmq.spring.annotation.MessageModel; +// import org.apache.rocketmq.spring.annotation.SelectorType; +// import org.apache.rocketmq.spring.core.RocketMQListener; +// import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener; +// import org.apache.rocketmq.spring.support.RocketMQListenerContainer; +// import org.apache.rocketmq.spring.support.RocketMQUtil; +// import org.slf4j.Logger; +// import org.slf4j.LoggerFactory; +// +// import org.springframework.beans.factory.InitializingBean; +// import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; +// import org.springframework.context.SmartLifecycle; +// import org.springframework.integration.support.MessageBuilder; +// import org.springframework.messaging.Message; +// import org.springframework.util.Assert; +// import org.springframework.util.StringUtils; +// +// import static +/// com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants.ROCKETMQ_RECONSUME_TIMES; +// +/// ** +// * A class that Listen on rocketmq message. +// *

+// * this class will delegate {@link RocketMQListener} to handle message +// * +// * @author Jim +// * @author Xiejiashuai +// * @see RocketMQListener +// */ +// public class RocketMQListenerBindingContainer +// implements InitializingBean, RocketMQListenerContainer, SmartLifecycle { +// +// private final static Logger log = LoggerFactory +// .getLogger(RocketMQListenerBindingContainer.class); +// +// private long suspendCurrentQueueTimeMillis = 1000; +// +// /** +// * Message consume retry strategy
+// * -1,no retry,put into DLQ directly
+// * 0,broker control retry frequency
+// * >0,client control retry frequency. +// */ +// private int delayLevelWhenNextConsume = 0; +// +// private List nameServer; +// +// private String consumerGroup; +// +// private String topic; +// +// private int consumeThreadMax = 64; +// +// private String charset = "UTF-8"; +// +// private RocketMQListener rocketMQListener; +// +// private RocketMQHeaderMapper headerMapper; +// +// private DefaultMQPushConsumer consumer; +// +// private boolean running; +// +// private final ExtendedConsumerProperties +/// rocketMQConsumerProperties; +// +// private final RocketMQMessageChannelBinder rocketMQMessageChannelBinder; +// +// private final RocketMQBinderConfigurationProperties +/// rocketBinderConfigurationProperties; +// +// // The following properties came from RocketMQConsumerProperties. +// private ConsumeMode consumeMode; +// +// private SelectorType selectorType; +// +// private String selectorExpression; +// +// private MessageModel messageModel; +// +// public RocketMQListenerBindingContainer( +// ExtendedConsumerProperties rocketMQConsumerProperties, +// RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties, +// RocketMQMessageChannelBinder rocketMQMessageChannelBinder) { +// this.rocketMQConsumerProperties = rocketMQConsumerProperties; +// this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties; +// this.rocketMQMessageChannelBinder = rocketMQMessageChannelBinder; +// this.consumeMode = rocketMQConsumerProperties.getExtension().getOrderly() +// ? ConsumeMode.ORDERLY : ConsumeMode.CONCURRENTLY; +// if (StringUtils.isEmpty(rocketMQConsumerProperties.getExtension().getSql())) { +// this.selectorType = SelectorType.TAG; +// this.selectorExpression = rocketMQConsumerProperties.getExtension().getTags(); +// } +// else { +// this.selectorType = SelectorType.SQL92; +// this.selectorExpression = rocketMQConsumerProperties.getExtension().getSql(); +// } +// this.messageModel = rocketMQConsumerProperties.getExtension().getBroadcasting() +// ? MessageModel.BROADCASTING : MessageModel.CLUSTERING; +// } +// +// @Override +// public void setupMessageListener(RocketMQListener rocketMQListener) { +// this.rocketMQListener = rocketMQListener; +// } +// +// @Override +// public void destroy() throws Exception { +// this.setRunning(false); +// if (Objects.nonNull(consumer)) { +// consumer.shutdown(); +// } +// log.info("container destroyed, {}", this.toString()); +// } +// +// @Override +// public void afterPropertiesSet() throws Exception { +// initRocketMQPushConsumer(); +// } +// +// @Override +// public boolean isAutoStartup() { +// return true; +// } +// +// @Override +// public void stop(Runnable callback) { +// stop(); +// callback.run(); +// } +// +// @Override +// public void start() { +// if (this.isRunning()) { +// throw new IllegalStateException( +// "container already running. " + this.toString()); +// } +// +// try { +// consumer.start(); +// } +// catch (MQClientException e) { +// throw new IllegalStateException("Failed to start RocketMQ push consumer", e); +// } +// this.setRunning(true); +// +// log.info("running container: {}", this.toString()); +// } +// +// @Override +// public void stop() { +// if (this.isRunning()) { +// if (Objects.nonNull(consumer)) { +// consumer.shutdown(); +// } +// setRunning(false); +// } +// } +// +// @Override +// public boolean isRunning() { +// return running; +// } +// +// private void setRunning(boolean running) { +// this.running = running; +// } +// +// @Override +// public int getPhase() { +// return Integer.MAX_VALUE; +// } +// +// private void initRocketMQPushConsumer() throws MQClientException { +// Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); +// Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); +// Assert.notNull(nameServer, "Property 'nameServer' is required"); +// Assert.notNull(topic, "Property 'topic' is required"); +// +// String ak = rocketBinderConfigurationProperties.getAccessKey(); +// String sk = rocketBinderConfigurationProperties.getSecretKey(); +// if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { +// RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk)); +// consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook, +// new AllocateMessageQueueAveragely(), +// rocketBinderConfigurationProperties.isEnableMsgTrace(), +// rocketBinderConfigurationProperties.getCustomizedTraceTopic()); +// consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, +// topic + "|" + UtilAll.getPid())); +// consumer.setVipChannelEnabled(false); +// } +// else { +// consumer = new DefaultMQPushConsumer(consumerGroup, +// rocketBinderConfigurationProperties.isEnableMsgTrace(), +// rocketBinderConfigurationProperties.getCustomizedTraceTopic()); +// } +// +// consumer.setNamesrvAddr(RocketMQBinderUtils.getNameServerStr(nameServer)); +// consumer.setConsumeThreadMax(rocketMQConsumerProperties.getConcurrency()); +// consumer.setConsumeThreadMin(rocketMQConsumerProperties.getConcurrency()); +// +// switch (messageModel) { +// case BROADCASTING: +// consumer.setMessageModel( +// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING); +// break; +// case CLUSTERING: +// consumer.setMessageModel( +// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING); +// break; +// default: +// throw new IllegalArgumentException("Property 'messageModel' was wrong."); +// } +// +// switch (selectorType) { +// case TAG: +// consumer.subscribe(topic, selectorExpression); +// break; +// case SQL92: +// consumer.subscribe(topic, MessageSelector.bySql(selectorExpression)); +// break; +// default: +// throw new IllegalArgumentException("Property 'selectorType' was wrong."); +// } +// +// switch (consumeMode) { +// case ORDERLY: +// consumer.setMessageListener(new DefaultMessageListenerOrderly()); +// break; +// case CONCURRENTLY: +// consumer.setMessageListener(new DefaultMessageListenerConcurrently()); +// break; +// default: +// throw new IllegalArgumentException("Property 'consumeMode' was wrong."); +// } +// +// if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { +// ((RocketMQPushConsumerLifecycleListener) rocketMQListener) +// .prepareStart(consumer); +// } +// +// } +// +// @Override +// public String toString() { +// return "RocketMQListenerBindingContainer{" + "consumerGroup='" + consumerGroup +// + '\'' + ", nameServer='" + nameServer + '\'' + ", topic='" + topic + '\'' +// + ", consumeMode=" + consumeMode + ", selectorType=" + selectorType +// + ", selectorExpression='" + selectorExpression + '\'' + ", messageModel=" +// + messageModel + '}'; +// } +// +// public long getSuspendCurrentQueueTimeMillis() { +// return suspendCurrentQueueTimeMillis; +// } +// +// public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) { +// this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis; +// } +// +// public int getDelayLevelWhenNextConsume() { +// return delayLevelWhenNextConsume; +// } +// +// public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) { +// this.delayLevelWhenNextConsume = delayLevelWhenNextConsume; +// } +// +// public List getNameServer() { +// return nameServer; +// } +// +// public void setNameServer(List nameServer) { +// this.nameServer = nameServer; +// } +// +// public String getConsumerGroup() { +// return consumerGroup; +// } +// +// public void setConsumerGroup(String consumerGroup) { +// this.consumerGroup = consumerGroup; +// } +// +// public String getTopic() { +// return topic; +// } +// +// public void setTopic(String topic) { +// this.topic = topic; +// } +// +// public int getConsumeThreadMax() { +// return consumeThreadMax; +// } +// +// public void setConsumeThreadMax(int consumeThreadMax) { +// this.consumeThreadMax = consumeThreadMax; +// } +// +// public String getCharset() { +// return charset; +// } +// +// public void setCharset(String charset) { +// this.charset = charset; +// } +// +// public RocketMQListener getRocketMQListener() { +// return rocketMQListener; +// } +// +// public void setRocketMQListener(RocketMQListener rocketMQListener) { +// this.rocketMQListener = rocketMQListener; +// } +// +// public DefaultMQPushConsumer getConsumer() { +// return consumer; +// } +// +// public void setConsumer(DefaultMQPushConsumer consumer) { +// this.consumer = consumer; +// } +// +// public ExtendedConsumerProperties +/// getRocketMQConsumerProperties() { +// return rocketMQConsumerProperties; +// } +// +// public ConsumeMode getConsumeMode() { +// return consumeMode; +// } +// +// public SelectorType getSelectorType() { +// return selectorType; +// } +// +// public String getSelectorExpression() { +// return selectorExpression; +// } +// +// public MessageModel getMessageModel() { +// return messageModel; +// } +// +// public RocketMQHeaderMapper getHeaderMapper() { +// return headerMapper; +// } +// +// public void setHeaderMapper(RocketMQHeaderMapper headerMapper) { +// this.headerMapper = headerMapper; +// } +// +// /** +// * Convert rocketmq {@link MessageExt} to Spring {@link Message}. +// * @param messageExt the rocketmq message +// * @return the converted Spring {@link Message} +// */ +// @SuppressWarnings("unchecked") +// private Message convertToSpringMessage(MessageExt messageExt) { +// +// // add reconsume-times header to messageExt +// int reconsumeTimes = messageExt.getReconsumeTimes(); +// messageExt.putUserProperty(ROCKETMQ_RECONSUME_TIMES, +// String.valueOf(reconsumeTimes)); +// Message message = RocketMQUtil.convertToSpringMessage(messageExt); +// return MessageBuilder.fromMessage(message) +// .copyHeaders(headerMapper.toHeaders(messageExt.getProperties())).build(); +// } +// +// public class DefaultMessageListenerConcurrently +// implements MessageListenerConcurrently { +// +// @SuppressWarnings({ "unchecked", "Duplicates" }) +// @Override +// public ConsumeConcurrentlyStatus consumeMessage(List msgs, +// ConsumeConcurrentlyContext context) { +// for (MessageExt messageExt : msgs) { +// log.debug("received msg: {}", messageExt); +// try { +// long now = System.currentTimeMillis(); +// rocketMQListener.onMessage(convertToSpringMessage(messageExt)); +// long costTime = System.currentTimeMillis() - now; +// log.debug("consume {} message key:[{}] cost: {} ms", +// messageExt.getMsgId(), messageExt.getKeys(), costTime); +// } +// catch (Exception e) { +// log.warn("consume message failed. messageExt:{}", messageExt, e); +// context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); +// return ConsumeConcurrentlyStatus.RECONSUME_LATER; +// } +// } +// +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; +// } +// +// } +// +// public class DefaultMessageListenerOrderly implements MessageListenerOrderly { +// +// @SuppressWarnings({ "unchecked", "Duplicates" }) +// @Override +// public ConsumeOrderlyStatus consumeMessage(List msgs, +// ConsumeOrderlyContext context) { +// for (MessageExt messageExt : msgs) { +// log.debug("received msg: {}", messageExt); +// try { +// long now = System.currentTimeMillis(); +// rocketMQListener.onMessage(convertToSpringMessage(messageExt)); +// long costTime = System.currentTimeMillis() - now; +// log.info("consume {} message key:[{}] cost: {} ms", +// messageExt.getMsgId(), messageExt.getKeys(), costTime); +// } +// catch (Exception e) { +// log.warn("consume message failed. messageExt:{}", messageExt, e); +// context.setSuspendCurrentQueueTimeMillis( +// suspendCurrentQueueTimeMillis); +// return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; +// } +// } +// +// return ConsumeOrderlyStatus.SUCCESS; +// } +// +// } +// +// } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java deleted file mode 100644 index a3b680419..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java +++ /dev/null @@ -1,176 +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.stream.binder.rocketmq.integration; - -import com.alibaba.cloud.stream.binder.rocketmq.consuming.RocketMQListenerBindingContainer; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; -import org.apache.rocketmq.spring.core.RocketMQListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; -import org.springframework.integration.endpoint.MessageProducerSupport; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessagingException; -import org.springframework.retry.RecoveryCallback; -import org.springframework.retry.RetryCallback; -import org.springframework.retry.RetryContext; -import org.springframework.retry.RetryListener; -import org.springframework.retry.support.RetryTemplate; -import org.springframework.util.Assert; - -/** - * @author Jim - */ -public class RocketMQInboundChannelAdapter extends MessageProducerSupport { - - private static final Logger log = LoggerFactory - .getLogger(RocketMQInboundChannelAdapter.class); - - private RetryTemplate retryTemplate; - - private RecoveryCallback recoveryCallback; - - private RocketMQListenerBindingContainer rocketMQListenerContainer; - - private final ExtendedConsumerProperties consumerProperties; - - private final InstrumentationManager instrumentationManager; - - public RocketMQInboundChannelAdapter( - RocketMQListenerBindingContainer rocketMQListenerContainer, - ExtendedConsumerProperties consumerProperties, - InstrumentationManager instrumentationManager) { - this.rocketMQListenerContainer = rocketMQListenerContainer; - this.consumerProperties = consumerProperties; - this.instrumentationManager = instrumentationManager; - } - - @Override - protected void onInit() { - if (consumerProperties == null - || !consumerProperties.getExtension().getEnabled()) { - return; - } - super.onInit(); - if (this.retryTemplate != null) { - Assert.state(getErrorChannel() == null, - "Cannot have an 'errorChannel' property when a 'RetryTemplate' is " - + "provided; use an 'ErrorMessageSendingRecoverer' in the 'recoveryCallback' property to " - + "send an error message when retries are exhausted"); - } - - BindingRocketMQListener listener = new BindingRocketMQListener(); - rocketMQListenerContainer.setRocketMQListener(listener); - - if (retryTemplate != null) { - this.retryTemplate.registerListener(listener); - } - - try { - rocketMQListenerContainer.afterPropertiesSet(); - - } - catch (Exception e) { - log.error("rocketMQListenerContainer init error: " + e.getMessage(), e); - throw new IllegalArgumentException( - "rocketMQListenerContainer init error: " + e.getMessage(), e); - } - - instrumentationManager.addHealthInstrumentation( - new Instrumentation(rocketMQListenerContainer.getTopic() - + rocketMQListenerContainer.getConsumerGroup())); - } - - @Override - protected void doStart() { - if (consumerProperties == null - || !consumerProperties.getExtension().getEnabled()) { - return; - } - try { - rocketMQListenerContainer.start(); - instrumentationManager - .getHealthInstrumentation(rocketMQListenerContainer.getTopic() - + rocketMQListenerContainer.getConsumerGroup()) - .markStartedSuccessfully(); - } - catch (Exception e) { - instrumentationManager - .getHealthInstrumentation(rocketMQListenerContainer.getTopic() - + rocketMQListenerContainer.getConsumerGroup()) - .markStartFailed(e); - log.error("RocketMQTemplate startup failed, Caused by " + e.getMessage()); - throw new MessagingException(MessageBuilder.withPayload( - "RocketMQTemplate startup failed, Caused by " + e.getMessage()) - .build(), e); - } - } - - @Override - protected void doStop() { - rocketMQListenerContainer.stop(); - } - - public void setRetryTemplate(RetryTemplate retryTemplate) { - this.retryTemplate = retryTemplate; - } - - public void setRecoveryCallback(RecoveryCallback recoveryCallback) { - this.recoveryCallback = recoveryCallback; - } - - protected class BindingRocketMQListener - implements RocketMQListener, RetryListener { - - @Override - public void onMessage(Message message) { - boolean enableRetry = RocketMQInboundChannelAdapter.this.retryTemplate != null; - if (enableRetry) { - RocketMQInboundChannelAdapter.this.retryTemplate.execute(context -> { - RocketMQInboundChannelAdapter.this.sendMessage(message); - return null; - }, (RecoveryCallback) RocketMQInboundChannelAdapter.this.recoveryCallback); - } - else { - RocketMQInboundChannelAdapter.this.sendMessage(message); - } - } - - @Override - public boolean open(RetryContext context, - RetryCallback callback) { - return true; - } - - @Override - public void close(RetryContext context, - RetryCallback callback, Throwable throwable) { - } - - @Override - public void onError(RetryContext context, - RetryCallback callback, Throwable throwable) { - - } - - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java deleted file mode 100644 index 2bf3fa627..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java +++ /dev/null @@ -1,302 +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.stream.binder.rocketmq.integration; - -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties; -import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.producer.SendCallback; -import org.apache.rocketmq.client.producer.SendResult; -import org.apache.rocketmq.client.producer.SendStatus; -import org.apache.rocketmq.common.message.MessageConst; -import org.apache.rocketmq.common.message.MessageQueue; -import org.apache.rocketmq.spring.core.RocketMQTemplate; -import org.apache.rocketmq.spring.support.RocketMQHeaders; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.cloud.stream.binder.BinderHeaders; -import org.springframework.cloud.stream.binder.ExtendedProducerProperties; -import org.springframework.cloud.stream.binding.MessageConverterConfigurer; -import org.springframework.context.Lifecycle; -import org.springframework.integration.handler.AbstractMessageHandler; -import org.springframework.integration.support.DefaultErrorMessageStrategy; -import org.springframework.integration.support.ErrorMessageStrategy; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.support.ErrorMessage; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * @author Jim - */ -public class RocketMQMessageHandler extends AbstractMessageHandler implements Lifecycle { - - private final static Logger log = LoggerFactory - .getLogger(RocketMQMessageHandler.class); - - private ErrorMessageStrategy errorMessageStrategy = new DefaultErrorMessageStrategy(); - - private MessageChannel sendFailureChannel; - - private final RocketMQTemplate rocketMQTemplate; - - private RocketMQHeaderMapper headerMapper; - - private final Boolean transactional; - - private final String destination; - - private final String groupName; - - private final InstrumentationManager instrumentationManager; - - private boolean sync = false; - - private volatile boolean running = false; - - private ExtendedProducerProperties producerProperties; - - private MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor; - - public RocketMQMessageHandler(RocketMQTemplate rocketMQTemplate, String destination, - String groupName, Boolean transactional, - InstrumentationManager instrumentationManager, - ExtendedProducerProperties producerProperties, - MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor) { - this.rocketMQTemplate = rocketMQTemplate; - this.destination = destination; - this.groupName = groupName; - this.transactional = transactional; - this.instrumentationManager = instrumentationManager; - this.producerProperties = producerProperties; - this.partitioningInterceptor = partitioningInterceptor; - } - - @Override - public void start() { - if (!transactional) { - instrumentationManager - .addHealthInstrumentation(new Instrumentation(destination)); - try { - rocketMQTemplate.afterPropertiesSet(); - instrumentationManager.getHealthInstrumentation(destination) - .markStartedSuccessfully(); - } - catch (Exception e) { - instrumentationManager.getHealthInstrumentation(destination) - .markStartFailed(e); - log.error("RocketMQTemplate startup failed, Caused by " + e.getMessage()); - throw new MessagingException(MessageBuilder.withPayload( - "RocketMQTemplate startup failed, Caused by " + e.getMessage()) - .build(), e); - } - } - if (producerProperties.isPartitioned()) { - try { - List messageQueues = rocketMQTemplate.getProducer() - .fetchPublishMessageQueues(destination); - if (producerProperties.getPartitionCount() != messageQueues.size()) { - logger.info(String.format( - "The partition count of topic '%s' will change from '%s' to '%s'", - destination, producerProperties.getPartitionCount(), - messageQueues.size())); - producerProperties.setPartitionCount(messageQueues.size()); - partitioningInterceptor - .setPartitionCount(producerProperties.getPartitionCount()); - } - } - catch (MQClientException e) { - logger.error("fetch publish message queues fail", e); - } - } - running = true; - } - - @Override - public void stop() { - if (!transactional) { - rocketMQTemplate.destroy(); - } - running = false; - } - - @Override - public boolean isRunning() { - return running; - } - - @Override - protected void handleMessageInternal( - org.springframework.messaging.Message message) { - try { - // issue 737 fix - Map jsonHeaders = headerMapper - .fromHeaders(message.getHeaders()); - message = org.springframework.messaging.support.MessageBuilder - .fromMessage(message).copyHeaders(jsonHeaders).build(); - - final StringBuilder topicWithTags = new StringBuilder(destination); - String tags = Optional - .ofNullable(message.getHeaders().get(RocketMQHeaders.TAGS)).orElse("") - .toString(); - if (!StringUtils.isEmpty(tags)) { - topicWithTags.append(":").append(tags); - } - - SendResult sendRes = null; - if (transactional) { - sendRes = rocketMQTemplate.sendMessageInTransaction(groupName, - topicWithTags.toString(), message, message.getHeaders() - .get(RocketMQBinderConstants.ROCKET_TRANSACTIONAL_ARG)); - log.debug("transactional send to topic " + topicWithTags + " " + sendRes); - } - else { - int delayLevel = 0; - try { - Object delayLevelObj = message.getHeaders() - .getOrDefault(MessageConst.PROPERTY_DELAY_TIME_LEVEL, 0); - if (delayLevelObj instanceof Number) { - delayLevel = ((Number) delayLevelObj).intValue(); - } - else if (delayLevelObj instanceof String) { - delayLevel = Integer.parseInt((String) delayLevelObj); - } - } - catch (Exception e) { - // ignore - } - boolean needSelectQueue = message.getHeaders() - .containsKey(BinderHeaders.PARTITION_HEADER); - if (sync) { - if (needSelectQueue) { - sendRes = rocketMQTemplate.syncSendOrderly( - topicWithTags.toString(), message, "", - rocketMQTemplate.getProducer().getSendMsgTimeout()); - } - else { - sendRes = rocketMQTemplate.syncSend(topicWithTags.toString(), - message, - rocketMQTemplate.getProducer().getSendMsgTimeout(), - delayLevel); - } - log.debug("sync send to topic " + topicWithTags + " " + sendRes); - } - else { - Message finalMessage = message; - SendCallback sendCallback = new SendCallback() { - @Override - public void onSuccess(SendResult sendResult) { - log.debug("async send to topic " + topicWithTags + " " - + sendResult); - } - - @Override - public void onException(Throwable e) { - log.error("RocketMQ Message hasn't been sent. Caused by " - + e.getMessage()); - if (getSendFailureChannel() != null) { - getSendFailureChannel().send( - RocketMQMessageHandler.this.errorMessageStrategy - .buildErrorMessage(new MessagingException( - finalMessage, e), null)); - } - } - }; - if (needSelectQueue) { - rocketMQTemplate.asyncSendOrderly(topicWithTags.toString(), - message, "", sendCallback, - rocketMQTemplate.getProducer().getSendMsgTimeout()); - } - else { - rocketMQTemplate.asyncSend(topicWithTags.toString(), message, - sendCallback); - } - } - } - if (sendRes != null && !sendRes.getSendStatus().equals(SendStatus.SEND_OK)) { - if (getSendFailureChannel() != null) { - this.getSendFailureChannel().send(message); - } - else { - throw new MessagingException(message, - new MQClientException("message hasn't been sent", null)); - } - } - } - catch (Exception e) { - log.error("RocketMQ Message hasn't been sent. Caused by " + e.getMessage()); - if (getSendFailureChannel() != null) { - getSendFailureChannel().send(this.errorMessageStrategy - .buildErrorMessage(new MessagingException(message, e), null)); - } - else { - throw new MessagingException(message, e); - } - } - - } - - /** - * Set the failure channel. After a send failure, an {@link ErrorMessage} will be sent - * to this channel with a payload of a {@link MessagingException} with the failed - * message and cause. - * @param sendFailureChannel the failure channel. - * @since 0.2.2 - */ - public void setSendFailureChannel(MessageChannel sendFailureChannel) { - this.sendFailureChannel = sendFailureChannel; - } - - /** - * Set the error message strategy implementation to use when sending error messages - * after send failures. Cannot be null. - * @param errorMessageStrategy the implementation. - * @since 0.2.2 - */ - public void setErrorMessageStrategy(ErrorMessageStrategy errorMessageStrategy) { - Assert.notNull(errorMessageStrategy, "'errorMessageStrategy' cannot be null"); - this.errorMessageStrategy = errorMessageStrategy; - } - - public MessageChannel getSendFailureChannel() { - return sendFailureChannel; - } - - public void setSync(boolean sync) { - this.sync = sync; - } - - public RocketMQHeaderMapper getHeaderMapper() { - return headerMapper; - } - - public void setHeaderMapper(RocketMQHeaderMapper headerMapper) { - this.headerMapper = headerMapper; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageSource.java deleted file mode 100644 index dd95864e0..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageSource.java +++ /dev/null @@ -1,382 +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.stream.binder.rocketmq.integration; - -import java.util.List; -import java.util.Set; - -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderUtils; -import com.alibaba.cloud.stream.binder.rocketmq.consuming.RocketMQMessageQueueChooser; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; -import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer; -import org.apache.rocketmq.client.consumer.MessageQueueListener; -import org.apache.rocketmq.client.consumer.MessageSelector; -import org.apache.rocketmq.client.consumer.PullResult; -import org.apache.rocketmq.client.consumer.PullStatus; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.common.message.MessageExt; -import org.apache.rocketmq.common.message.MessageQueue; -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; -import org.apache.rocketmq.spring.support.RocketMQUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; -import org.springframework.context.Lifecycle; -import org.springframework.integration.IntegrationMessageHeaderAccessor; -import org.springframework.integration.acks.AcknowledgmentCallback; -import org.springframework.integration.acks.AcknowledgmentCallbackFactory; -import org.springframework.integration.endpoint.AbstractMessageSource; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * @author Jim - */ -public class RocketMQMessageSource extends AbstractMessageSource - implements DisposableBean, Lifecycle { - - private final static Logger log = LoggerFactory - .getLogger(RocketMQMessageSource.class); - - private final RocketMQCallbackFactory ackCallbackFactory; - - private final RocketMQBinderConfigurationProperties rocketMQBinderConfigurationProperties; - - private final ExtendedConsumerProperties rocketMQConsumerProperties; - - private final String topic; - - private final String group; - - private final Object consumerMonitor = new Object(); - - private DefaultMQPullConsumer consumer; - - private boolean running; - - private MessageSelector messageSelector; - - private RocketMQMessageQueueChooser messageQueueChooser = new RocketMQMessageQueueChooser(); - - public RocketMQMessageSource( - RocketMQBinderConfigurationProperties rocketMQBinderConfigurationProperties, - ExtendedConsumerProperties rocketMQConsumerProperties, - String topic, String group) { - this(new RocketMQCallbackFactory(), rocketMQBinderConfigurationProperties, - rocketMQConsumerProperties, topic, group); - } - - public RocketMQMessageSource(RocketMQCallbackFactory ackCallbackFactory, - RocketMQBinderConfigurationProperties rocketMQBinderConfigurationProperties, - ExtendedConsumerProperties rocketMQConsumerProperties, - String topic, String group) { - this.ackCallbackFactory = ackCallbackFactory; - this.rocketMQBinderConfigurationProperties = rocketMQBinderConfigurationProperties; - this.rocketMQConsumerProperties = rocketMQConsumerProperties; - this.topic = topic; - this.group = group; - } - - @Override - public synchronized void start() { - if (this.isRunning()) { - throw new IllegalStateException( - "pull consumer already running. " + this.toString()); - } - try { - consumer = new DefaultMQPullConsumer(group); - consumer.setNamesrvAddr(RocketMQBinderUtils.getNameServerStr( - rocketMQBinderConfigurationProperties.getNameServer())); - consumer.setConsumerPullTimeoutMillis( - rocketMQConsumerProperties.getExtension().getPullTimeout()); - consumer.setMessageModel(MessageModel.CLUSTERING); - - String tags = rocketMQConsumerProperties.getExtension().getTags(); - String sql = rocketMQConsumerProperties.getExtension().getSql(); - - if (!StringUtils.isEmpty(tags) && !StringUtils.isEmpty(sql)) { - messageSelector = MessageSelector.byTag(tags); - } - else if (!StringUtils.isEmpty(tags)) { - messageSelector = MessageSelector.byTag(tags); - } - else if (!StringUtils.isEmpty(sql)) { - messageSelector = MessageSelector.bySql(sql); - } - - consumer.registerMessageQueueListener(topic, new MessageQueueListener() { - @Override - public void messageQueueChanged(String topic, Set mqAll, - Set mqDivided) { - log.info( - "messageQueueChanged, topic='{}', mqAll=`{}`, mqDivided=`{}`", - topic, mqAll, mqDivided); - switch (consumer.getMessageModel()) { - case BROADCASTING: - RocketMQMessageSource.this.resetMessageQueues(mqAll); - break; - case CLUSTERING: - RocketMQMessageSource.this.resetMessageQueues(mqDivided); - break; - default: - break; - } - } - }); - consumer.start(); - } - catch (MQClientException e) { - log.error("DefaultMQPullConsumer startup error: " + e.getMessage(), e); - } - this.setRunning(true); - } - - @Override - public synchronized void stop() { - if (this.isRunning()) { - this.setRunning(false); - consumer.shutdown(); - } - } - - @Override - public synchronized boolean isRunning() { - return running; - } - - @Override - protected synchronized Object doReceive() { - if (messageQueueChooser.getMessageQueues() == null - || messageQueueChooser.getMessageQueues().size() == 0) { - return null; - } - try { - int count = 0; - while (count < messageQueueChooser.getMessageQueues().size()) { - MessageQueue messageQueue; - synchronized (this.consumerMonitor) { - messageQueue = messageQueueChooser.choose(); - messageQueueChooser.increment(); - } - - long offset = consumer.fetchConsumeOffset(messageQueue, - rocketMQConsumerProperties.getExtension().isFromStore()); - - log.debug("topic='{}', group='{}', messageQueue='{}', offset now='{}'", - this.topic, this.group, messageQueue, offset); - - PullResult pullResult; - if (messageSelector != null) { - pullResult = consumer.pull(messageQueue, messageSelector, offset, 1); - } - else { - pullResult = consumer.pull(messageQueue, (String) null, offset, 1); - } - - if (pullResult.getPullStatus() == PullStatus.FOUND) { - List messageExtList = pullResult.getMsgFoundList(); - - Message message = RocketMQUtil - .convertToSpringMessage(messageExtList.get(0)); - - AcknowledgmentCallback ackCallback = this.ackCallbackFactory - .createCallback(new RocketMQAckInfo(messageQueue, pullResult, - consumer, offset)); - - Message messageResult = MessageBuilder.fromMessage(message).setHeader( - IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK, - ackCallback).build(); - return messageResult; - } - else { - log.debug("messageQueue='{}' PullResult='{}' with topic `{}`", - messageQueueChooser.getMessageQueues(), - pullResult.getPullStatus(), topic); - } - count++; - } - } - catch (Exception e) { - log.error("Consumer pull error: " + e.getMessage(), e); - } - return null; - } - - @Override - public String getComponentType() { - return "rocketmq:message-source"; - } - - public synchronized void setRunning(boolean running) { - this.running = running; - } - - public synchronized void resetMessageQueues(Set queueSet) { - log.info("resetMessageQueues, topic='{}', messageQueue=`{}`", topic, queueSet); - synchronized (this.consumerMonitor) { - this.messageQueueChooser.reset(queueSet); - } - } - - public static class RocketMQCallbackFactory - implements AcknowledgmentCallbackFactory { - - @Override - public AcknowledgmentCallback createCallback(RocketMQAckInfo info) { - return new RocketMQAckCallback(info); - } - - } - - public static class RocketMQAckCallback implements AcknowledgmentCallback { - - private final RocketMQAckInfo ackInfo; - - private boolean acknowledged; - - private boolean autoAckEnabled = true; - - public RocketMQAckCallback(RocketMQAckInfo ackInfo) { - this.ackInfo = ackInfo; - } - - protected void setAcknowledged(boolean acknowledged) { - this.acknowledged = acknowledged; - } - - @Override - public boolean isAcknowledged() { - return this.acknowledged; - } - - @Override - public void noAutoAck() { - this.autoAckEnabled = false; - } - - @Override - public boolean isAutoAck() { - return this.autoAckEnabled; - } - - @Override - public void acknowledge(Status status) { - Assert.notNull(status, "'status' cannot be null"); - if (this.acknowledged) { - throw new IllegalStateException("Already acknowledged"); - } - log.debug("acknowledge(" + status.name() + ") for " + this); - synchronized (this.ackInfo.getConsumerMonitor()) { - try { - switch (status) { - case ACCEPT: - case REJECT: - ackInfo.getConsumer().updateConsumeOffset( - ackInfo.getMessageQueue(), - ackInfo.getPullResult().getNextBeginOffset()); - log.debug("messageQueue='{}' offset update to `{}`", - ackInfo.getMessageQueue(), String.valueOf( - ackInfo.getPullResult().getNextBeginOffset())); - break; - case REQUEUE: - // decrease index and update offset of messageQueue of ackInfo - int oldIndex = ackInfo.getMessageQueueChooser().requeue(); - ackInfo.getConsumer().updateConsumeOffset( - ackInfo.getMessageQueue(), ackInfo.getOldOffset()); - log.debug( - "messageQueue='{}' offset requeue to index:`{}`, oldOffset:'{}'", - ackInfo.getMessageQueue(), oldIndex, - ackInfo.getOldOffset()); - break; - default: - break; - } - } - catch (MQClientException e) { - log.error("acknowledge error: " + e.getErrorMessage(), e); - } - finally { - this.acknowledged = true; - } - } - } - - @Override - public String toString() { - return "RocketMQAckCallback{" + "ackInfo=" + ackInfo + ", acknowledged=" - + acknowledged + ", autoAckEnabled=" + autoAckEnabled + '}'; - } - - } - - public class RocketMQAckInfo { - - private final MessageQueue messageQueue; - - private final PullResult pullResult; - - private final DefaultMQPullConsumer consumer; - - private final long oldOffset; - - public RocketMQAckInfo(MessageQueue messageQueue, PullResult pullResult, - DefaultMQPullConsumer consumer, long oldOffset) { - this.messageQueue = messageQueue; - this.pullResult = pullResult; - this.consumer = consumer; - this.oldOffset = oldOffset; - } - - public MessageQueue getMessageQueue() { - return messageQueue; - } - - public PullResult getPullResult() { - return pullResult; - } - - public DefaultMQPullConsumer getConsumer() { - return consumer; - } - - public RocketMQMessageQueueChooser getMessageQueueChooser() { - return RocketMQMessageSource.this.messageQueueChooser; - } - - public long getOldOffset() { - return oldOffset; - } - - public Object getConsumerMonitor() { - return RocketMQMessageSource.this.consumerMonitor; - } - - @Override - public String toString() { - return "RocketMQAckInfo{" + "messageQueue=" + messageQueue + ", pullResult=" - + pullResult + ", consumer=" + consumer + ", oldOffset=" + oldOffset - + '}'; - } - - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java index 080bebf90..397e62854 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java @@ -16,8 +16,11 @@ package com.alibaba.cloud.stream.binder.rocketmq.metrics; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; +import org.springframework.context.Lifecycle; + /** * @author Timur Valiev * @author Jim @@ -25,6 +28,7 @@ import java.util.concurrent.atomic.AtomicBoolean; public class Instrumentation { private final String name; + private Lifecycle actuator; protected final AtomicBoolean started = new AtomicBoolean(false); @@ -34,6 +38,19 @@ public class Instrumentation { this.name = name; } + public Instrumentation(String name, Lifecycle actuator) { + this.name = name; + this.actuator = actuator; + } + + public Lifecycle getActuator() { + return actuator; + } + + public void setActuator(Lifecycle actuator) { + this.actuator = actuator; + } + public boolean isDown() { return startException != null; } @@ -67,4 +84,8 @@ public class Instrumentation { return startException; } + @Override + public int hashCode() { + return Objects.hash(getName(), getActuator()); + } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java index 8b4939585..de6e1e794 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java @@ -16,37 +16,34 @@ package com.alibaba.cloud.stream.binder.rocketmq.metrics; +import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; /** * @author Timur Valiev * @author Jim */ -public class InstrumentationManager { +public final class InstrumentationManager { - private final Map runtime = new ConcurrentHashMap<>(); + private static final Map HEALTH_INSTRUMENTATIONS = new HashMap<>(); - private final Map healthInstrumentations = new HashMap<>(); - - public Set getHealthInstrumentations() { - return healthInstrumentations.entrySet().stream().map(Map.Entry::getValue) - .collect(Collectors.toSet()); - } - - public void addHealthInstrumentation(Instrumentation instrumentation) { - healthInstrumentations.put(instrumentation.getName(), instrumentation); + public static Collection getHealthInstrumentations() { + return HEALTH_INSTRUMENTATIONS.values(); } - public Instrumentation getHealthInstrumentation(String key) { - return healthInstrumentations.get(key); - } + public static void addHealthInstrumentation(Instrumentation instrumentation) { + if (null != instrumentation) { + HEALTH_INSTRUMENTATIONS.computeIfPresent(instrumentation.hashCode(), + (k, v) -> { + if (instrumentation.getActuator() != null) { + instrumentation.getActuator().stop(); + } + throw new IllegalArgumentException( + "The current actuator exists, please confirm if there is a repeat operation!!!"); + }); + } - public Map getRuntime() { - return runtime; } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java index 3a9dcb403..fd5e77919 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java @@ -1,11 +1,11 @@ /* - * Copyright 2013-2018 the original author or authors. + * Copyright (C) 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,86 +16,13 @@ package com.alibaba.cloud.stream.binder.rocketmq.properties; -import java.util.Arrays; -import java.util.List; - -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants; -import org.apache.rocketmq.common.MixAll; - import org.springframework.boot.context.properties.ConfigurationProperties; /** - * @author Timur Valiev + * binding rocketMq properties. * @author Jim */ @ConfigurationProperties(prefix = "spring.cloud.stream.rocketmq.binder") -public class RocketMQBinderConfigurationProperties { - - /** - * The name server list for rocketMQ. - */ - private List nameServer = Arrays - .asList(RocketMQBinderConstants.DEFAULT_NAME_SERVER); - - /** - * The property of "access-key". - */ - private String accessKey; - - /** - * The property of "secret-key". - */ - private String secretKey; - - /** - * Switch flag instance for message trace. - */ - private boolean enableMsgTrace = true; - - /** - * The name value of message trace topic.If you don't config,you can use the default - * trace topic name. - */ - private String customizedTraceTopic = MixAll.RMQ_SYS_TRACE_TOPIC; - - public List getNameServer() { - return nameServer; - } - - public void setNameServer(List nameServer) { - this.nameServer = nameServer; - } - - public String getAccessKey() { - return accessKey; - } - - public void setAccessKey(String accessKey) { - this.accessKey = accessKey; - } - - public String getSecretKey() { - return secretKey; - } - - public void setSecretKey(String secretKey) { - this.secretKey = secretKey; - } - - public boolean isEnableMsgTrace() { - return enableMsgTrace; - } - - public void setEnableMsgTrace(boolean enableMsgTrace) { - this.enableMsgTrace = enableMsgTrace; - } - - public String getCustomizedTraceTopic() { - return customizedTraceTopic; - } - - public void setCustomizedTraceTopic(String customizedTraceTopic) { - this.customizedTraceTopic = customizedTraceTopic; - } +public class RocketMQBinderConfigurationProperties extends RocketMQCommonProperties { } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBindingProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBindingProperties.java deleted file mode 100644 index 814ae1018..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBindingProperties.java +++ /dev/null @@ -1,49 +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.stream.binder.rocketmq.properties; - -import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; - -/** - * @author Timur Valiev - * @author Jim - */ -public class RocketMQBindingProperties implements BinderSpecificPropertiesProvider { - - private RocketMQConsumerProperties consumer = new RocketMQConsumerProperties(); - - private RocketMQProducerProperties producer = new RocketMQProducerProperties(); - - @Override - public RocketMQConsumerProperties getConsumer() { - return consumer; - } - - public void setConsumer(RocketMQConsumerProperties consumer) { - this.consumer = consumer; - } - - @Override - public RocketMQProducerProperties getProducer() { - return producer; - } - - public void setProducer(RocketMQProducerProperties producer) { - this.producer = producer; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java index 9c059ec56..1a889f6d7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java @@ -1,11 +1,11 @@ /* - * Copyright 2013-2018 the original author or authors. + * Copyright (C) 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,153 +16,436 @@ package com.alibaba.cloud.stream.binder.rocketmq.properties; -import java.util.Set; +import java.io.Serializable; -import com.alibaba.cloud.stream.binder.rocketmq.support.JacksonRocketMQHeaderMapper; -import org.apache.rocketmq.client.consumer.MQPushConsumer; -import org.apache.rocketmq.client.consumer.MessageSelector; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; +import org.apache.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService; +import org.apache.rocketmq.client.impl.consumer.ConsumeMessageOrderlyService; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; /** - * @author Timur Valiev + * Extended consumer properties for RocketMQ binder. + * * @author Jim */ -public class RocketMQConsumerProperties { +public class RocketMQConsumerProperties extends RocketMQCommonProperties { /** - * using '||' to split tag {@link MQPushConsumer#subscribe(String, String)}. + * Message model defines the way how messages are delivered to each consumer clients. + *

+ * + * This field defaults to clustering. */ - private String tags; + private String messageModel = MessageModel.CLUSTERING.getModeCN(); /** - * {@link MQPushConsumer#subscribe(String, MessageSelector)} - * {@link MessageSelector#bySql(String)}. + * Queue allocation algorithm specifying how message queues are allocated to each + * consumer clients. */ - private String sql; + private String allocateMessageQueueStrategy; /** - * {@link MessageModel#BROADCASTING}. + * The expressions include tags or SQL,as follow: + *

+ * tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } . + *

+ * Determines whether there are specific characters "{@code ||}" in the expression to + * determine how the message is filtered,tags or SQL. */ - private Boolean broadcasting = false; + private String subscription; /** - * if orderly is true, using {@link MessageListenerOrderly} else if orderly if false, - * using {@link MessageListenerConcurrently}. + * Delay some time when exception occur */ - private Boolean orderly = false; + private long pullTimeDelayMillsWhenException = 1000; /** - * for concurrently listener. message consume retry strategy. see - * {@link ConsumeConcurrentlyContext#delayLevelWhenNextConsume}. -1 means dlq(or - * discard, see {@link this#shouldRequeue}), others means requeue. + * Consuming point on consumer booting. + *

+ * + * There are three consuming points: + *
    + *
  • CONSUME_FROM_LAST_OFFSET: consumer clients pick up where it + * stopped previously. If it were a newly booting up consumer client, according aging + * of the consumer group, there are two cases: + *
      + *
    1. if the consumer group is created so recently that the earliest message being + * subscribed has yet expired, which means the consumer group represents a lately + * launched business, consuming will start from the very beginning;
    2. + *
    3. if the earliest message being subscribed has expired, consuming will start from + * the latest messages, meaning messages born prior to the booting timestamp would be + * ignored.
    4. + *
    + *
  • + *
  • CONSUME_FROM_FIRST_OFFSET: Consumer client will start from + * earliest messages available.
  • + *
  • CONSUME_FROM_TIMESTAMP: Consumer client will start from specified + * timestamp, which means messages born prior to {@link #consumeTimestamp} will be + * ignored
  • + *
+ */ + private ConsumeFromWhere consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET; + /** + * Backtracking consumption time with second precision. Time format is + * 20131223171201
+ * Implying Seventeen twelve and 01 seconds on December 23, 2013 year
+ * Default backtracking consumption time Half an hour ago. */ - private int delayLevelWhenNextConsume = 0; + private String consumeTimestamp = UtilAll + .timeMillisToHumanString3(System.currentTimeMillis() - (1000 * 60 * 30)); /** - * for orderly listener. next retry delay time. + * Flow control threshold on queue level, each message queue will cache at most 1000 + * messages by default, Consider the {@link #pullBatchSize}, the instantaneous value + * may exceed the limit */ - private long suspendCurrentQueueTimeMillis = 1000; + private int pullThresholdForQueue = 1000; + /** + * Limit the cached message size on queue level, each message queue will cache at most + * 100 MiB messages by default, Consider the {@link #pullBatchSize}, the instantaneous + * value may exceed the limit + * + *

+ * The size of a message only measured by message body, so it's not accurate + */ + private int pullThresholdSizeForQueue = 100; - private Boolean enabled = true; + /** + * Maximum number of messages pulled each time. + */ + private int pullBatchSize = 10; /** - * {@link JacksonRocketMQHeaderMapper#addTrustedPackages(String...)}. + * Consume max span offset.it has no effect on sequential consumption. */ - private Set trustedPackages; + private int consumeMaxSpan = 2000; - // ------------ For Pull Consumer ------------ + private Push push = new Push(); + private Pull pull = new Pull(); - private long pullTimeout = 10 * 1000; + public String getMessageModel() { + return messageModel; + } + + public RocketMQConsumerProperties setMessageModel(String messageModel) { + this.messageModel = messageModel; + return this; + } - private boolean fromStore; + public String getAllocateMessageQueueStrategy() { + return allocateMessageQueueStrategy; + } - // ------------ For Pull Consumer ------------ + public void setAllocateMessageQueueStrategy(String allocateMessageQueueStrategy) { + this.allocateMessageQueueStrategy = allocateMessageQueueStrategy; + } + + public String getSubscription() { + return subscription; + } - public String getTags() { - return tags; + public void setSubscription(String subscription) { + this.subscription = subscription; } - public void setTags(String tags) { - this.tags = tags; + public Push getPush() { + return push; } - public String getSql() { - return sql; + public void setPush(Push push) { + this.push = push; } - public void setSql(String sql) { - this.sql = sql; + public long getPullTimeDelayMillsWhenException() { + return pullTimeDelayMillsWhenException; } - public Boolean getOrderly() { - return orderly; + public RocketMQConsumerProperties setPullTimeDelayMillsWhenException( + long pullTimeDelayMillsWhenException) { + this.pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException; + return this; } - public void setOrderly(Boolean orderly) { - this.orderly = orderly; + public ConsumeFromWhere getConsumeFromWhere() { + return consumeFromWhere; } - public Boolean getEnabled() { - return enabled; + public RocketMQConsumerProperties setConsumeFromWhere( + ConsumeFromWhere consumeFromWhere) { + this.consumeFromWhere = consumeFromWhere; + return this; } - public void setEnabled(Boolean enabled) { - this.enabled = enabled; + public String getConsumeTimestamp() { + return consumeTimestamp; } - public Boolean getBroadcasting() { - return broadcasting; + public RocketMQConsumerProperties setConsumeTimestamp(String consumeTimestamp) { + this.consumeTimestamp = consumeTimestamp; + return this; } - public void setBroadcasting(Boolean broadcasting) { - this.broadcasting = broadcasting; + public int getPullThresholdForQueue() { + return pullThresholdForQueue; } - public int getDelayLevelWhenNextConsume() { - return delayLevelWhenNextConsume; + public RocketMQConsumerProperties setPullThresholdForQueue( + int pullThresholdForQueue) { + this.pullThresholdForQueue = pullThresholdForQueue; + return this; } - public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) { - this.delayLevelWhenNextConsume = delayLevelWhenNextConsume; + public int getPullThresholdSizeForQueue() { + return pullThresholdSizeForQueue; } - public long getSuspendCurrentQueueTimeMillis() { - return suspendCurrentQueueTimeMillis; + public RocketMQConsumerProperties setPullThresholdSizeForQueue( + int pullThresholdSizeForQueue) { + this.pullThresholdSizeForQueue = pullThresholdSizeForQueue; + return this; } - public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) { - this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis; + public int getPullBatchSize() { + return pullBatchSize; } - public long getPullTimeout() { - return pullTimeout; + public RocketMQConsumerProperties setPullBatchSize(int pullBatchSize) { + this.pullBatchSize = pullBatchSize; + return this; } - public void setPullTimeout(long pullTimeout) { - this.pullTimeout = pullTimeout; + public Pull getPull() { + return pull; } - public boolean isFromStore() { - return fromStore; + public RocketMQConsumerProperties setPull(Pull pull) { + this.pull = pull; + return this; } - public void setFromStore(boolean fromStore) { - this.fromStore = fromStore; + public int getConsumeMaxSpan() { + return consumeMaxSpan; } - public boolean shouldRequeue() { - return delayLevelWhenNextConsume != -1; + public RocketMQConsumerProperties setConsumeMaxSpan(int consumeMaxSpan) { + this.consumeMaxSpan = consumeMaxSpan; + return this; } - public Set getTrustedPackages() { - return trustedPackages; + public static class Push implements Serializable { + private static final long serialVersionUID = -7398468554978817630L; + + /** + * if orderly is true, using {@link MessageListenerOrderly} else if orderly if + * false, using {@link MessageListenerConcurrently}. + */ + private boolean orderly = false; + /** + * Suspending pulling time for cases requiring slow pulling like flow-control + * scenario. see{@link ConsumeMessageOrderlyService#processConsumeResult}. + * see{@link ConsumeOrderlyContext#getSuspendCurrentQueueTimeMillis}. + */ + private int suspendCurrentQueueTimeMillis = 1000; + + /** + * https://github.com/alibaba/spring-cloud-alibaba/issues/1866 Max re-consume + * times. -1 means 16 times. + *

+ * If messages are re-consumed more than {@link #maxReconsumeTimes} before + * success, it's be directed to a deletion queue waiting. + */ + private int maxReconsumeTimes; + + /** + * for concurrently listener. message consume retry strategy. -1 means dlq(or + * discard. see {@link ConsumeMessageConcurrentlyService#processConsumeResult}. + * see {@link ConsumeConcurrentlyContext#getDelayLevelWhenNextConsume}. + */ + private int delayLevelWhenNextConsume = 0; + + /** + * Flow control threshold on topic level, default value is -1(Unlimited) + *

+ * The value of {@code pullThresholdForQueue} will be overwrote and calculated + * based on {@code pullThresholdForTopic} if it is't unlimited + *

+ * For example, if the value of pullThresholdForTopic is 1000 and 10 message + * queues are assigned to this consumer, then pullThresholdForQueue will be set to + * 100. + */ + private int pullThresholdForTopic = -1; + + /** + * Limit the cached message size on topic level, default value is -1 + * MiB(Unlimited) + *

+ * The value of {@code pullThresholdSizeForQueue} will be overwrote and calculated + * based on {@code pullThresholdSizeForTopic} if it is't unlimited + *

+ * For example, if the value of pullThresholdSizeForTopic is 1000 MiB and 10 + * message queues are assigned to this consumer, then pullThresholdSizeForQueue + * will be set to 100 MiB + */ + private int pullThresholdSizeForTopic = -1; + + /** + * Message pull Interval + */ + private long pullInterval = 0; + + /** + * Batch consumption size + */ + private int consumeMessageBatchMaxSize = 1; + + public boolean getOrderly() { + return orderly; + } + + public void setOrderly(boolean orderly) { + this.orderly = orderly; + } + + public int getSuspendCurrentQueueTimeMillis() { + return suspendCurrentQueueTimeMillis; + } + + public void setSuspendCurrentQueueTimeMillis(int suspendCurrentQueueTimeMillis) { + this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis; + } + + public int getMaxReconsumeTimes() { + return maxReconsumeTimes; + } + + public void setMaxReconsumeTimes(int maxReconsumeTimes) { + this.maxReconsumeTimes = maxReconsumeTimes; + } + + public int getDelayLevelWhenNextConsume() { + return delayLevelWhenNextConsume; + } + + public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) { + this.delayLevelWhenNextConsume = delayLevelWhenNextConsume; + } + + public int getPullThresholdForTopic() { + return pullThresholdForTopic; + } + + public void setPullThresholdForTopic(int pullThresholdForTopic) { + this.pullThresholdForTopic = pullThresholdForTopic; + } + + public int getPullThresholdSizeForTopic() { + return pullThresholdSizeForTopic; + } + + public void setPullThresholdSizeForTopic(int pullThresholdSizeForTopic) { + this.pullThresholdSizeForTopic = pullThresholdSizeForTopic; + } + + public long getPullInterval() { + return pullInterval; + } + + public void setPullInterval(long pullInterval) { + this.pullInterval = pullInterval; + } + + public int getConsumeMessageBatchMaxSize() { + return consumeMessageBatchMaxSize; + } + + public void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) { + this.consumeMessageBatchMaxSize = consumeMessageBatchMaxSize; + } } - public void setTrustedPackages(Set trustedPackages) { - this.trustedPackages = trustedPackages; + public static class Pull implements Serializable { + /** + * The poll timeout in milliseconds + */ + private long pollTimeoutMillis = 1000 * 5; + /** + * Pull thread number + */ + private int pullThreadNums = 20; + + /** + * Interval time in in milliseconds for checking changes in topic metadata. + */ + private long topicMetadataCheckIntervalMillis = 30 * 1000; + + /** + * Long polling mode, the Consumer connection timeout(must greater than + * brokerSuspendMaxTimeMillis), it is not recommended to modify + */ + private long consumerTimeoutMillisWhenSuspend = 1000 * 30; + + /** + * Ack state handling, including receive, reject, and retry, when a consumption + * exception occurs. see {@link } + */ + private String errAcknowledge; + + private long pullThresholdForAll = 1000L; + + public long getPollTimeoutMillis() { + return pollTimeoutMillis; + } + + public void setPollTimeoutMillis(long pollTimeoutMillis) { + this.pollTimeoutMillis = pollTimeoutMillis; + } + + public int getPullThreadNums() { + return pullThreadNums; + } + + public void setPullThreadNums(int pullThreadNums) { + this.pullThreadNums = pullThreadNums; + } + + public long getTopicMetadataCheckIntervalMillis() { + return topicMetadataCheckIntervalMillis; + } + + public void setTopicMetadataCheckIntervalMillis( + long topicMetadataCheckIntervalMillis) { + this.topicMetadataCheckIntervalMillis = topicMetadataCheckIntervalMillis; + } + + public long getConsumerTimeoutMillisWhenSuspend() { + return consumerTimeoutMillisWhenSuspend; + } + + public void setConsumerTimeoutMillisWhenSuspend( + long consumerTimeoutMillisWhenSuspend) { + this.consumerTimeoutMillisWhenSuspend = consumerTimeoutMillisWhenSuspend; + } + + public String getErrAcknowledge() { + return errAcknowledge; + } + + public void setErrAcknowledge(String errAcknowledge) { + this.errAcknowledge = errAcknowledge; + } + + public long getPullThresholdForAll() { + return pullThresholdForAll; + } + + public void setPullThresholdForAll(long pullThresholdForAll) { + this.pullThresholdForAll = pullThresholdForAll; + } } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java index 890d22500..5fc34ed08 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java @@ -1,11 +1,11 @@ /* - * Copyright 2013-2018 the original author or authors. + * Copyright (C) 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,12 +21,14 @@ import org.springframework.cloud.stream.binder.AbstractExtendedBindingProperties import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; /** - * @author Timur Valiev + * rocketMQ specific extended binding properties class that extends from + * {@link AbstractExtendedBindingProperties}. + * * @author Jim */ @ConfigurationProperties("spring.cloud.stream.rocketmq") public class RocketMQExtendedBindingProperties extends - AbstractExtendedBindingProperties { + AbstractExtendedBindingProperties { private static final String DEFAULTS_PREFIX = "spring.cloud.stream.rocketmq.default"; @@ -37,7 +39,7 @@ public class RocketMQExtendedBindingProperties extends @Override public Class getExtendedPropertiesEntryClass() { - return RocketMQBindingProperties.class; + return RocketMQSpecificPropertiesProvider.class; } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java index ab2a92a3a..8f73cf93f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java @@ -1,11 +1,11 @@ /* - * Copyright 2013-2018 the original author or authors. + * Copyright (C) 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,55 +16,39 @@ package com.alibaba.cloud.stream.binder.rocketmq.properties; -import org.apache.rocketmq.client.producer.DefaultMQProducer; - /** - * @author Timur Valiev + * Extended producer properties for RocketMQ binder. + * * @author Jim */ -public class RocketMQProducerProperties { - - private Boolean enabled = true; +public class RocketMQProducerProperties extends RocketMQCommonProperties { /** - * Name of producer. + * Timeout for sending messages. */ - private String group; - - /** - * Maximum allowed message size in bytes {@link DefaultMQProducer#maxMessageSize}. - */ - private Integer maxMessageSize = 1024 * 1024 * 4; - - private Boolean transactional = false; - - private Boolean sync = false; - - private Boolean vipChannelEnabled = true; - - /** - * Millis of send message timeout. - */ - private int sendMessageTimeout = 3000; + private int sendMsgTimeout = 3000; /** * Compress message body threshold, namely, message body larger than 4k will be * compressed on default. */ - private int compressMessageBodyThreshold = 1024 * 4; + private int compressMsgBodyThreshold = 1024 * 4; /** * Maximum number of retry to perform internally before claiming sending failure in - * synchronous mode. This may potentially cause message duplication which is up to - * application developers to resolve. + * synchronous mode. + *

+ * + * This may potentially cause message duplication which is up to application + * developers to resolve. */ private int retryTimesWhenSendFailed = 2; /** - *

* Maximum number of retry to perform internally before claiming sending failure in * asynchronous mode. *

+ * * This may potentially cause message duplication which is up to application * developers to resolve. */ @@ -73,94 +57,165 @@ public class RocketMQProducerProperties { /** * Indicate whether to retry another broker on sending failure internally. */ - private boolean retryNextServer = false; + private boolean retryAnotherBroker = false; - public String getGroup() { - return group; + /** + * Maximum allowed message size in bytes. + */ + private int maxMessageSize = 1024 * 1024 * 4; + + private String producerType = ProducerType.Normal.name(); + + private String sendType = SendType.Sync.name(); + + private String sendCallBack; + + private String transactionListener; + + private String messageQueueSelector; + + private String errorMessageStrategy; + + private String sendFailureChannel; + + private String checkForbiddenHook; + + private String sendMessageHook; + + public int getSendMsgTimeout() { + return sendMsgTimeout; + } + + public void setSendMsgTimeout(int sendMsgTimeout) { + this.sendMsgTimeout = sendMsgTimeout; } - public void setGroup(String group) { - this.group = group; + public int getCompressMsgBodyThreshold() { + return compressMsgBodyThreshold; } - public Boolean getEnabled() { - return enabled; + public void setCompressMsgBodyThreshold(int compressMsgBodyThreshold) { + this.compressMsgBodyThreshold = compressMsgBodyThreshold; } - public void setEnabled(Boolean enabled) { - this.enabled = enabled; + public int getRetryTimesWhenSendFailed() { + return retryTimesWhenSendFailed; } - public Integer getMaxMessageSize() { + public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) { + this.retryTimesWhenSendFailed = retryTimesWhenSendFailed; + } + + public int getRetryTimesWhenSendAsyncFailed() { + return retryTimesWhenSendAsyncFailed; + } + + public void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) { + this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed; + } + + public boolean getRetryAnotherBroker() { + return retryAnotherBroker; + } + + public void setRetryAnotherBroker(boolean retryAnotherBroker) { + this.retryAnotherBroker = retryAnotherBroker; + } + + public int getMaxMessageSize() { return maxMessageSize; } - public void setMaxMessageSize(Integer maxMessageSize) { + public void setMaxMessageSize(int maxMessageSize) { this.maxMessageSize = maxMessageSize; } - public Boolean getTransactional() { - return transactional; + public String getProducerType() { + return producerType; } - public void setTransactional(Boolean transactional) { - this.transactional = transactional; + public void setProducerType(String producerType) { + this.producerType = producerType; } - public Boolean getSync() { - return sync; + public String getSendType() { + return sendType; } - public void setSync(Boolean sync) { - this.sync = sync; + public void setSendType(String sendType) { + this.sendType = sendType; } - public Boolean getVipChannelEnabled() { - return vipChannelEnabled; + public String getSendCallBack() { + return sendCallBack; } - public void setVipChannelEnabled(Boolean vipChannelEnabled) { - this.vipChannelEnabled = vipChannelEnabled; + public void setSendCallBack(String sendCallBack) { + this.sendCallBack = sendCallBack; } - public int getSendMessageTimeout() { - return sendMessageTimeout; + public String getTransactionListener() { + return transactionListener; } - public void setSendMessageTimeout(int sendMessageTimeout) { - this.sendMessageTimeout = sendMessageTimeout; + public void setTransactionListener(String transactionListener) { + this.transactionListener = transactionListener; } - public int getCompressMessageBodyThreshold() { - return compressMessageBodyThreshold; + public String getMessageQueueSelector() { + return messageQueueSelector; } - public void setCompressMessageBodyThreshold(int compressMessageBodyThreshold) { - this.compressMessageBodyThreshold = compressMessageBodyThreshold; + public void setMessageQueueSelector(String messageQueueSelector) { + this.messageQueueSelector = messageQueueSelector; } - public int getRetryTimesWhenSendFailed() { - return retryTimesWhenSendFailed; + public String getErrorMessageStrategy() { + return errorMessageStrategy; } - public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) { - this.retryTimesWhenSendFailed = retryTimesWhenSendFailed; + public void setErrorMessageStrategy(String errorMessageStrategy) { + this.errorMessageStrategy = errorMessageStrategy; } - public int getRetryTimesWhenSendAsyncFailed() { - return retryTimesWhenSendAsyncFailed; + public String getSendFailureChannel() { + return sendFailureChannel; } - public void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) { - this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed; + public void setSendFailureChannel(String sendFailureChannel) { + this.sendFailureChannel = sendFailureChannel; + } + + public String getCheckForbiddenHook() { + return checkForbiddenHook; } - public boolean isRetryNextServer() { - return retryNextServer; + public void setCheckForbiddenHook(String checkForbiddenHook) { + this.checkForbiddenHook = checkForbiddenHook; } - public void setRetryNextServer(boolean retryNextServer) { - this.retryNextServer = retryNextServer; + public String getSendMessageHook() { + return sendMessageHook; + } + + public void setSendMessageHook(String sendMessageHook) { + this.sendMessageHook = sendMessageHook; + } + + public enum ProducerType { + Normal, Trans; + + public boolean equalsName(String name) { + return this.name().equalsIgnoreCase(name); + } + } + + public enum SendType { + OneWay, Async, Sync,; + + public boolean equalsName(String name) { + return this.name().equalsIgnoreCase(name); + } } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java index 694dcdc96..0580fe859 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java @@ -36,7 +36,7 @@ public class PartitionMessageQueueSelector implements MessageQueueSelector { @Override public MessageQueue select(List mqs, Message msg, Object arg) { - Integer partition = 0; + int partition = 0; try { partition = Math.abs( Integer.parseInt(msg.getProperty(BinderHeaders.PARTITION_HEADER))); From a6e01c998417669fcd4d4b053db454d37725fe7a Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 1 Feb 2021 11:24:25 +0800 Subject: [PATCH 07/99] Code refactoring and some new feature support --- ...gHandlerMappingsProviderConfiguration.java | 45 +++ .../RocketMQBinderAutoConfiguration.java | 81 +++++ .../rocketmq/contants/RocketMQConst.java | 90 ++++++ .../convert/RocketMQMessageConverter.java | 84 +++++ .../custom/RocketMQBeanContainerCache.java | 75 +++++ .../RocketMQConfigBeanPostProcessor.java | 43 +++ .../extend/ErrorAcknowledgeHandler.java | 35 +++ .../inbound/RocketMQConsumerFactory.java | 156 ++++++++++ .../RocketMQInboundChannelAdapter.java | 228 ++++++++++++++ .../pull/DefaultErrorAcknowledgeHandler.java | 43 +++ .../inbound/pull/RocketMQAckCallback.java | 112 +++++++ .../inbound/pull/RocketMQMessageSource.java | 161 ++++++++++ .../outbound/RocketMQProduceFactory.java | 131 ++++++++ .../RocketMQProducerMessageHandler.java | 286 ++++++++++++++++++ .../properties/RocketMQCommonProperties.java | 201 ++++++++++++ .../RocketMQSpecificPropertiesProvider.java | 66 ++++ .../RocketMQMessageConverterSupport.java | 185 +++++++++++ .../binder/rocketmq/utils/RocketMQUtils.java | 98 ++++++ 18 files changed, 2120 insertions(+) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java new file mode 100644 index 000000000..eb6e6ce52 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java @@ -0,0 +1,45 @@ +/* + * 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.stream.binder.rocketmq.autoconfigurate; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.context.properties.source.ConfigurationPropertyName; +import org.springframework.cloud.stream.config.BindingHandlerAdvise.MappingsProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ExtendedBindingHandlerMappingsProviderConfiguration { + + @Bean + public MappingsProvider rocketExtendedPropertiesDefaultMappingsProvider() { + return () -> { + Map mappings = new HashMap<>(); + mappings.put( + ConfigurationPropertyName.of("spring.cloud.stream.rocketmq.bindings"), + ConfigurationPropertyName.of("spring.cloud.stream.rocketmq.default")); + mappings.put( + ConfigurationPropertyName.of("spring.cloud.stream.rocketmq.streams"), + ConfigurationPropertyName + .of("spring.cloud.stream.rocketmq.streams.default")); + return mappings; + }; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java new file mode 100644 index 000000000..abcb9b961 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java @@ -0,0 +1,81 @@ +/* + * 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.stream.binder.rocketmq.autoconfigurate; + +import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder; +import com.alibaba.cloud.stream.binder.rocketmq.actuator.RocketMQBinderHealthIndicator; +import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter; +import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; +import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; +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; +import org.springframework.messaging.converter.CompositeMessageConverter; + +/** + * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681 + * @author Timur Valiev + * @author Jim + */ +@Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties({ RocketMQExtendedBindingProperties.class, + RocketMQBinderConfigurationProperties.class }) +public class RocketMQBinderAutoConfiguration { + + @Autowired + private RocketMQExtendedBindingProperties extendedBindingProperties; + @Autowired + private RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties; + + @Bean + public RocketMQConfigBeanPostProcessor rocketMQConfigBeanPostProcessor() { + return new RocketMQConfigBeanPostProcessor(); + } + + @Bean(RocketMQMessageConverter.DEFAULT_NAME) + @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME }) + public CompositeMessageConverter rocketMQMessageConverter() { + return new RocketMQMessageConverter().getMessageConverter(); + } + + @Bean + @ConditionalOnEnabledHealthIndicator("rocketmq") + @ConditionalOnClass(name = "org.springframework.boot.actuate.health.HealthIndicator") + public RocketMQBinderHealthIndicator rocketMQBinderHealthIndicator() { + return new RocketMQBinderHealthIndicator(); + } + + @Bean + public RocketMQTopicProvisioner rocketMQTopicProvisioner() { + return new RocketMQTopicProvisioner(); + } + + @Bean + public RocketMQMessageChannelBinder rocketMQMessageChannelBinder( + RocketMQTopicProvisioner provisioningProvider) { + return new RocketMQMessageChannelBinder(rocketBinderConfigurationProperties, + extendedBindingProperties, provisioningProvider); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java new file mode 100644 index 000000000..e83a6a172 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.contants; + +import org.apache.rocketmq.common.message.MessageConst; + +import static org.apache.rocketmq.spring.support.RocketMQHeaders.PREFIX; + +/** + * @author zkzlx + */ +public class RocketMQConst extends MessageConst { + + /** + * Header key for RocketMQ Transactional Args. + */ + public static final String ROCKET_TRANSACTIONAL_ARG = "TRANSACTIONAL_ARG"; + + /** + * Default NameServer value. + */ + public static final String DEFAULT_NAME_SERVER = "127.0.0.1:9876"; + + /** + * Default group for SCS RocketMQ Binder. + */ + public static final String DEFAULT_GROUP = PREFIX + "binder_default_group_name"; + + /** + * RocketMQ re-consume times. + */ + public static final String ROCKETMQ_RECONSUME_TIMES = PREFIX + "RECONSUME_TIMES"; + + public static final String USER_TRANSACTIONAL_ARGS = "TRANSACTIONAL_ARGS"; + + /** + * It is mainly provided for conversion between rocketMq-message and Spring-message, + * and parameters are passed through HEADERS. + */ + public static class Headers { + public static final String KEYS = MessageConst.PROPERTY_KEYS; + public static final String TAGS = MessageConst.PROPERTY_TAGS; + public static final String TOPIC = "MQ_TOPIC"; + /** + * The ID of the message. + */ + public static final String MESSAGE_ID = "MQ_MESSAGE_ID"; + /** + * The timestamp that the message producer invokes the message sending API. + */ + public static final String BORN_TIMESTAMP = "MQ_BORN_TIMESTAMP"; + /** + * The IP and port number of the message producer + */ + public static final String BORN_HOST = "MQ_BORN_HOST"; + + /** + * Message flag, MQ is not processed and is available for use by applications. + */ + public static final String FLAG = "MQ_FLAG"; + /** + * Message consumption queue ID + */ + public static final String QUEUE_ID = "MQ_QUEUE_ID"; + /** + * Message system Flag, such as whether or not to compress, whether or not to + * transactional messages. + */ + public static final String SYS_FLAG = "MQ_SYS_FLAG"; + /** + * The transaction ID of the transaction message. + */ + public static final String TRANSACTION_ID = "MQ_TRANSACTION_ID"; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java new file mode 100644 index 000000000..58f17c6ef --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.convert; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.messaging.converter.ByteArrayMessageConverter; +import org.springframework.messaging.converter.CompositeMessageConverter; +import org.springframework.messaging.converter.MappingJackson2MessageConverter; +import org.springframework.messaging.converter.MessageConverter; +import org.springframework.messaging.converter.StringMessageConverter; +import org.springframework.util.ClassUtils; + +/** + * The default message converter of rocketMq,its bean name is {@link #DEFAULT_NAME} + * @author zkzlx + */ +public class RocketMQMessageConverter { + + public static final String DEFAULT_NAME = "rocketMQMessageConverter"; + + private static final boolean JACKSON_PRESENT; + private static final boolean FASTJSON_PRESENT; + + static { + ClassLoader classLoader = RocketMQMessageConverter.class.getClassLoader(); + JACKSON_PRESENT = ClassUtils + .isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) + && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", + classLoader); + FASTJSON_PRESENT = ClassUtils.isPresent("com.alibaba.fastjson.JSON", classLoader) + && ClassUtils.isPresent( + "com.alibaba.fastjson.support.config.FastJsonConfig", + classLoader); + } + + private CompositeMessageConverter messageConverter; + + public RocketMQMessageConverter() { + List messageConverters = new ArrayList<>(); + ByteArrayMessageConverter byteArrayMessageConverter = new ByteArrayMessageConverter(); + byteArrayMessageConverter.setContentTypeResolver(null); + messageConverters.add(byteArrayMessageConverter); + messageConverters.add(new StringMessageConverter()); + if (JACKSON_PRESENT) { + messageConverters.add(new MappingJackson2MessageConverter()); + } + if (FASTJSON_PRESENT) { + try { + messageConverters.add((MessageConverter) ClassUtils.forName( + "com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter", + ClassUtils.getDefaultClassLoader()).newInstance()); + } + catch (ClassNotFoundException | IllegalAccessException + | InstantiationException ignored) { + // ignore this exception + } + } + messageConverter = new CompositeMessageConverter(messageConverters); + } + + public CompositeMessageConverter getMessageConverter() { + return messageConverter; + } + + public void setMessageConverter(CompositeMessageConverter messageConverter) { + this.messageConverter = messageConverter; + } +} \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java new file mode 100644 index 000000000..9afc94821 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.custom; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler; +import org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import org.apache.rocketmq.client.consumer.listener.MessageListener; +import org.apache.rocketmq.client.hook.CheckForbiddenHook; +import org.apache.rocketmq.client.hook.SendMessageHook; +import org.apache.rocketmq.client.producer.MessageQueueSelector; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.TransactionListener; + +import org.springframework.messaging.converter.CompositeMessageConverter; +import org.springframework.util.StringUtils; + +/** + * Gets the beans configured in the configuration file + * + * @author junboXiang + */ +public final class RocketMQBeanContainerCache { + + private static final Class[] CLASSES = new Class[] { + CompositeMessageConverter.class, AllocateMessageQueueStrategy.class, + MessageQueueSelector.class, MessageListener.class, TransactionListener.class, + SendCallback.class, CheckForbiddenHook.class, SendMessageHook.class, + ErrorAcknowledgeHandler.class }; + + private static final Map BEANS_CACHE = new ConcurrentHashMap<>(); + + static void putBean(String beanName, Object beanObj) { + BEANS_CACHE.put(beanName, beanObj); + } + + static Class[] getClassAry() { + return CLASSES; + } + + public static T getBean(String beanName, Class clazz) { + return getBean(beanName, clazz, null); + } + + public static T getBean(String beanName, Class clazz, T defaultObj) { + if (StringUtils.isEmpty(beanName)) { + return defaultObj; + } + Object obj = BEANS_CACHE.get(beanName); + if (null == obj) { + return defaultObj; + } + if (clazz.isAssignableFrom(obj.getClass())) { + return (T) obj; + } + return defaultObj; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java new file mode 100644 index 000000000..30bd64328 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.custom; + +import java.util.stream.Stream; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; + +/** + * find RocketMQ bean by annotations + * + * @author junboXiang + * + */ +public class RocketMQConfigBeanPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + Stream.of(RocketMQBeanContainerCache.getClassAry()).forEach(clazz -> { + if (clazz.isAssignableFrom(bean.getClass())) { + RocketMQBeanContainerCache.putBean(beanName, bean); + } + }); + return bean; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java new file mode 100644 index 000000000..fcf6de804 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.extend; + +import org.springframework.integration.acks.AcknowledgmentCallback.Status; +import org.springframework.messaging.Message; + +/** + * @author zkzlx + */ +public interface ErrorAcknowledgeHandler { + + /** + * Ack state handling, including receive, reject, and retry, when a consumption + * exception occurs. + * @param message + * @return see {@link Status} + */ + Status handler(Message message); + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java new file mode 100644 index 000000000..876249581 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java @@ -0,0 +1,156 @@ +/* + * 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.stream.binder.rocketmq.integration.inbound; + +import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; +import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy; +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; +import org.apache.rocketmq.remoting.RPCHook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Extended function related to producer . eg:initial + * + * @author zkzlx + */ +public final class RocketMQConsumerFactory { + + private final static Logger log = LoggerFactory + .getLogger(RocketMQConsumerFactory.class); + + public static DefaultMQPushConsumer initPushConsumer( + ExtendedConsumerProperties extendedConsumerProperties) { + RocketMQConsumerProperties consumerProperties = extendedConsumerProperties + .getExtension(); + Assert.notNull(consumerProperties.getGroup(), + "Property 'group' is required - consumerGroup"); + Assert.notNull(consumerProperties.getNameServer(), + "Property 'nameServer' is required"); + AllocateMessageQueueStrategy allocateMessageQueueStrategy = RocketMQBeanContainerCache + .getBean(consumerProperties.getAllocateMessageQueueStrategy(), + AllocateMessageQueueStrategy.class, + new AllocateMessageQueueAveragely()); + RPCHook rpcHook = null; + if (!StringUtils.isEmpty(consumerProperties.getAccessKey()) + && !StringUtils.isEmpty(consumerProperties.getSecretKey())) { + rpcHook = new AclClientRPCHook( + new SessionCredentials(consumerProperties.getAccessKey(), + consumerProperties.getSecretKey())); + } + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer( + consumerProperties.getGroup(), rpcHook, allocateMessageQueueStrategy, + consumerProperties.getEnableMsgTrace(), + consumerProperties.getCustomizedTraceTopic()); + consumer.setVipChannelEnabled( + null == rpcHook && consumerProperties.getVipChannelEnabled()); + consumer.setInstanceName( + RocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup())); + consumer.setNamespace(consumerProperties.getNamespace()); + consumer.setNamesrvAddr(consumerProperties.getNameServer()); + consumer.setMessageModel(getMessageModel(consumerProperties.getMessageModel())); + consumer.setUseTLS(consumerProperties.getUseTLS()); + consumer.setPullTimeDelayMillsWhenException( + consumerProperties.getPullTimeDelayMillsWhenException()); + consumer.setPullBatchSize(consumerProperties.getPullBatchSize()); + consumer.setConsumeFromWhere(consumerProperties.getConsumeFromWhere()); + consumer.setHeartbeatBrokerInterval( + consumerProperties.getHeartbeatBrokerInterval()); + consumer.setPersistConsumerOffsetInterval( + consumerProperties.getPersistConsumerOffsetInterval()); + consumer.setPullInterval(consumerProperties.getPush().getPullInterval()); + consumer.setConsumeThreadMin(extendedConsumerProperties.getConcurrency()); + consumer.setConsumeThreadMax(extendedConsumerProperties.getConcurrency()); + return consumer; + } + + /** + * todo Compatible with versions less than 4.6 ? + * @return + */ + public static DefaultLitePullConsumer initPullConsumer( + ExtendedConsumerProperties extendedConsumerProperties) { + RocketMQConsumerProperties consumerProperties = extendedConsumerProperties + .getExtension(); + Assert.notNull(consumerProperties.getGroup(), + "Property 'group' is required - consumerGroup"); + Assert.notNull(consumerProperties.getNameServer(), + "Property 'nameServer' is required"); + AllocateMessageQueueStrategy allocateMessageQueueStrategy = RocketMQBeanContainerCache + .getBean(consumerProperties.getAllocateMessageQueueStrategy(), + AllocateMessageQueueStrategy.class, + new AllocateMessageQueueAveragely()); + + RPCHook rpcHook = null; + if (!StringUtils.isEmpty(consumerProperties.getAccessKey()) + && !StringUtils.isEmpty(consumerProperties.getSecretKey())) { + rpcHook = new AclClientRPCHook( + new SessionCredentials(consumerProperties.getAccessKey(), + consumerProperties.getSecretKey())); + } + + DefaultLitePullConsumer consumer = new DefaultLitePullConsumer( + consumerProperties.getNamespace(), consumerProperties.getGroup(), + rpcHook); + consumer.setVipChannelEnabled( + null == rpcHook && consumerProperties.getVipChannelEnabled()); + consumer.setInstanceName( + RocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup())); + consumer.setAllocateMessageQueueStrategy(allocateMessageQueueStrategy); + consumer.setNamesrvAddr(consumerProperties.getNameServer()); + consumer.setMessageModel(getMessageModel(consumerProperties.getMessageModel())); + consumer.setUseTLS(consumerProperties.getUseTLS()); + consumer.setPullTimeDelayMillsWhenException( + consumerProperties.getPullTimeDelayMillsWhenException()); + consumer.setConsumerTimeoutMillisWhenSuspend( + consumerProperties.getPull().getConsumerTimeoutMillisWhenSuspend()); + consumer.setPullBatchSize(consumerProperties.getPullBatchSize()); + consumer.setConsumeFromWhere(consumerProperties.getConsumeFromWhere()); + consumer.setHeartbeatBrokerInterval( + consumerProperties.getHeartbeatBrokerInterval()); + consumer.setPersistConsumerOffsetInterval( + consumerProperties.getPersistConsumerOffsetInterval()); + consumer.setPollTimeoutMillis( + consumerProperties.getPull().getPollTimeoutMillis()); + consumer.setPullThreadNums(extendedConsumerProperties.getConcurrency()); + // The internal queues are cached by a maximum of 1000 + consumer.setPullThresholdForAll(extendedConsumerProperties.getExtension() + .getPull().getPullThresholdForAll()); + return consumer; + } + + private static MessageModel getMessageModel(String messageModel) { + for (MessageModel model : MessageModel.values()) { + if (model.getModeCN().equalsIgnoreCase(messageModel)) { + return model; + } + } + return MessageModel.CLUSTERING; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java new file mode 100644 index 000000000..d0aec5523 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java @@ -0,0 +1,228 @@ +/* + * 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.stream.binder.rocketmq.integration.inbound; + +import java.util.List; +import java.util.function.Supplier; + +import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; +import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; +import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport; +import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; +import org.apache.rocketmq.common.message.MessageExt; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; +import org.springframework.integration.context.OrderlyShutdownCapable; +import org.springframework.integration.endpoint.MessageProducerSupport; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessagingException; +import org.springframework.retry.RecoveryCallback; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryListener; +import org.springframework.retry.support.RetryTemplate; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * TODO Describe what it does + * @author Jim + */ +public class RocketMQInboundChannelAdapter extends MessageProducerSupport + implements OrderlyShutdownCapable { + + private static final Logger log = LoggerFactory + .getLogger(RocketMQInboundChannelAdapter.class); + + private RetryTemplate retryTemplate; + private RecoveryCallback recoveryCallback; + private DefaultMQPushConsumer pushConsumer; + + private final String topic; + private final ExtendedConsumerProperties extendedConsumerProperties; + + public RocketMQInboundChannelAdapter(String topic, + ExtendedConsumerProperties extendedConsumerProperties) { + this.topic = topic; + this.extendedConsumerProperties = extendedConsumerProperties; + } + + @Override + protected void onInit() { + if (extendedConsumerProperties.getExtension() == null + || !extendedConsumerProperties.getExtension().getEnabled()) { + return; + } + Instrumentation instrumentation = new Instrumentation(topic, this); + try { + super.onInit(); + if (this.retryTemplate != null) { + Assert.state(getErrorChannel() == null, + "Cannot have an 'errorChannel' property when a 'RetryTemplate' is " + + "provided; use an 'ErrorMessageSendingRecoverer' in the 'recoveryCallback' property to " + + "send an error message when retries are exhausted"); + this.retryTemplate.registerListener(new RetryListener() { + @Override + public boolean open(RetryContext context, + RetryCallback callback) { + return true; + } + + @Override + public void close(RetryContext context, + RetryCallback callback, Throwable throwable) { + } + + @Override + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { + } + }); + } + pushConsumer = RocketMQConsumerFactory + .initPushConsumer(extendedConsumerProperties); + // prepare register consumer message listener,the next step is to be + // compatible with a custom MessageListener. + if (extendedConsumerProperties.getExtension().getPush().getOrderly()) { + pushConsumer.registerMessageListener((MessageListenerOrderly) (msgs, + context) -> RocketMQInboundChannelAdapter.this + .consumeMessage(msgs, () -> { + context.setSuspendCurrentQueueTimeMillis( + extendedConsumerProperties.getExtension() + .getPush() + .getSuspendCurrentQueueTimeMillis()); + return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; + }, () -> ConsumeOrderlyStatus.SUCCESS)); + } + else { + pushConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, + context) -> RocketMQInboundChannelAdapter.this + .consumeMessage(msgs, () -> { + context.setDelayLevelWhenNextConsume( + extendedConsumerProperties.getExtension() + .getPush() + .getDelayLevelWhenNextConsume()); + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + }, () -> ConsumeConcurrentlyStatus.CONSUME_SUCCESS)); + } + instrumentation.markStartedSuccessfully(); + } + catch (Exception e) { + instrumentation.markStartFailed(e); + log.error("DefaultMQPushConsumer init failed, Caused by " + e.getMessage()); + throw new MessagingException(MessageBuilder.withPayload( + "DefaultMQPushConsumer init failed, Caused by " + e.getMessage()) + .build(), e); + } + finally { + InstrumentationManager.addHealthInstrumentation(instrumentation); + } + } + + /** + * The actual execution of a user-defined input consumption service method. + * @param messageExtList rocket mq message list + * @param failSupplier {@link ConsumeConcurrentlyStatus} or + * {@link ConsumeOrderlyStatus} + * @param sucSupplier {@link ConsumeConcurrentlyStatus} or + * {@link ConsumeOrderlyStatus} + * @param + * @return + */ + private R consumeMessage(List messageExtList, + Supplier failSupplier, Supplier sucSupplier) { + if (CollectionUtils.isEmpty(messageExtList)) { + throw new MessagingException( + "DefaultMQPushConsumer consuming failed, Caused by messageExtList is empty"); + } + for (MessageExt messageExt : messageExtList) { + try { + Message message = RocketMQMessageConverterSupport + .convertMessage2Spring(messageExt); + if (this.retryTemplate != null) { + this.retryTemplate.execute(context -> { + this.sendMessage(message); + return message; + }, this.recoveryCallback); + } + else { + this.sendMessage(message); + } + } + catch (Exception e) { + log.warn("consume message failed. messageExt:{}", messageExt, e); + return failSupplier.get(); + } + } + return sucSupplier.get(); + } + + @Override + protected void doStart() { + if (extendedConsumerProperties.getExtension() == null + || !extendedConsumerProperties.getExtension().getEnabled()) { + return; + } + try { + pushConsumer.subscribe(topic, RocketMQUtils.getMessageSelector( + extendedConsumerProperties.getExtension().getSubscription())); + pushConsumer.start(); + } + catch (Exception e) { + log.error("DefaultMQPushConsumer init failed, Caused by " + e.getMessage()); + throw new MessagingException(MessageBuilder.withPayload( + "DefaultMQPushConsumer init failed, Caused by " + e.getMessage()) + .build(), e); + } + } + + @Override + protected void doStop() { + if (pushConsumer != null) { + pushConsumer.shutdown(); + } + } + + public void setRetryTemplate(RetryTemplate retryTemplate) { + this.retryTemplate = retryTemplate; + } + + public void setRecoveryCallback(RecoveryCallback recoveryCallback) { + this.recoveryCallback = recoveryCallback; + } + + @Override + public int beforeShutdown() { + this.stop(); + return 0; + } + + @Override + public int afterShutdown() { + return 0; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java new file mode 100644 index 000000000..3296a128e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull; + +import com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler; + +import org.springframework.integration.acks.AcknowledgmentCallback.Status; +import org.springframework.messaging.Message; + +/** + * By default, if consumption fails, the corresponding MessageQueue will always be + * retried, that is, the consumption of other messages in the MessageQueue will be + * blocked. + * + * @author zkzlx + */ +public class DefaultErrorAcknowledgeHandler implements ErrorAcknowledgeHandler { + /** + * Ack state handling, including receive, reject, and retry, when a consumption + * exception occurs. + * + * @param message + * @return see {@link Status} + */ + @Override + public Status handler(Message message) { + return Status.REQUEUE; + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java new file mode 100644 index 000000000..f617dd097 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull; + +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.impl.consumer.AssignedMessageQueue; +import org.apache.rocketmq.client.impl.consumer.ProcessQueue; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.integration.acks.AcknowledgmentCallback; +import org.springframework.util.Assert; + +/** + * A pollable {@link org.springframework.integration.core.MessageSource} for RocketMQ. + * @author zkzlx + */ +public class RocketMQAckCallback implements AcknowledgmentCallback { + private final static Logger log = LoggerFactory.getLogger(RocketMQAckCallback.class); + + private boolean acknowledged; + private boolean autoAckEnabled = true; + private MessageExt messageExt; + private AssignedMessageQueue assignedMessageQueue; + private DefaultLitePullConsumer consumer; + private final MessageQueue messageQueue; + + public RocketMQAckCallback(DefaultLitePullConsumer consumer, + AssignedMessageQueue assignedMessageQueue, MessageQueue messageQueue, + MessageExt messageExt) { + this.messageExt = messageExt; + this.consumer = consumer; + this.assignedMessageQueue = assignedMessageQueue; + this.messageQueue = messageQueue; + } + + @Override + public boolean isAcknowledged() { + return this.acknowledged; + } + + @Override + public void noAutoAck() { + this.autoAckEnabled = false; + } + + @Override + public boolean isAutoAck() { + return this.autoAckEnabled; + } + + @Override + public void acknowledge(Status status) { + Assert.notNull(status, "'status' cannot be null"); + if (this.acknowledged) { + throw new IllegalStateException("Already acknowledged"); + } + synchronized (messageQueue) { + try { + long offset = messageExt.getQueueOffset(); + switch (status) { + case REJECT: + case ACCEPT: + long consumerOffset = assignedMessageQueue + .getConsumerOffset(messageQueue); + if (consumerOffset != -1) { + ProcessQueue processQueue = assignedMessageQueue + .getProcessQueue(messageQueue); + if (processQueue != null && !processQueue.isDropped()) { + consumer.getOffsetStore().updateOffset(messageQueue, + consumerOffset, false); + } + } + if (consumer.getMessageModel() == MessageModel.BROADCASTING) { + consumer.getOffsetStore().persist(messageQueue); + } + break; + case REQUEUE: + consumer.seek(messageQueue, offset); + break; + default: + break; + } + } + catch (MQClientException e) { + throw new IllegalStateException(e); + } + finally { + this.acknowledged = true; + } + } + } + +} \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java new file mode 100644 index 000000000..2ca91384b --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java @@ -0,0 +1,161 @@ +/* + * 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.stream.binder.rocketmq.integration.inbound.pull; + +import java.lang.reflect.Field; +import java.util.List; + +import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQConsumerFactory; +import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; +import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; +import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport; +import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils; +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; +import org.apache.rocketmq.client.consumer.MessageSelector; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.impl.consumer.AssignedMessageQueue; +import org.apache.rocketmq.client.impl.consumer.DefaultLitePullConsumerImpl; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.common.message.MessageQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.beans.factory.DisposableBean; +import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; +import org.springframework.context.Lifecycle; +import org.springframework.integration.IntegrationMessageHeaderAccessor; +import org.springframework.integration.endpoint.AbstractMessageSource; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ReflectionUtils; + +/** + * @author Jim + */ +public class RocketMQMessageSource extends AbstractMessageSource + implements DisposableBean, Lifecycle { + + private final static Logger log = LoggerFactory + .getLogger(RocketMQMessageSource.class); + + private DefaultLitePullConsumer consumer; + private AssignedMessageQueue assignedMessageQueue; + private volatile boolean running; + + private final String topic; + private final MessageSelector messageSelector; + private final ExtendedConsumerProperties extendedConsumerProperties; + + public RocketMQMessageSource(String name, + ExtendedConsumerProperties extendedConsumerProperties) { + this.topic = name; + this.messageSelector = RocketMQUtils.getMessageSelector( + extendedConsumerProperties.getExtension().getSubscription()); + this.extendedConsumerProperties = extendedConsumerProperties; + + } + + @Override + public synchronized void start() { + Instrumentation instrumentation = new Instrumentation(topic, this); + try { + if (this.isRunning()) { + throw new IllegalStateException( + "pull consumer already running. " + this.toString()); + } + this.consumer = RocketMQConsumerFactory + .initPullConsumer(extendedConsumerProperties); + // This parameter must be 1, otherwise doReceive cannot be handled singly. + this.consumer.setPullBatchSize(1); + this.consumer.subscribe(topic, messageSelector); + this.consumer.setAutoCommit(false); + this.assignedMessageQueue = acquireAssignedMessageQueue(this.consumer); + this.consumer.start(); + instrumentation.markStartedSuccessfully(); + } + catch (MQClientException e) { + instrumentation.markStartFailed(e); + log.error("DefaultMQPullConsumer startup error: " + e.getMessage(), e); + } + finally { + InstrumentationManager.addHealthInstrumentation(instrumentation); + } + this.running = true; + } + + private AssignedMessageQueue acquireAssignedMessageQueue( + DefaultLitePullConsumer consumer) { + Field field = ReflectionUtils.findField(DefaultLitePullConsumer.class, + "defaultLitePullConsumerImpl"); + assert field != null; + field.setAccessible(true); + DefaultLitePullConsumerImpl defaultLitePullConsumerImpl = (DefaultLitePullConsumerImpl) ReflectionUtils + .getField(field, consumer); + + field = ReflectionUtils.findField(DefaultLitePullConsumerImpl.class, + "assignedMessageQueue"); + assert field != null; + field.setAccessible(true); + return (AssignedMessageQueue) ReflectionUtils.getField(field, + defaultLitePullConsumerImpl); + } + + @Override + public synchronized void stop() { + if (this.isRunning() && null != consumer) { + consumer.unsubscribe(topic); + consumer.shutdown(); + this.running = false; + } + } + + @Override + public synchronized boolean isRunning() { + return running; + } + + @Override + protected synchronized Object doReceive() { + List messageExtList = consumer.poll(); + if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) { + return null; + } + MessageExt messageExt = messageExtList.get(0); + MessageQueue messageQueue = null; + for (MessageQueue queue : assignedMessageQueue.getAssignedMessageQueues()) { + if (queue.getQueueId() == messageExt.getQueueId()) { + messageQueue = queue; + break; + } + } + Message message = RocketMQMessageConverterSupport + .convertMessage2Spring(messageExtList.get(0)); + return MessageBuilder.fromMessage(message) + .setHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK, + new RocketMQAckCallback(this.consumer, assignedMessageQueue, + messageQueue, messageExt)) + .build(); + } + + @Override + public String getComponentType() { + return "rocketmq:message-source"; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java new file mode 100644 index 000000000..7017ba46e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java @@ -0,0 +1,131 @@ +/* + * 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.stream.binder.rocketmq.integration.outbound; + +import java.lang.reflect.Field; + +import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties; +import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.hook.CheckForbiddenHook; +import org.apache.rocketmq.client.hook.SendMessageHook; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; +import org.apache.rocketmq.client.trace.TraceDispatcher; +import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.remoting.RPCHook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Extended function related to producer . eg:initial + * + * @author zkzlx + */ +public final class RocketMQProduceFactory { + + private final static Logger log = LoggerFactory + .getLogger(RocketMQProduceFactory.class); + + /** + * init for the producer,including convert producer params. + * @return + */ + public static DefaultMQProducer initRocketMQProducer(String topic, + RocketMQProducerProperties producerProperties) { + Assert.notNull(producerProperties.getGroup(), + "Property 'group' is required - producerGroup"); + Assert.notNull(producerProperties.getNameServer(), + "Property 'nameServer' is required"); + + RPCHook rpcHook = null; + if (!StringUtils.isEmpty(producerProperties.getAccessKey()) + && !StringUtils.isEmpty(producerProperties.getSecretKey())) { + rpcHook = new AclClientRPCHook( + new SessionCredentials(producerProperties.getAccessKey(), + producerProperties.getSecretKey())); + } + DefaultMQProducer producer; + if (RocketMQProducerProperties.ProducerType.Trans + .equalsName(producerProperties.getProducerType())) { + producer = new TransactionMQProducer(producerProperties.getNamespace(), + producerProperties.getGroup(), rpcHook); + if (producerProperties.getEnableMsgTrace()) { + try { + AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher( + producerProperties.getGroup(), TraceDispatcher.Type.PRODUCE, + producerProperties.getCustomizedTraceTopic(), rpcHook); + dispatcher.setHostProducer(producer.getDefaultMQProducerImpl()); + Field field = DefaultMQProducer.class + .getDeclaredField("traceDispatcher"); + field.setAccessible(true); + field.set(producer, dispatcher); + producer.getDefaultMQProducerImpl().registerSendMessageHook( + new SendMessageTraceHookImpl(dispatcher)); + } + catch (Throwable e) { + log.error( + "system mq-trace hook init failed ,maybe can't send msg trace data"); + } + } + } + else { + producer = new DefaultMQProducer(producerProperties.getNamespace(), + producerProperties.getGroup(), rpcHook, + producerProperties.getEnableMsgTrace(), + producerProperties.getCustomizedTraceTopic()); + } + + producer.setVipChannelEnabled( + null == rpcHook && producerProperties.getVipChannelEnabled()); + producer.setInstanceName( + RocketMQUtils.getInstanceName(rpcHook, topic + "|" + UtilAll.getPid())); + producer.setNamesrvAddr(producerProperties.getNameServer()); + producer.setSendMsgTimeout(producerProperties.getSendMsgTimeout()); + producer.setRetryTimesWhenSendFailed( + producerProperties.getRetryTimesWhenSendFailed()); + producer.setRetryTimesWhenSendAsyncFailed( + producerProperties.getRetryTimesWhenSendAsyncFailed()); + producer.setCompressMsgBodyOverHowmuch( + producerProperties.getCompressMsgBodyThreshold()); + producer.setRetryAnotherBrokerWhenNotStoreOK( + producerProperties.getRetryAnotherBroker()); + producer.setMaxMessageSize(producerProperties.getMaxMessageSize()); + producer.setUseTLS(producerProperties.getUseTLS()); + CheckForbiddenHook checkForbiddenHook = RocketMQBeanContainerCache.getBean( + producerProperties.getCheckForbiddenHook(), CheckForbiddenHook.class); + if (null != checkForbiddenHook) { + producer.getDefaultMQProducerImpl() + .registerCheckForbiddenHook(checkForbiddenHook); + } + SendMessageHook sendMessageHook = RocketMQBeanContainerCache + .getBean(producerProperties.getSendMessageHook(), SendMessageHook.class); + if (null != sendMessageHook) { + producer.getDefaultMQProducerImpl().registerSendMessageHook(sendMessageHook); + } + + return producer; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java new file mode 100644 index 000000000..66b58f797 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java @@ -0,0 +1,286 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.integration.outbound; + +import java.util.List; + +import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; +import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache; +import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; +import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties; +import com.alibaba.cloud.stream.binder.rocketmq.provisioning.selector.PartitionMessageQueueSelector; +import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.MessageQueueSelector; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.SendStatus; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.common.message.MessageQueue; +import org.apache.rocketmq.remoting.exception.RemotingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.stream.binder.ExtendedProducerProperties; +import org.springframework.cloud.stream.binding.MessageConverterConfigurer; +import org.springframework.cloud.stream.binding.MessageConverterConfigurer.PartitioningInterceptor; +import org.springframework.cloud.stream.provisioning.ProducerDestination; +import org.springframework.context.Lifecycle; +import org.springframework.integration.handler.AbstractMessageHandler; +import org.springframework.integration.support.ErrorMessageStrategy; +import org.springframework.integration.support.ErrorMessageUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessagingException; + +/** + * @author Jim + */ +public class RocketMQProducerMessageHandler extends AbstractMessageHandler + implements Lifecycle { + + private final static Logger log = LoggerFactory + .getLogger(RocketMQProducerMessageHandler.class); + + private volatile boolean running = false; + private volatile boolean isTrans = false; + + private ErrorMessageStrategy errorMessageStrategy; + private MessageChannel sendFailureChannel; + private MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor; + private DefaultMQProducer defaultMQProducer; + private MessageQueueSelector messageQueueSelector; + + private final ProducerDestination destination; + private final ExtendedProducerProperties extendedProducerProperties; + private final RocketMQProducerProperties mqProducerProperties; + + public RocketMQProducerMessageHandler(ProducerDestination destination, + ExtendedProducerProperties extendedProducerProperties, + RocketMQProducerProperties mqProducerProperties) { + this.destination = destination; + this.extendedProducerProperties = extendedProducerProperties; + this.mqProducerProperties = mqProducerProperties; + } + + @Override + protected void onInit() { + if (null == mqProducerProperties || !mqProducerProperties.getEnabled()) { + return; + } + super.onInit(); + this.defaultMQProducer = RocketMQProduceFactory + .initRocketMQProducer(destination.getName(), mqProducerProperties); + this.isTrans = defaultMQProducer instanceof TransactionMQProducer; + // Use the default if the partition is on and no customization is available. + this.messageQueueSelector = RocketMQBeanContainerCache.getBean( + mqProducerProperties.getMessageQueueSelector(), + MessageQueueSelector.class, + extendedProducerProperties.isPartitioned() + ? new PartitionMessageQueueSelector() + : null); + } + + @Override + public void start() { + Instrumentation instrumentation = new Instrumentation(destination.getName(), + this); + try { + defaultMQProducer.start(); + // TransactionMQProducer does not currently support custom + // MessageQueueSelector. + if (!isTrans && extendedProducerProperties.isPartitioned()) { + List messageQueues = defaultMQProducer + .fetchPublishMessageQueues(destination.getName()); + if (extendedProducerProperties.getPartitionCount() != messageQueues + .size()) { + logger.info(String.format( + "The partition count of topic '%s' will change from '%s' to '%s'", + destination.getName(), + extendedProducerProperties.getPartitionCount(), + messageQueues.size())); + extendedProducerProperties.setPartitionCount(messageQueues.size()); + // may be npe! + partitioningInterceptor.setPartitionCount( + extendedProducerProperties.getPartitionCount()); + } + } + running = true; + instrumentation.markStartedSuccessfully(); + } + catch (MQClientException | NullPointerException e) { + instrumentation.markStartFailed(e); + log.error("The defaultMQProducer startup failure !!!", e); + } + finally { + InstrumentationManager.addHealthInstrumentation(instrumentation); + } + } + + @Override + public void stop() { + if (running && null != defaultMQProducer) { + defaultMQProducer.shutdown(); + } + running = false; + } + + @Override + public boolean isRunning() { + return running; + } + + @Override + protected void handleMessageInternal(Message message) { + try { + org.apache.rocketmq.common.message.Message mqMessage = RocketMQMessageConverterSupport + .convertMessage2MQ(destination.getName(), message); + SendResult sendResult; + if (defaultMQProducer instanceof TransactionMQProducer) { + TransactionListener transactionListener = RocketMQBeanContainerCache + .getBean(mqProducerProperties.getTransactionListener(), + TransactionListener.class); + if (transactionListener == null) { + throw new MessagingException( + "TransactionMQProducer must have a TransactionMQProducer !!! "); + } + ((TransactionMQProducer) defaultMQProducer) + .setTransactionListener(transactionListener); + log.info("send transaction message :" + mqMessage); + sendResult = defaultMQProducer.sendMessageInTransaction(mqMessage, + message.getHeaders().get(RocketMQConst.USER_TRANSACTIONAL_ARGS)); + } + else { + log.info("send message :" + mqMessage); + sendResult = this.send(mqMessage, this.messageQueueSelector, + message.getHeaders(), message); + } + if (sendResult == null + || !SendStatus.SEND_OK.equals(sendResult.getSendStatus())) { + log.error("message send fail.SendStatus is not OK "); + this.doFail(message, new MessagingException( + "message send fail.SendStatus is not OK.")); + } + } + catch (Exception e) { + log.error("RocketMQ Message hasn't been sent. Caused by " + e.getMessage(), + e); + this.doFail(message, e); + } + } + + private SendResult send(org.apache.rocketmq.common.message.Message mqMessage, + MessageQueueSelector selector, Object args, Message message) + throws RemotingException, MQClientException, InterruptedException, + MQBrokerException { + SendResult sendResult = new SendResult(); + sendResult.setSendStatus(SendStatus.SEND_OK); + if (RocketMQProducerProperties.SendType.OneWay + .equalsName(mqProducerProperties.getSendType())) { + if (null != selector) { + defaultMQProducer.sendOneway(mqMessage, selector, args); + } + else { + defaultMQProducer.sendOneway(mqMessage); + } + return sendResult; + } + if (RocketMQProducerProperties.SendType.Sync + .equalsName(mqProducerProperties.getSendType())) { + if (null != selector) { + return defaultMQProducer.send(mqMessage, selector, args); + } + return defaultMQProducer.send(mqMessage); + } + if (RocketMQProducerProperties.SendType.Async + .equalsName(mqProducerProperties.getSendType())) { + if (null != selector) { + defaultMQProducer.send(mqMessage, selector, args, + this.getSendCallback(message)); + } + else { + defaultMQProducer.send(mqMessage, this.getSendCallback(message)); + } + return sendResult; + } + throw new MessagingException( + "message hasn't been sent,cause by : the SendType must be in this values[OneWay, Async, Sync]"); + } + + /** + * https://github.com/alibaba/spring-cloud-alibaba/issues/1408 + * @param message + * @return + */ + private SendCallback getSendCallback(Message message) { + SendCallback sendCallback = RocketMQBeanContainerCache + .getBean(mqProducerProperties.getSendCallBack(), SendCallback.class); + if (null == sendCallback) { + sendCallback = new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + } + + @Override + public void onException(Throwable e) { + RocketMQProducerMessageHandler.this.doFail(message, e); + } + }; + } + return sendCallback; + } + + private void doFail(Message message, Throwable e) { + if (getSendFailureChannel() != null) { + getSendFailureChannel().send(getErrorMessageStrategy().buildErrorMessage(e, + ErrorMessageUtils.getAttributeAccessor(message, message))); + } + else { + throw new MessagingException(message, e); + } + } + + public MessageChannel getSendFailureChannel() { + return sendFailureChannel; + } + + public void setSendFailureChannel(MessageChannel sendFailureChannel) { + this.sendFailureChannel = sendFailureChannel; + } + + public ErrorMessageStrategy getErrorMessageStrategy() { + return errorMessageStrategy; + } + + public void setErrorMessageStrategy(ErrorMessageStrategy errorMessageStrategy) { + this.errorMessageStrategy = errorMessageStrategy; + } + + public PartitioningInterceptor getPartitioningInterceptor() { + return partitioningInterceptor; + } + + public RocketMQProducerMessageHandler setPartitioningInterceptor( + PartitioningInterceptor partitioningInterceptor) { + this.partitioningInterceptor = partitioningInterceptor; + return this; + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java new file mode 100644 index 000000000..00e7d30dd --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.properties; + +import java.io.Serializable; + +import org.apache.rocketmq.client.AccessChannel; +import org.apache.rocketmq.client.impl.factory.MQClientInstance; +import org.apache.rocketmq.remoting.netty.TlsSystemConfig; + +/** + * @author zkzlx + */ +public class RocketMQCommonProperties implements Serializable { + private static final long serialVersionUID = -6724870154343284715L; + + private boolean enabled = true; + + private String nameServer; + + /** + * The property of "access-key". + */ + private String accessKey; + + /** + * The property of "secret-key". + */ + private String secretKey; + /** + * Consumers of the same role is required to have exactly same subscriptions and + * consumerGroup to correctly achieve load balance. It's required and needs to be + * globally unique. + *

+ * Producer group conceptually aggregates all producer instances of exactly same role, + * which is particularly important when transactional messages are involved. + *

+ *

+ * For non-transactional messages, it does not matter as long as it's unique per + * process. + *

+ *

+ * See here for further + * discussion. + */ + private String group; + + private String namespace; + private String accessChannel = AccessChannel.LOCAL.name(); + /** + * Pulling topic information interval from the named server. + * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask + * updateTopicRouteInfoFromNameServer. + */ + private int pollNameServerInterval = 1000 * 30; + /** + * Heartbeat interval in microseconds with message broker. + * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask + * sendHeartbeatToAllBroker . + */ + private int heartbeatBrokerInterval = 1000 * 30; + /** + * Offset persistent interval for consumer. + * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask + * sendHeartbeatToAllBroker . + */ + private int persistConsumerOffsetInterval = 1000 * 5; + + private boolean vipChannelEnabled = false; + + private boolean useTLS = TlsSystemConfig.tlsEnable; + + private boolean enableMsgTrace = true; + private String customizedTraceTopic; + + public boolean getEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getNameServer() { + return nameServer; + } + + public void setNameServer(String nameServer) { + this.nameServer = nameServer; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getAccessChannel() { + return accessChannel; + } + + public void setAccessChannel(String accessChannel) { + this.accessChannel = accessChannel; + } + + public int getPollNameServerInterval() { + return pollNameServerInterval; + } + + public void setPollNameServerInterval(int pollNameServerInterval) { + this.pollNameServerInterval = pollNameServerInterval; + } + + public int getHeartbeatBrokerInterval() { + return heartbeatBrokerInterval; + } + + public void setHeartbeatBrokerInterval(int heartbeatBrokerInterval) { + this.heartbeatBrokerInterval = heartbeatBrokerInterval; + } + + public int getPersistConsumerOffsetInterval() { + return persistConsumerOffsetInterval; + } + + public void setPersistConsumerOffsetInterval(int persistConsumerOffsetInterval) { + this.persistConsumerOffsetInterval = persistConsumerOffsetInterval; + } + + public boolean getVipChannelEnabled() { + return vipChannelEnabled; + } + + public void setVipChannelEnabled(boolean vipChannelEnabled) { + this.vipChannelEnabled = vipChannelEnabled; + } + + public boolean getUseTLS() { + return useTLS; + } + + public void setUseTLS(boolean useTLS) { + this.useTLS = useTLS; + } + + public boolean getEnableMsgTrace() { + return enableMsgTrace; + } + + public void setEnableMsgTrace(boolean enableMsgTrace) { + this.enableMsgTrace = enableMsgTrace; + } + + public String getCustomizedTraceTopic() { + return customizedTraceTopic; + } + + public void setCustomizedTraceTopic(String customizedTraceTopic) { + this.customizedTraceTopic = customizedTraceTopic; + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java new file mode 100644 index 000000000..99a1a36fb --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.properties; + +import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; + +/** + * Container object for RocketMQ specific extended producer and consumer binding + * properties. + * + * @author Jim + */ +public class RocketMQSpecificPropertiesProvider + implements BinderSpecificPropertiesProvider { + + /** + * Consumer specific binding properties. @see {@link RocketMQConsumerProperties}. + */ + private RocketMQConsumerProperties consumer = new RocketMQConsumerProperties(); + + /** + * Producer specific binding properties. @see {@link RocketMQProducerProperties}. + */ + private RocketMQProducerProperties producer = new RocketMQProducerProperties(); + + /** + * @return {@link RocketMQConsumerProperties} Consumer specific binding + * properties. @see {@link RocketMQConsumerProperties}. + */ + @Override + public RocketMQConsumerProperties getConsumer() { + return this.consumer; + } + + public void setConsumer(RocketMQConsumerProperties consumer) { + this.consumer = consumer; + } + + /** + * @return {@link RocketMQProducerProperties} Producer specific binding + * properties. @see {@link RocketMQProducerProperties}. + */ + @Override + public RocketMQProducerProperties getProducer() { + return this.producer; + } + + public void setProducer(RocketMQProducerProperties producer) { + this.producer = producer; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java new file mode 100644 index 000000000..d4b62e5fa --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.support; + +import java.nio.charset.Charset; +import java.util.Map; +import java.util.Objects; + +import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; +import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst.Headers; +import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter; +import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache; +import org.apache.rocketmq.common.message.MessageConst; +import org.apache.rocketmq.common.message.MessageExt; + +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.converter.CompositeMessageConverter; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.util.CollectionUtils; +import org.springframework.util.MimeTypeUtils; +import org.springframework.util.StringUtils; + +/** + * + * @author zkzlx + */ +public class RocketMQMessageConverterSupport { + + private static final CompositeMessageConverter MESSAGE_CONVERTER = RocketMQBeanContainerCache + .getBean(RocketMQMessageConverter.DEFAULT_NAME, + CompositeMessageConverter.class, + new RocketMQMessageConverter().getMessageConverter()); + + public static Message convertMessage2Spring(MessageExt message) { + MessageBuilder messageBuilder = MessageBuilder.withPayload(message.getBody()) + .setHeader(toRocketHeaderKey(Headers.KEYS), message.getKeys()) + .setHeader(toRocketHeaderKey(Headers.TAGS), message.getTags()) + .setHeader(toRocketHeaderKey(Headers.TOPIC), message.getTopic()) + .setHeader(toRocketHeaderKey(Headers.MESSAGE_ID), message.getMsgId()) + .setHeader(toRocketHeaderKey(Headers.BORN_TIMESTAMP), + message.getBornTimestamp()) + .setHeader(toRocketHeaderKey(Headers.BORN_HOST), + message.getBornHostString()) + .setHeader(toRocketHeaderKey(Headers.FLAG), message.getFlag()) + .setHeader(toRocketHeaderKey(Headers.QUEUE_ID), message.getQueueId()) + .setHeader(toRocketHeaderKey(Headers.SYS_FLAG), message.getSysFlag()) + .setHeader(toRocketHeaderKey(Headers.TRANSACTION_ID), + message.getTransactionId()); + addUserProperties(message.getProperties(), messageBuilder); + return messageBuilder.build(); + } + + public static String toRocketHeaderKey(String rawKey) { + return "ROCKET_" + rawKey; + } + + private static void addUserProperties(Map properties, + MessageBuilder messageBuilder) { + if (!CollectionUtils.isEmpty(properties)) { + properties.forEach((key, val) -> { + if (!MessageConst.STRING_HASH_SET.contains(key) + && !MessageHeaders.ID.equals(key) + && !MessageHeaders.TIMESTAMP.equals(key)) { + messageBuilder.setHeader(key, val); + } + }); + } + } + + public static org.apache.rocketmq.common.message.Message convertMessage2MQ( + String destination, Message source) { + Message message = MESSAGE_CONVERTER.toMessage(source.getPayload(), + source.getHeaders()); + assert message != null; + MessageBuilder builder = MessageBuilder.fromMessage(message); + builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN); + message = builder.build(); + return doConvert(destination, message); + } + + private static org.apache.rocketmq.common.message.Message doConvert(String topic, + Message message) { + Charset charset = Charset.defaultCharset(); + Object payloadObj = message.getPayload(); + byte[] payloads; + try { + if (payloadObj instanceof String) { + payloads = ((String) payloadObj).getBytes(charset); + } + else if (payloadObj instanceof byte[]) { + payloads = (byte[]) message.getPayload(); + } + else { + String jsonObj = (String) MESSAGE_CONVERTER.fromMessage(message, + payloadObj.getClass()); + if (null == jsonObj) { + throw new RuntimeException(String.format( + "empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]", + MESSAGE_CONVERTER.getClass(), payloadObj.getClass(), + payloadObj)); + } + payloads = jsonObj.getBytes(charset); + } + } + catch (Exception e) { + throw new RuntimeException("convert to RocketMQ message failed.", e); + } + return getAndWrapMessage(topic, message.getHeaders(), payloads); + } + + private static org.apache.rocketmq.common.message.Message getAndWrapMessage( + String topic, MessageHeaders headers, byte[] payloads) { + if (topic == null || topic.length() < 1) { + return null; + } + if (payloads == null || payloads.length < 1) { + return null; + } + org.apache.rocketmq.common.message.Message rocketMsg = new org.apache.rocketmq.common.message.Message( + topic, payloads); + if (Objects.nonNull(headers) && !headers.isEmpty()) { + Object tag = headers.getOrDefault(Headers.TAGS, + headers.get(toRocketHeaderKey(Headers.TAGS))); + if (!StringUtils.isEmpty(tag)) { + rocketMsg.setTags(String.valueOf(tag)); + } + + Object keys = headers.getOrDefault(Headers.KEYS, + headers.get(toRocketHeaderKey(Headers.KEYS))); + if (!StringUtils.isEmpty(keys)) { + rocketMsg.setKeys(keys.toString()); + } + Object flagObj = headers.getOrDefault(Headers.FLAG, + headers.get(toRocketHeaderKey(Headers.FLAG))); + int flag = 0; + int delayLevel = 0; + try { + flagObj = flagObj == null ? 0 : flagObj; + Object delayLevelObj = headers.getOrDefault( + RocketMQConst.PROPERTY_DELAY_TIME_LEVEL, + headers.get(toRocketHeaderKey( + RocketMQConst.PROPERTY_DELAY_TIME_LEVEL))); + delayLevelObj = delayLevelObj == null ? 0 : delayLevelObj; + delayLevel = Integer.parseInt(String.valueOf(delayLevelObj)); + flag = Integer.parseInt(String.valueOf(flagObj)); + } + catch (Exception ignored) { + } + if (delayLevel > 0) { + rocketMsg.setDelayTimeLevel(delayLevel); + } + rocketMsg.setFlag(flag); + Object waitStoreMsgOkObj = headers + .getOrDefault(RocketMQConst.PROPERTY_WAIT_STORE_MSG_OK, "true"); + rocketMsg.setWaitStoreMsgOK( + Boolean.parseBoolean(String.valueOf(waitStoreMsgOkObj))); + headers.entrySet().stream() + .filter(entry -> !Objects.equals(entry.getKey(), Headers.FLAG)) + .forEach(entry -> { + if (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) { + rocketMsg.putUserProperty(entry.getKey(), + String.valueOf(entry.getValue())); + } + }); + + } + return rocketMsg; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java new file mode 100644 index 000000000..3f7898422 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.stream.binder.rocketmq.utils; + +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; +import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQCommonProperties; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.consumer.MessageSelector; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.remoting.RPCHook; + +import org.springframework.util.StringUtils; + +/** + * TODO Describe what it does + * + * @author Jim + */ +public class RocketMQUtils { + + public static T mergeRocketMQProperties( + RocketMQBinderConfigurationProperties binderConfigurationProperties, + T mqProperties) { + if (null == binderConfigurationProperties || mqProperties == null) { + return mqProperties; + } + if (StringUtils.isEmpty(mqProperties.getNameServer())) { + mqProperties.setNameServer(binderConfigurationProperties.getNameServer()); + } + if (StringUtils.isEmpty(mqProperties.getSecretKey())) { + mqProperties.setSecretKey(binderConfigurationProperties.getSecretKey()); + } + if (StringUtils.isEmpty(mqProperties.getAccessKey())) { + mqProperties.setAccessKey(binderConfigurationProperties.getAccessKey()); + } + if (StringUtils.isEmpty(mqProperties.getAccessChannel())) { + mqProperties + .setAccessChannel(binderConfigurationProperties.getAccessChannel()); + } + if (StringUtils.isEmpty(mqProperties.getNamespace())) { + mqProperties.setNamespace(binderConfigurationProperties.getNamespace()); + } + if (StringUtils.isEmpty(mqProperties.getGroup())) { + mqProperties.setGroup(binderConfigurationProperties.getGroup()); + } + if (StringUtils.isEmpty(mqProperties.getCustomizedTraceTopic())) { + mqProperties.setCustomizedTraceTopic( + binderConfigurationProperties.getCustomizedTraceTopic()); + } + mqProperties.setNameServer(getNameServerStr(mqProperties.getNameServer())); + return mqProperties; + } + + public static String getInstanceName(RPCHook rpcHook, String identify) { + String separator = "|"; + StringBuilder instanceName = new StringBuilder(); + if (null != rpcHook) { + SessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook) + .getSessionCredentials(); + instanceName.append(sessionCredentials.getAccessKey()).append(separator) + .append(sessionCredentials.getSecretKey()).append(separator); + } + instanceName.append(identify).append(separator).append(UtilAll.getPid()); + return instanceName.toString(); + } + + public static String getNameServerStr(String nameServer) { + if (StringUtils.isEmpty(nameServer)) { + return null; + } + return nameServer.replaceAll(",", ";"); + } + + private static final String SQL = "sql:"; + + public static MessageSelector getMessageSelector(String expression) { + if (StringUtils.hasText(expression) && expression.startsWith(SQL)) { + return MessageSelector.bySql(expression.replaceFirst(SQL, "")); + } + return MessageSelector.byTag(expression); + } + +} From 5a763e0ec987041ae85702bfe36494bbc45f1ecf Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 1 Feb 2021 11:29:37 +0800 Subject: [PATCH 08/99] Code refactoring and some new feature support - delete some invalid files. --- .../rocketmq/RocketMQBinderConstants.java | 51 --------- .../RocketMQBinderAutoConfiguration.java | 81 -------------- ...inderHealthIndicatorAutoConfiguration.java | 40 ------- ...etMQComponent4BinderAutoConfiguration.java | 102 ------------------ .../main/resources/META-INF/spring.binders | 2 +- .../main/resources/META-INF/spring.factories | 2 +- 6 files changed, 2 insertions(+), 276 deletions(-) delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java deleted file mode 100644 index 47e4b9e7f..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java +++ /dev/null @@ -1,51 +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.stream.binder.rocketmq; - -import static org.apache.rocketmq.spring.support.RocketMQHeaders.PREFIX; - -/** - * @author Jim - * @author Xiejiashuai - */ -public final class RocketMQBinderConstants { - - /** - * Header key for RocketMQ Transactional Args. - */ - public static final String ROCKET_TRANSACTIONAL_ARG = "TRANSACTIONAL_ARG"; - - /** - * Default NameServer value. - */ - public static final String DEFAULT_NAME_SERVER = "127.0.0.1:9876"; - - /** - * Default group for SCS RocketMQ Binder. - */ - public static final String DEFAULT_GROUP = PREFIX + "binder_default_group_name"; - - /** - * RocketMQ re-consume times. - */ - public static final String ROCKETMQ_RECONSUME_TIMES = PREFIX + "RECONSUME_TIMES"; - - private RocketMQBinderConstants() { - throw new AssertionError("Must not instantiate constant utility class"); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java deleted file mode 100644 index 3031c2656..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java +++ /dev/null @@ -1,81 +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.stream.binder.rocketmq.config; - -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; -import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner; -import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; -import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties; - -import org.springframework.beans.factory.annotation.Autowired; -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; - -/** - * @author Timur Valiev - * @author Jim - */ -@Configuration(proxyBeanMethods = false) -@Import({ RocketMQAutoConfiguration.class, - RocketMQBinderHealthIndicatorAutoConfiguration.class }) -@EnableConfigurationProperties({ RocketMQBinderConfigurationProperties.class, - RocketMQExtendedBindingProperties.class }) -public class RocketMQBinderAutoConfiguration { - - private final RocketMQExtendedBindingProperties extendedBindingProperties; - - private final RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties; - - @Autowired(required = false) - private RocketMQProperties rocketMQProperties = new RocketMQProperties(); - - @Autowired - public RocketMQBinderAutoConfiguration( - RocketMQExtendedBindingProperties extendedBindingProperties, - RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties) { - this.extendedBindingProperties = extendedBindingProperties; - this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties; - } - - @Bean - public RocketMQTopicProvisioner provisioningProvider() { - return new RocketMQTopicProvisioner(); - } - - @Bean - public RocketMQMessageChannelBinder rocketMessageChannelBinder( - RocketMQTopicProvisioner provisioningProvider, - InstrumentationManager instrumentationManager) { - RocketMQMessageChannelBinder binder = new RocketMQMessageChannelBinder( - provisioningProvider, extendedBindingProperties, - rocketBinderConfigurationProperties, rocketMQProperties, - instrumentationManager); - binder.setExtendedBindingProperties(extendedBindingProperties); - return binder; - } - - @Bean - public InstrumentationManager instrumentationManager() { - return new InstrumentationManager(); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java deleted file mode 100644 index 1c3b5dc0d..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java +++ /dev/null @@ -1,40 +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.stream.binder.rocketmq.config; - -import com.alibaba.cloud.stream.binder.rocketmq.actuator.RocketMQBinderHealthIndicator; - -import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; -import org.springframework.boot.actuate.endpoint.annotation.Endpoint; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Jim - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnClass(Endpoint.class) -public class RocketMQBinderHealthIndicatorAutoConfiguration { - - @Bean - @ConditionalOnEnabledHealthIndicator("rocketmq") - public RocketMQBinderHealthIndicator rocketBinderHealthIndicator() { - return new RocketMQBinderHealthIndicator(); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java deleted file mode 100644 index 6968ead86..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java +++ /dev/null @@ -1,102 +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.stream.binder.rocketmq.config; - -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.rocketmq.acl.common.AclClientRPCHook; -import org.apache.rocketmq.acl.common.SessionCredentials; -import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; -import org.apache.rocketmq.spring.config.RocketMQConfigUtils; -import org.apache.rocketmq.spring.config.RocketMQTransactionAnnotationProcessor; -import org.apache.rocketmq.spring.config.TransactionHandlerRegistry; -import org.apache.rocketmq.spring.core.RocketMQTemplate; - -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; -import org.springframework.util.StringUtils; - -/** - * @author Jim - */ -@Configuration(proxyBeanMethods = false) -@AutoConfigureAfter(RocketMQAutoConfiguration.class) -@ConditionalOnMissingBean(DefaultMQProducer.class) -public class RocketMQComponent4BinderAutoConfiguration { - - private final Environment environment; - - public RocketMQComponent4BinderAutoConfiguration(Environment environment) { - this.environment = environment; - } - - @Bean - @ConditionalOnMissingBean(DefaultMQProducer.class) - public DefaultMQProducer defaultMQProducer() { - DefaultMQProducer producer; - String configNameServer = environment.resolveRequiredPlaceholders( - "${spring.cloud.stream.rocketmq.binder.name-server:${rocketmq.producer.name-server:}}"); - String ak = environment.resolveRequiredPlaceholders( - "${spring.cloud.stream.rocketmq.binder.access-key:${rocketmq.producer.access-key:}}"); - String sk = environment.resolveRequiredPlaceholders( - "${spring.cloud.stream.rocketmq.binder.secret-key:${rocketmq.producer.secret-key:}}"); - if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { - producer = new DefaultMQProducer(RocketMQBinderConstants.DEFAULT_GROUP, - new AclClientRPCHook(new SessionCredentials(ak, sk))); - producer.setVipChannelEnabled(false); - } - else { - producer = new DefaultMQProducer(RocketMQBinderConstants.DEFAULT_GROUP); - } - if (StringUtils.isEmpty(configNameServer)) { - configNameServer = RocketMQBinderConstants.DEFAULT_NAME_SERVER; - } - producer.setNamesrvAddr(configNameServer); - return producer; - } - - @Bean(destroyMethod = "destroy") - @ConditionalOnMissingBean - public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, - ObjectMapper objectMapper) { - RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); - rocketMQTemplate.setProducer(mqProducer); - rocketMQTemplate.setObjectMapper(objectMapper); - return rocketMQTemplate; - } - - @Bean - @ConditionalOnBean(RocketMQTemplate.class) - @ConditionalOnMissingBean(TransactionHandlerRegistry.class) - public TransactionHandlerRegistry transactionHandlerRegistry( - RocketMQTemplate template) { - return new TransactionHandlerRegistry(template); - } - - @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME) - @ConditionalOnBean(TransactionHandlerRegistry.class) - public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor( - TransactionHandlerRegistry transactionHandlerRegistry) { - return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry); - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders index 2e5b99538..b232e1f10 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders @@ -1 +1 @@ -rocketmq:com.alibaba.cloud.stream.binder.rocketmq.config.RocketMQBinderAutoConfiguration \ No newline at end of file +rocketmq:com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories index 82d344e00..e18651dc4 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.alibaba.cloud.stream.binder.rocketmq.config.RocketMQComponent4BinderAutoConfiguration +com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration From c1c559717154a92d87739450ea85e3186fea4029 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 1 Feb 2021 13:46:28 +0800 Subject: [PATCH 09/99] Code refactoring and some new feature support - delete some invalid files. --- .../RocketMQListenerBindingContainer.java | 470 ------------------ .../RocketMQMessageQueueChooser.java | 62 --- 2 files changed, 532 deletions(-) delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java deleted file mode 100644 index 7bd875f33..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java +++ /dev/null @@ -1,470 +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.stream.binder.rocketmq.consuming; -// -// import java.util.List; -// import java.util.Objects; -// -// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderUtils; -// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder; -// import -/// com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; -// import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties; -// import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; -// import org.apache.rocketmq.acl.common.AclClientRPCHook; -// import org.apache.rocketmq.acl.common.SessionCredentials; -// import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; -// import org.apache.rocketmq.client.consumer.MessageSelector; -// import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; -// import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; -// import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; -// import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; -// import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; -// import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; -// import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; -// import org.apache.rocketmq.client.exception.MQClientException; -// import org.apache.rocketmq.common.UtilAll; -// import org.apache.rocketmq.common.message.MessageExt; -// import org.apache.rocketmq.remoting.RPCHook; -// import org.apache.rocketmq.spring.annotation.ConsumeMode; -// import org.apache.rocketmq.spring.annotation.MessageModel; -// import org.apache.rocketmq.spring.annotation.SelectorType; -// import org.apache.rocketmq.spring.core.RocketMQListener; -// import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener; -// import org.apache.rocketmq.spring.support.RocketMQListenerContainer; -// import org.apache.rocketmq.spring.support.RocketMQUtil; -// import org.slf4j.Logger; -// import org.slf4j.LoggerFactory; -// -// import org.springframework.beans.factory.InitializingBean; -// import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; -// import org.springframework.context.SmartLifecycle; -// import org.springframework.integration.support.MessageBuilder; -// import org.springframework.messaging.Message; -// import org.springframework.util.Assert; -// import org.springframework.util.StringUtils; -// -// import static -/// com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants.ROCKETMQ_RECONSUME_TIMES; -// -/// ** -// * A class that Listen on rocketmq message. -// *

-// * this class will delegate {@link RocketMQListener} to handle message -// * -// * @author Jim -// * @author Xiejiashuai -// * @see RocketMQListener -// */ -// public class RocketMQListenerBindingContainer -// implements InitializingBean, RocketMQListenerContainer, SmartLifecycle { -// -// private final static Logger log = LoggerFactory -// .getLogger(RocketMQListenerBindingContainer.class); -// -// private long suspendCurrentQueueTimeMillis = 1000; -// -// /** -// * Message consume retry strategy
-// * -1,no retry,put into DLQ directly
-// * 0,broker control retry frequency
-// * >0,client control retry frequency. -// */ -// private int delayLevelWhenNextConsume = 0; -// -// private List nameServer; -// -// private String consumerGroup; -// -// private String topic; -// -// private int consumeThreadMax = 64; -// -// private String charset = "UTF-8"; -// -// private RocketMQListener rocketMQListener; -// -// private RocketMQHeaderMapper headerMapper; -// -// private DefaultMQPushConsumer consumer; -// -// private boolean running; -// -// private final ExtendedConsumerProperties -/// rocketMQConsumerProperties; -// -// private final RocketMQMessageChannelBinder rocketMQMessageChannelBinder; -// -// private final RocketMQBinderConfigurationProperties -/// rocketBinderConfigurationProperties; -// -// // The following properties came from RocketMQConsumerProperties. -// private ConsumeMode consumeMode; -// -// private SelectorType selectorType; -// -// private String selectorExpression; -// -// private MessageModel messageModel; -// -// public RocketMQListenerBindingContainer( -// ExtendedConsumerProperties rocketMQConsumerProperties, -// RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties, -// RocketMQMessageChannelBinder rocketMQMessageChannelBinder) { -// this.rocketMQConsumerProperties = rocketMQConsumerProperties; -// this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties; -// this.rocketMQMessageChannelBinder = rocketMQMessageChannelBinder; -// this.consumeMode = rocketMQConsumerProperties.getExtension().getOrderly() -// ? ConsumeMode.ORDERLY : ConsumeMode.CONCURRENTLY; -// if (StringUtils.isEmpty(rocketMQConsumerProperties.getExtension().getSql())) { -// this.selectorType = SelectorType.TAG; -// this.selectorExpression = rocketMQConsumerProperties.getExtension().getTags(); -// } -// else { -// this.selectorType = SelectorType.SQL92; -// this.selectorExpression = rocketMQConsumerProperties.getExtension().getSql(); -// } -// this.messageModel = rocketMQConsumerProperties.getExtension().getBroadcasting() -// ? MessageModel.BROADCASTING : MessageModel.CLUSTERING; -// } -// -// @Override -// public void setupMessageListener(RocketMQListener rocketMQListener) { -// this.rocketMQListener = rocketMQListener; -// } -// -// @Override -// public void destroy() throws Exception { -// this.setRunning(false); -// if (Objects.nonNull(consumer)) { -// consumer.shutdown(); -// } -// log.info("container destroyed, {}", this.toString()); -// } -// -// @Override -// public void afterPropertiesSet() throws Exception { -// initRocketMQPushConsumer(); -// } -// -// @Override -// public boolean isAutoStartup() { -// return true; -// } -// -// @Override -// public void stop(Runnable callback) { -// stop(); -// callback.run(); -// } -// -// @Override -// public void start() { -// if (this.isRunning()) { -// throw new IllegalStateException( -// "container already running. " + this.toString()); -// } -// -// try { -// consumer.start(); -// } -// catch (MQClientException e) { -// throw new IllegalStateException("Failed to start RocketMQ push consumer", e); -// } -// this.setRunning(true); -// -// log.info("running container: {}", this.toString()); -// } -// -// @Override -// public void stop() { -// if (this.isRunning()) { -// if (Objects.nonNull(consumer)) { -// consumer.shutdown(); -// } -// setRunning(false); -// } -// } -// -// @Override -// public boolean isRunning() { -// return running; -// } -// -// private void setRunning(boolean running) { -// this.running = running; -// } -// -// @Override -// public int getPhase() { -// return Integer.MAX_VALUE; -// } -// -// private void initRocketMQPushConsumer() throws MQClientException { -// Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); -// Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); -// Assert.notNull(nameServer, "Property 'nameServer' is required"); -// Assert.notNull(topic, "Property 'topic' is required"); -// -// String ak = rocketBinderConfigurationProperties.getAccessKey(); -// String sk = rocketBinderConfigurationProperties.getSecretKey(); -// if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { -// RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk)); -// consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook, -// new AllocateMessageQueueAveragely(), -// rocketBinderConfigurationProperties.isEnableMsgTrace(), -// rocketBinderConfigurationProperties.getCustomizedTraceTopic()); -// consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, -// topic + "|" + UtilAll.getPid())); -// consumer.setVipChannelEnabled(false); -// } -// else { -// consumer = new DefaultMQPushConsumer(consumerGroup, -// rocketBinderConfigurationProperties.isEnableMsgTrace(), -// rocketBinderConfigurationProperties.getCustomizedTraceTopic()); -// } -// -// consumer.setNamesrvAddr(RocketMQBinderUtils.getNameServerStr(nameServer)); -// consumer.setConsumeThreadMax(rocketMQConsumerProperties.getConcurrency()); -// consumer.setConsumeThreadMin(rocketMQConsumerProperties.getConcurrency()); -// -// switch (messageModel) { -// case BROADCASTING: -// consumer.setMessageModel( -// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING); -// break; -// case CLUSTERING: -// consumer.setMessageModel( -// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING); -// break; -// default: -// throw new IllegalArgumentException("Property 'messageModel' was wrong."); -// } -// -// switch (selectorType) { -// case TAG: -// consumer.subscribe(topic, selectorExpression); -// break; -// case SQL92: -// consumer.subscribe(topic, MessageSelector.bySql(selectorExpression)); -// break; -// default: -// throw new IllegalArgumentException("Property 'selectorType' was wrong."); -// } -// -// switch (consumeMode) { -// case ORDERLY: -// consumer.setMessageListener(new DefaultMessageListenerOrderly()); -// break; -// case CONCURRENTLY: -// consumer.setMessageListener(new DefaultMessageListenerConcurrently()); -// break; -// default: -// throw new IllegalArgumentException("Property 'consumeMode' was wrong."); -// } -// -// if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { -// ((RocketMQPushConsumerLifecycleListener) rocketMQListener) -// .prepareStart(consumer); -// } -// -// } -// -// @Override -// public String toString() { -// return "RocketMQListenerBindingContainer{" + "consumerGroup='" + consumerGroup -// + '\'' + ", nameServer='" + nameServer + '\'' + ", topic='" + topic + '\'' -// + ", consumeMode=" + consumeMode + ", selectorType=" + selectorType -// + ", selectorExpression='" + selectorExpression + '\'' + ", messageModel=" -// + messageModel + '}'; -// } -// -// public long getSuspendCurrentQueueTimeMillis() { -// return suspendCurrentQueueTimeMillis; -// } -// -// public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) { -// this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis; -// } -// -// public int getDelayLevelWhenNextConsume() { -// return delayLevelWhenNextConsume; -// } -// -// public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) { -// this.delayLevelWhenNextConsume = delayLevelWhenNextConsume; -// } -// -// public List getNameServer() { -// return nameServer; -// } -// -// public void setNameServer(List nameServer) { -// this.nameServer = nameServer; -// } -// -// public String getConsumerGroup() { -// return consumerGroup; -// } -// -// public void setConsumerGroup(String consumerGroup) { -// this.consumerGroup = consumerGroup; -// } -// -// public String getTopic() { -// return topic; -// } -// -// public void setTopic(String topic) { -// this.topic = topic; -// } -// -// public int getConsumeThreadMax() { -// return consumeThreadMax; -// } -// -// public void setConsumeThreadMax(int consumeThreadMax) { -// this.consumeThreadMax = consumeThreadMax; -// } -// -// public String getCharset() { -// return charset; -// } -// -// public void setCharset(String charset) { -// this.charset = charset; -// } -// -// public RocketMQListener getRocketMQListener() { -// return rocketMQListener; -// } -// -// public void setRocketMQListener(RocketMQListener rocketMQListener) { -// this.rocketMQListener = rocketMQListener; -// } -// -// public DefaultMQPushConsumer getConsumer() { -// return consumer; -// } -// -// public void setConsumer(DefaultMQPushConsumer consumer) { -// this.consumer = consumer; -// } -// -// public ExtendedConsumerProperties -/// getRocketMQConsumerProperties() { -// return rocketMQConsumerProperties; -// } -// -// public ConsumeMode getConsumeMode() { -// return consumeMode; -// } -// -// public SelectorType getSelectorType() { -// return selectorType; -// } -// -// public String getSelectorExpression() { -// return selectorExpression; -// } -// -// public MessageModel getMessageModel() { -// return messageModel; -// } -// -// public RocketMQHeaderMapper getHeaderMapper() { -// return headerMapper; -// } -// -// public void setHeaderMapper(RocketMQHeaderMapper headerMapper) { -// this.headerMapper = headerMapper; -// } -// -// /** -// * Convert rocketmq {@link MessageExt} to Spring {@link Message}. -// * @param messageExt the rocketmq message -// * @return the converted Spring {@link Message} -// */ -// @SuppressWarnings("unchecked") -// private Message convertToSpringMessage(MessageExt messageExt) { -// -// // add reconsume-times header to messageExt -// int reconsumeTimes = messageExt.getReconsumeTimes(); -// messageExt.putUserProperty(ROCKETMQ_RECONSUME_TIMES, -// String.valueOf(reconsumeTimes)); -// Message message = RocketMQUtil.convertToSpringMessage(messageExt); -// return MessageBuilder.fromMessage(message) -// .copyHeaders(headerMapper.toHeaders(messageExt.getProperties())).build(); -// } -// -// public class DefaultMessageListenerConcurrently -// implements MessageListenerConcurrently { -// -// @SuppressWarnings({ "unchecked", "Duplicates" }) -// @Override -// public ConsumeConcurrentlyStatus consumeMessage(List msgs, -// ConsumeConcurrentlyContext context) { -// for (MessageExt messageExt : msgs) { -// log.debug("received msg: {}", messageExt); -// try { -// long now = System.currentTimeMillis(); -// rocketMQListener.onMessage(convertToSpringMessage(messageExt)); -// long costTime = System.currentTimeMillis() - now; -// log.debug("consume {} message key:[{}] cost: {} ms", -// messageExt.getMsgId(), messageExt.getKeys(), costTime); -// } -// catch (Exception e) { -// log.warn("consume message failed. messageExt:{}", messageExt, e); -// context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); -// return ConsumeConcurrentlyStatus.RECONSUME_LATER; -// } -// } -// -// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; -// } -// -// } -// -// public class DefaultMessageListenerOrderly implements MessageListenerOrderly { -// -// @SuppressWarnings({ "unchecked", "Duplicates" }) -// @Override -// public ConsumeOrderlyStatus consumeMessage(List msgs, -// ConsumeOrderlyContext context) { -// for (MessageExt messageExt : msgs) { -// log.debug("received msg: {}", messageExt); -// try { -// long now = System.currentTimeMillis(); -// rocketMQListener.onMessage(convertToSpringMessage(messageExt)); -// long costTime = System.currentTimeMillis() - now; -// log.info("consume {} message key:[{}] cost: {} ms", -// messageExt.getMsgId(), messageExt.getKeys(), costTime); -// } -// catch (Exception e) { -// log.warn("consume message failed. messageExt:{}", messageExt, e); -// context.setSuspendCurrentQueueTimeMillis( -// suspendCurrentQueueTimeMillis); -// return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; -// } -// } -// -// return ConsumeOrderlyStatus.SUCCESS; -// } -// -// } -// -// } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java deleted file mode 100644 index 948555924..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java +++ /dev/null @@ -1,62 +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.stream.binder.rocketmq.consuming; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.apache.rocketmq.common.message.MessageQueue; - -/** - * @author Jim - */ -public class RocketMQMessageQueueChooser { - - private volatile int queueIndex = 0; - - private volatile List messageQueues; - - public MessageQueue choose() { - return messageQueues.get(queueIndex); - } - - public int requeue() { - if (queueIndex - 1 < 0) { - this.queueIndex = messageQueues.size() - 1; - } - else { - this.queueIndex = this.queueIndex - 1; - } - return this.queueIndex; - } - - public void increment() { - this.queueIndex = (this.queueIndex + 1) % messageQueues.size(); - } - - public void reset(Set queueSet) { - this.messageQueues = null; - this.messageQueues = new ArrayList<>(queueSet); - this.queueIndex = 0; - } - - public List getMessageQueues() { - return messageQueues; - } - -} From 7684fe71ca9e1257e658c2635644311fc5edb51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=A4=A7=E7=9B=B8?= Date: Fri, 26 Feb 2021 10:33:13 +0800 Subject: [PATCH 10/99] Upgrade Sentinel to 1.8.1 --- spring-cloud-alibaba-dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 1fdaf8695..6914341bf 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -19,7 +19,7 @@ 2.2.5.RC2 - 1.8.0 + 1.8.1 1.3.0 1.4.1 0.8.0 From 15df0bff6b1f4489508e68c56ce59e09178f6cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=A4=A7=E7=9B=B8?= Date: Fri, 26 Feb 2021 10:59:39 +0800 Subject: [PATCH 11/99] Upgrade Sentinel to 1.8.1 --- .../sentinel/endpoint/SentinelHealthIndicator.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java index 996a483b7..8be1174a2 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java @@ -16,17 +16,15 @@ package com.alibaba.cloud.sentinel.endpoint; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import com.alibaba.cloud.sentinel.SentinelProperties; 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 com.alibaba.csp.sentinel.transport.endpoint.Endpoint; +import java.util.List; +import java.util.Map; +import java.util.HashMap; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.Health; @@ -84,8 +82,7 @@ public class SentinelHealthIndicator extends AbstractHealthIndicator { // Check health of Dashboard boolean dashboardUp = true; - List> consoleServerList = TransportConfig - .getConsoleServerList(); + List consoleServerList = TransportConfig.getConsoleServerList(); if (CollectionUtils.isEmpty(consoleServerList)) { // If Dashboard isn't configured, it's OK and mark the status of Dashboard // with UNKNOWN. From 4817ca53b86949dca8cbd1ca7cabcfd8057373f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=A4=A7=E7=9B=B8?= Date: Fri, 26 Feb 2021 11:32:15 +0800 Subject: [PATCH 12/99] Upgrade Sentinel to 1.8.1 --- .../cloud/sentinel/endpoint/SentinelHealthIndicator.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java index 8be1174a2..b502fc543 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/endpoint/SentinelHealthIndicator.java @@ -16,15 +16,17 @@ package com.alibaba.cloud.sentinel.endpoint; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import com.alibaba.cloud.sentinel.SentinelProperties; 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.transport.endpoint.Endpoint; -import java.util.List; -import java.util.Map; -import java.util.HashMap; + import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.Health; From 9d164f9a0a72ebba55f0d6c02d4a4ceca317a2dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=A4=A7=E7=9B=B8?= Date: Fri, 26 Feb 2021 13:40:31 +0800 Subject: [PATCH 13/99] Upgrade Sentinel to 1.8.1 --- .../SentinelAutoConfigurationTests.java | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java index 56c5bf6bd..99b9fd3b5 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java @@ -16,8 +16,11 @@ package com.alibaba.cloud.sentinel; -import java.util.Arrays; -import java.util.Map; +import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate; import com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration; @@ -31,11 +34,13 @@ import com.alibaba.csp.sentinel.slots.block.RuleConstant; 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 com.alibaba.csp.sentinel.transport.endpoint.Endpoint; +import com.alibaba.csp.sentinel.transport.endpoint.Protocol; +import java.util.Arrays; +import java.util.Map; import org.junit.Before; 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; @@ -52,12 +57,6 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; -import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mock; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - /** * @author Jim * @author jiashuai.xie @@ -134,8 +133,10 @@ public class SentinelAutoConfigurationTests { Map map = sentinelEndpoint.invoke(); assertThat(map.get("logUsePid")).isEqualTo(Boolean.TRUE); - assertThat(map.get("consoleServer").toString()).isEqualTo( - Arrays.asList(Tuple2.of("localhost", 8080), Tuple2.of("localhost", 8081)) + assertThat(map.get("consoleServer").toString()) + .isEqualTo(Arrays + .asList(new Endpoint(Protocol.HTTP, "localhost", 8080), + new Endpoint(Protocol.HTTP, "localhost", 8081)) .toString()); assertThat(map.get("clientPort")).isEqualTo("9999"); assertThat(map.get("heartbeatIntervalMs")).isEqualTo(20000L); @@ -185,8 +186,10 @@ public class SentinelAutoConfigurationTests { @Test public void testSentinelSystemProperties() { assertThat(LogBase.isLogNameUsePid()).isEqualTo(true); - assertThat(TransportConfig.getConsoleServerList().toString()).isEqualTo( - Arrays.asList(Tuple2.of("localhost", 8080), Tuple2.of("localhost", 8081)) + assertThat(TransportConfig.getConsoleServerList().toString()) + .isEqualTo(Arrays + .asList(new Endpoint(Protocol.HTTP, "localhost", 8080), + new Endpoint(Protocol.HTTP, "localhost", 8081)) .toString()); assertThat(TransportConfig.getPort()).isEqualTo("9999"); assertThat(TransportConfig.getHeartbeatIntervalMs().longValue()) From 2701624da227149e39b9890702a91c3390a15514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=A4=A7=E7=9B=B8?= Date: Fri, 26 Feb 2021 13:54:51 +0800 Subject: [PATCH 14/99] Upgrade Sentinel to 1.8.1 --- .../sentinel/SentinelAutoConfigurationTests.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java index 99b9fd3b5..2b4c51e0f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/SentinelAutoConfigurationTests.java @@ -16,11 +16,8 @@ package com.alibaba.cloud.sentinel; -import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mock; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; +import java.util.Arrays; +import java.util.Map; import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate; import com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration; @@ -36,11 +33,10 @@ import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import com.alibaba.csp.sentinel.transport.config.TransportConfig; import com.alibaba.csp.sentinel.transport.endpoint.Endpoint; import com.alibaba.csp.sentinel.transport.endpoint.Protocol; -import java.util.Arrays; -import java.util.Map; import org.junit.Before; 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; @@ -57,6 +53,12 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; +import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + /** * @author Jim * @author jiashuai.xie From fd1deaa475c907f9048dd30caf721235a09d8140 Mon Sep 17 00:00:00 2001 From: dhb Date: Thu, 11 Mar 2021 12:21:02 +0800 Subject: [PATCH 15/99] fix dubbo service group and service merger cannot obtain urls --- .../DubboServiceMetadataRepository.java | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java index a5be34df8..494c78c68 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -19,6 +19,7 @@ package com.alibaba.cloud.dubbo.metadata.repository; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -41,6 +42,7 @@ import com.alibaba.cloud.dubbo.util.JSONUtils; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -407,8 +409,34 @@ public class DubboServiceMetadataRepository public List getExportedURLs(String serviceInterface, String group, String version) { - String serviceKey = URL.buildKey(serviceInterface, group, version); - return allExportedURLs.getOrDefault(serviceKey, Collections.emptyList()); + if (group != null) { + List urls = new LinkedList<>(); + if (CommonConstants.ANY_VALUE.equals(group)) { + String serviceKey = URL.buildKey(serviceInterface, group, version); + String expectKey = serviceKey.substring(2); + for (String key : allExportedURLs.keySet()) { + if (key.endsWith(expectKey)) { + urls.addAll(allExportedURLs.get(key)); + } + } + } + else { + String[] groups = group.split(CommonConstants.COMMA_SEPARATOR); + for (String expectKey : groups) { + String serviceKey = URL.buildKey(serviceInterface, expectKey, + version); + List urlList = allExportedURLs.get(serviceKey); + if (urlList != null) { + urls.addAll(urlList); + } + } + } + return urls; + } + else { + String serviceKey = URL.buildKey(serviceInterface, null, version); + return allExportedURLs.getOrDefault(serviceKey, Collections.emptyList()); + } } /** From b7f1dc9b04749b23e4cef0d2d0fd85ceac912816 Mon Sep 17 00:00:00 2001 From: luyanbo Date: Mon, 15 Mar 2021 17:12:07 +0800 Subject: [PATCH 16/99] =?UTF-8?q?=E6=B7=BB=E5=8A=A0RamRoleName=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cloud/nacos/NacosConfigProperties.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java index 4827aebf1..6722f8bba 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java @@ -53,6 +53,7 @@ import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT_PORT; import static com.alibaba.nacos.api.PropertyKeyConst.MAX_RETRY; import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE; import static com.alibaba.nacos.api.PropertyKeyConst.PASSWORD; +import static com.alibaba.nacos.api.PropertyKeyConst.RAM_ROLE_NAME; import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY; import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR; import static com.alibaba.nacos.api.PropertyKeyConst.USERNAME; @@ -202,6 +203,11 @@ public class NacosConfigProperties { */ private String secretKey; + /** + * access key for namespace. + */ + private String ramRoleName; + /** * context path for nacos config server. */ @@ -356,6 +362,14 @@ public class NacosConfigProperties { this.secretKey = secretKey; } + public String getRamRoleName() { + return ramRoleName; + } + + public void setRamRoleName(String ramRoleName) { + this.ramRoleName = ramRoleName; + } + public String getEncode() { return encode; } @@ -548,6 +562,7 @@ public class NacosConfigProperties { properties.put(NAMESPACE, Objects.toString(this.namespace, "")); properties.put(ACCESS_KEY, Objects.toString(this.accessKey, "")); properties.put(SECRET_KEY, Objects.toString(this.secretKey, "")); + properties.put(RAM_ROLE_NAME, Objects.toString(this.ramRoleName, "")); properties.put(CLUSTER_NAME, Objects.toString(this.clusterName, "")); properties.put(MAX_RETRY, Objects.toString(this.maxRetry, "")); properties.put(CONFIG_LONG_POLL_TIMEOUT, @@ -560,8 +575,7 @@ public class NacosConfigProperties { int index = endpoint.indexOf(":"); properties.put(ENDPOINT, endpoint.substring(0, index)); properties.put(ENDPOINT_PORT, endpoint.substring(index + 1)); - } - else { + } else { properties.put(ENDPOINT, endpoint); } @@ -597,6 +611,7 @@ public class NacosConfigProperties { + ", enableRemoteSyncConfig=" + enableRemoteSyncConfig + ", endpoint='" + endpoint + '\'' + ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\'' + ", secretKey='" + secretKey + '\'' + + ", ramRoleName='" + ramRoleName + '\'' + ", contextPath='" + contextPath + '\'' + ", clusterName='" + clusterName + '\'' + ", name='" + name + '\'' + '\'' + ", shares=" + sharedConfigs + ", extensions=" + extensionConfigs + ", refreshEnabled=" From 6d7c47a3660de3aa40fd519f52c84947638a4733 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 22 Mar 2021 11:05:31 +0800 Subject: [PATCH 17/99] Code refactoring and some new feature support - delete some invalid files. --- .../src/main/resources/application.properties | 8 ++-- .../alibaba/cloud/examples/SenderService.java | 4 +- .../examples/TransactionListenerImpl.java | 38 +++++++++---------- .../src/main/resources/application.properties | 1 + .../rocketmq/contants/RocketMQConst.java | 13 +------ .../inbound/pull/RocketMQMessageSource.java | 25 +++++++++--- .../RocketMQProducerMessageHandler.java | 2 +- .../binder/rocketmq/utils/RocketMQUtils.java | 3 +- .../RocketMQAutoConfigurationTests.java | 22 +++++------ 9 files changed, 61 insertions(+), 55 deletions(-) diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties index 2779db522..e2e77bd0b 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties @@ -3,20 +3,20 @@ spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876 spring.cloud.stream.bindings.input1.destination=test-topic spring.cloud.stream.bindings.input1.content-type=text/plain spring.cloud.stream.bindings.input1.group=test-group1 -spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true +spring.cloud.stream.rocketmq.bindings.input1.consumer.push.orderly=true spring.cloud.stream.bindings.input2.destination=test-topic spring.cloud.stream.bindings.input2.content-type=text/plain spring.cloud.stream.bindings.input2.group=test-group2 -spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false -spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr +spring.cloud.stream.rocketmq.bindings.input2.consumer.push.orderly=false +spring.cloud.stream.rocketmq.bindings.input2.consumer.subscription=tagStr spring.cloud.stream.bindings.input2.consumer.concurrency=20 spring.cloud.stream.bindings.input2.consumer.maxAttempts=1 spring.cloud.stream.bindings.input3.destination=test-topic spring.cloud.stream.bindings.input3.content-type=application/json spring.cloud.stream.bindings.input3.group=test-group3 -spring.cloud.stream.rocketmq.bindings.input3.consumer.tags=tagObj +spring.cloud.stream.rocketmq.bindings.input3.consumer.subscription=tagObj spring.cloud.stream.bindings.input3.consumer.concurrency=20 spring.cloud.stream.bindings.input4.destination=TransactionTopic diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java index cd9e50939..f7db15b57 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java @@ -20,8 +20,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import com.alibaba.cloud.examples.RocketMQProduceApplication.MySource; +import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; import org.apache.rocketmq.common.message.MessageConst; -import org.apache.rocketmq.spring.support.RocketMQHeaders; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.Message; @@ -62,7 +62,7 @@ public class SenderService { MessageBuilder builder = MessageBuilder.withPayload(msg) .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON); builder.setHeader("test", String.valueOf(num)); - builder.setHeader(RocketMQHeaders.TAGS, "binder"); + builder.setHeader(RocketMQConst.USER_TRANSACTIONAL_ARGS, "binder"); Message message = builder.build(); source.output2().send(message); } diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java index e58beb221..1cc1b3290 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java @@ -16,43 +16,43 @@ package com.alibaba.cloud.examples; -import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; -import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; -import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; -import org.springframework.messaging.Message; +import org.apache.rocketmq.client.producer.LocalTransactionState; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageExt; +import org.springframework.stereotype.Component; /** * @author Jim */ -@RocketMQTransactionListener(txProducerGroup = "myTxProducerGroup", corePoolSize = 5, - maximumPoolSize = 10) -public class TransactionListenerImpl implements RocketMQLocalTransactionListener { +@Component("myTransactionListener") +public class TransactionListenerImpl implements TransactionListener { @Override - public RocketMQLocalTransactionState executeLocalTransaction(Message msg, - Object arg) { - Object num = msg.getHeaders().get("test"); + public LocalTransactionState executeLocalTransaction(Message msg, + Object arg) { + Object num = msg.getProperty("test"); if ("1".equals(num)) { System.out.println( - "executer: " + new String((byte[]) msg.getPayload()) + " unknown"); - return RocketMQLocalTransactionState.UNKNOWN; + "executer: " + new String(msg.getBody()) + " unknown"); + return LocalTransactionState.UNKNOW; } else if ("2".equals(num)) { System.out.println( - "executer: " + new String((byte[]) msg.getPayload()) + " rollback"); - return RocketMQLocalTransactionState.ROLLBACK; + "executer: " + new String(msg.getBody()) + " rollback"); + return LocalTransactionState.ROLLBACK_MESSAGE; } System.out.println( - "executer: " + new String((byte[]) msg.getPayload()) + " commit"); - return RocketMQLocalTransactionState.COMMIT; + "executer: " + new String(msg.getBody()) + " commit"); + return LocalTransactionState.COMMIT_MESSAGE; } @Override - public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { - System.out.println("check: " + new String((byte[]) msg.getPayload())); - return RocketMQLocalTransactionState.COMMIT; + public LocalTransactionState checkLocalTransaction(MessageExt msg) { + System.out.println("check: " + new String(msg.getBody())); + return LocalTransactionState.COMMIT_MESSAGE; } } diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties index 772bf456e..08ab26ca0 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties @@ -11,6 +11,7 @@ spring.cloud.stream.bindings.output2.destination=TransactionTopic spring.cloud.stream.bindings.output2.content-type=application/json spring.cloud.stream.rocketmq.bindings.output2.producer.transactional=true spring.cloud.stream.rocketmq.bindings.output2.producer.group=myTxProducerGroup +spring.cloud.stream.rocketmq.bindings.output2.producer.transactionListener=myTransactionListener spring.cloud.stream.bindings.output3.destination=pull-topic spring.cloud.stream.bindings.output3.content-type=text/plain diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java index e83a6a172..694c8519c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java @@ -18,18 +18,11 @@ package com.alibaba.cloud.stream.binder.rocketmq.contants; import org.apache.rocketmq.common.message.MessageConst; -import static org.apache.rocketmq.spring.support.RocketMQHeaders.PREFIX; - /** * @author zkzlx */ public class RocketMQConst extends MessageConst { - /** - * Header key for RocketMQ Transactional Args. - */ - public static final String ROCKET_TRANSACTIONAL_ARG = "TRANSACTIONAL_ARG"; - /** * Default NameServer value. */ @@ -38,12 +31,8 @@ public class RocketMQConst extends MessageConst { /** * Default group for SCS RocketMQ Binder. */ - public static final String DEFAULT_GROUP = PREFIX + "binder_default_group_name"; + public static final String DEFAULT_GROUP = "binder_default_group_name"; - /** - * RocketMQ re-consume times. - */ - public static final String ROCKETMQ_RECONSUME_TIMES = PREFIX + "RECONSUME_TIMES"; public static final String USER_TRANSACTIONAL_ARGS = "TRANSACTIONAL_ARGS"; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java index 2ca91384b..a378fc615 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java @@ -17,6 +17,7 @@ package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull; import java.lang.reflect.Field; +import java.util.Iterator; import java.util.List; import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQConsumerFactory; @@ -62,6 +63,8 @@ public class RocketMQMessageSource extends AbstractMessageSource private final MessageSelector messageSelector; private final ExtendedConsumerProperties extendedConsumerProperties; + private volatile Iterator messageExtIterator=null; + public RocketMQMessageSource(String name, ExtendedConsumerProperties extendedConsumerProperties) { this.topic = name; @@ -82,7 +85,7 @@ public class RocketMQMessageSource extends AbstractMessageSource this.consumer = RocketMQConsumerFactory .initPullConsumer(extendedConsumerProperties); // This parameter must be 1, otherwise doReceive cannot be handled singly. - this.consumer.setPullBatchSize(1); +// this.consumer.setPullBatchSize(1); this.consumer.subscribe(topic, messageSelector); this.consumer.setAutoCommit(false); this.assignedMessageQueue = acquireAssignedMessageQueue(this.consumer); @@ -132,11 +135,20 @@ public class RocketMQMessageSource extends AbstractMessageSource @Override protected synchronized Object doReceive() { - List messageExtList = consumer.poll(); - if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) { + if(messageExtIterator == null){ + List messageExtList = consumer.poll(); + if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) { + return null; + } + messageExtIterator = messageExtList.iterator(); + } + MessageExt messageExt=messageExtIterator.next(); + if(!messageExtIterator.hasNext()){ + messageExtIterator = null; + } + if(null == messageExt){ return null; } - MessageExt messageExt = messageExtList.get(0); MessageQueue messageQueue = null; for (MessageQueue queue : assignedMessageQueue.getAssignedMessageQueues()) { if (queue.getQueueId() == messageExt.getQueueId()) { @@ -144,8 +156,11 @@ public class RocketMQMessageSource extends AbstractMessageSource break; } } + if(messageQueue == null){ + throw new IllegalArgumentException("The message queue is not in assigned list"); + } Message message = RocketMQMessageConverterSupport - .convertMessage2Spring(messageExtList.get(0)); + .convertMessage2Spring(messageExt); return MessageBuilder.fromMessage(message) .setHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK, new RocketMQAckCallback(this.consumer, assignedMessageQueue, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java index 66b58f797..3d58b8af0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java @@ -160,7 +160,7 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler TransactionListener.class); if (transactionListener == null) { throw new MessagingException( - "TransactionMQProducer must have a TransactionMQProducer !!! "); + "TransactionMQProducer must have a TransactionListener !!! "); } ((TransactionMQProducer) defaultMQProducer) .setTransactionListener(transactionListener); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java index 3f7898422..85165955d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java @@ -16,6 +16,7 @@ package com.alibaba.cloud.stream.binder.rocketmq.utils; +import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQCommonProperties; import org.apache.rocketmq.acl.common.AclClientRPCHook; @@ -81,7 +82,7 @@ public class RocketMQUtils { public static String getNameServerStr(String nameServer) { if (StringUtils.isEmpty(nameServer)) { - return null; + return RocketMQConst.DEFAULT_NAME_SERVER; } return nameServer.replaceAll(",", ";"); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java index 8207f9893..02d0de9f9 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java @@ -18,7 +18,7 @@ package com.alibaba.cloud.stream.binder.rocketmq; import java.util.Arrays; -import com.alibaba.cloud.stream.binder.rocketmq.config.RocketMQBinderAutoConfiguration; +import com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; import org.junit.Test; @@ -37,20 +37,20 @@ public class RocketMQAutoConfigurationTests { .withConfiguration( AutoConfigurations.of(RocketMQBinderAutoConfiguration.class)) .withPropertyValues( - "spring.cloud.stream.rocketmq.binder.name-server[0]=127.0.0.1:9876", - "spring.cloud.stream.rocketmq.binder.name-server[1]=127.0.0.1:9877", + "spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876,127.0.0.1:9877", "spring.cloud.stream.bindings.output.destination=TopicOrderTest", "spring.cloud.stream.bindings.output.content-type=application/json", + "spring.cloud.stream.bindings.input1.destination=TopicOrderTest", "spring.cloud.stream.bindings.input1.content-type=application/json", "spring.cloud.stream.bindings.input1.group=test-group1", - "spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true", + "spring.cloud.stream.rocketmq.bindings.input1.consumer.push.orderly=true", "spring.cloud.stream.bindings.input1.consumer.maxAttempts=1", "spring.cloud.stream.bindings.input2.destination=TopicOrderTest", "spring.cloud.stream.bindings.input2.content-type=application/json", "spring.cloud.stream.bindings.input2.group=test-group2", - "spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false", - "spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tag1"); + "spring.cloud.stream.rocketmq.bindings.input2.consumer.push.orderly=false", + "spring.cloud.stream.rocketmq.bindings.input2.consumer.subscription=tag1"); @Test public void testProperties() { @@ -58,16 +58,16 @@ public class RocketMQAutoConfigurationTests { RocketMQBinderConfigurationProperties binderConfigurationProperties = context .getBean(RocketMQBinderConfigurationProperties.class); assertThat(binderConfigurationProperties.getNameServer()) - .isEqualTo(Arrays.asList("127.0.0.1:9876", "127.0.0.1:9877")); + .isEqualTo("127.0.0.1:9876,127.0.0.1:9877"); RocketMQExtendedBindingProperties bindingProperties = context .getBean(RocketMQExtendedBindingProperties.class); assertThat( - bindingProperties.getExtendedConsumerProperties("input2").getTags()) + bindingProperties.getExtendedConsumerProperties("input2").getSubscription()) .isEqualTo("tag1"); - assertThat(bindingProperties.getExtendedConsumerProperties("input2") - .getOrderly()).isFalse(); + assertThat(bindingProperties.getExtendedConsumerProperties("input2").getPush().getOrderly() + ).isFalse(); assertThat(bindingProperties.getExtendedConsumerProperties("input1") - .getOrderly()).isTrue(); + .getPush().getOrderly()).isTrue(); }); } From 9379d18ace1a4ca3fb2400920c7e95b17eb4fda9 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 22 Mar 2021 14:37:22 +0800 Subject: [PATCH 18/99] Code style --- .../examples/TransactionListenerImpl.java | 14 +++--- .../RocketMQMessageChannelBinder.java | 7 +-- .../RocketMQBinderAutoConfiguration.java | 4 +- .../rocketmq/contants/RocketMQConst.java | 33 +++++++++++--- .../convert/RocketMQMessageConverter.java | 14 ++++-- .../custom/RocketMQBeanContainerCache.java | 9 ++-- .../RocketMQConfigBeanPostProcessor.java | 6 +-- .../extend/ErrorAcknowledgeHandler.java | 6 +-- .../inbound/RocketMQConsumerFactory.java | 6 ++- .../RocketMQInboundChannelAdapter.java | 12 ++--- .../pull/DefaultErrorAcknowledgeHandler.java | 9 ++-- .../inbound/pull/RocketMQAckCallback.java | 13 ++++-- .../inbound/pull/RocketMQMessageSource.java | 21 +++++---- .../outbound/RocketMQProduceFactory.java | 9 +++- .../RocketMQProducerMessageHandler.java | 24 ++++++---- .../rocketmq/metrics/Instrumentation.java | 14 ++++++ .../metrics/InstrumentationManager.java | 3 ++ ...RocketMQBinderConfigurationProperties.java | 5 ++- .../properties/RocketMQCommonProperties.java | 29 ++++++------ .../RocketMQConsumerProperties.java | 45 ++++++++++--------- .../RocketMQExtendedBindingProperties.java | 4 +- .../RocketMQProducerProperties.java | 32 ++++++++++--- .../RocketMQSpecificPropertiesProvider.java | 4 +- .../RocketMQMessageConverterSupport.java | 10 +++-- .../binder/rocketmq/utils/RocketMQUtils.java | 11 ++--- .../RocketMQAutoConfigurationTests.java | 15 +++---- 26 files changed, 231 insertions(+), 128 deletions(-) diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java index 1cc1b3290..446570ec9 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java @@ -16,11 +16,11 @@ package com.alibaba.cloud.examples; - import org.apache.rocketmq.client.producer.LocalTransactionState; import org.apache.rocketmq.client.producer.TransactionListener; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.message.MessageExt; + import org.springframework.stereotype.Component; /** @@ -30,22 +30,18 @@ import org.springframework.stereotype.Component; public class TransactionListenerImpl implements TransactionListener { @Override - public LocalTransactionState executeLocalTransaction(Message msg, - Object arg) { + public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { Object num = msg.getProperty("test"); if ("1".equals(num)) { - System.out.println( - "executer: " + new String(msg.getBody()) + " unknown"); + System.out.println("executer: " + new String(msg.getBody()) + " unknown"); return LocalTransactionState.UNKNOW; } else if ("2".equals(num)) { - System.out.println( - "executer: " + new String(msg.getBody()) + " rollback"); + System.out.println("executer: " + new String(msg.getBody()) + " rollback"); return LocalTransactionState.ROLLBACK_MESSAGE; } - System.out.println( - "executer: " + new String(msg.getBody()) + " commit"); + System.out.println("executer: " + new String(msg.getBody()) + " commit"); return LocalTransactionState.COMMIT_MESSAGE; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java index 5683bff68..403f51476 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -60,6 +60,7 @@ public class RocketMQMessageChannelBinder extends ExtendedPropertiesBinder { private final RocketMQExtendedBindingProperties extendedBindingProperties; + private final RocketMQBinderConfigurationProperties binderConfigurationProperties; public RocketMQMessageChannelBinder( @@ -175,7 +176,6 @@ public class RocketMQMessageChannelBinder extends /** * Binders can return an {@link ErrorMessageStrategy} for building error messages; * binder implementations typically might add extra headers to the error message. - * * @return the implementation - may be null. */ @Override @@ -203,4 +203,5 @@ public class RocketMQMessageChannelBinder extends public Class getExtendedPropertiesEntryClass() { return this.extendedBindingProperties.getExtendedPropertiesEntryClass(); } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java index abcb9b961..ec47e951a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java @@ -34,7 +34,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.messaging.converter.CompositeMessageConverter; /** - * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681 + * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681 . + * * @author Timur Valiev * @author Jim */ @@ -45,6 +46,7 @@ public class RocketMQBinderAutoConfiguration { @Autowired private RocketMQExtendedBindingProperties extendedBindingProperties; + @Autowired private RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java index 694c8519c..4f893642e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -31,9 +31,11 @@ public class RocketMQConst extends MessageConst { /** * Default group for SCS RocketMQ Binder. */ - public static final String DEFAULT_GROUP = "binder_default_group_name"; - + public static final String DEFAULT_GROUP = "binder_default_group_name"; + /** + * user args for SCS RocketMQ Binder. + */ public static final String USER_TRANSACTIONAL_ARGS = "TRANSACTIONAL_ARGS"; /** @@ -41,19 +43,34 @@ public class RocketMQConst extends MessageConst { * and parameters are passed through HEADERS. */ public static class Headers { + + /** + * keys for SCS RocketMQ Headers. + */ public static final String KEYS = MessageConst.PROPERTY_KEYS; + + /** + * tags for SCS RocketMQ Headers. + */ public static final String TAGS = MessageConst.PROPERTY_TAGS; + + /** + * topic for SCS RocketMQ Headers. + */ public static final String TOPIC = "MQ_TOPIC"; + /** * The ID of the message. */ public static final String MESSAGE_ID = "MQ_MESSAGE_ID"; + /** * The timestamp that the message producer invokes the message sending API. */ public static final String BORN_TIMESTAMP = "MQ_BORN_TIMESTAMP"; + /** - * The IP and port number of the message producer + * The IP and port number of the message producer. */ public static final String BORN_HOST = "MQ_BORN_HOST"; @@ -61,19 +78,23 @@ public class RocketMQConst extends MessageConst { * Message flag, MQ is not processed and is available for use by applications. */ public static final String FLAG = "MQ_FLAG"; + /** - * Message consumption queue ID + * Message consumption queue ID. */ public static final String QUEUE_ID = "MQ_QUEUE_ID"; + /** * Message system Flag, such as whether or not to compress, whether or not to * transactional messages. */ public static final String SYS_FLAG = "MQ_SYS_FLAG"; + /** * The transaction ID of the transaction message. */ public static final String TRANSACTION_ID = "MQ_TRANSACTION_ID"; + } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java index 58f17c6ef..98bd03263 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -27,14 +27,19 @@ import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.util.ClassUtils; /** - * The default message converter of rocketMq,its bean name is {@link #DEFAULT_NAME} + * The default message converter of rocketMq,its bean name is {@link #DEFAULT_NAME} . + * * @author zkzlx */ public class RocketMQMessageConverter { + /** + * rocketMQMessageConverter. + */ public static final String DEFAULT_NAME = "rocketMQMessageConverter"; private static final boolean JACKSON_PRESENT; + private static final boolean FASTJSON_PRESENT; static { @@ -81,4 +86,5 @@ public class RocketMQMessageConverter { public void setMessageConverter(CompositeMessageConverter messageConverter) { this.messageConverter = messageConverter; } -} \ No newline at end of file + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java index 9afc94821..21c62aede 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -32,12 +32,15 @@ import org.springframework.messaging.converter.CompositeMessageConverter; import org.springframework.util.StringUtils; /** - * Gets the beans configured in the configuration file + * Gets the beans configured in the configuration file. * * @author junboXiang */ public final class RocketMQBeanContainerCache { + private RocketMQBeanContainerCache() { + } + private static final Class[] CLASSES = new Class[] { CompositeMessageConverter.class, AllocateMessageQueueStrategy.class, MessageQueueSelector.class, MessageListener.class, TransactionListener.class, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java index 30bd64328..a83fdbe08 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -22,7 +22,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; /** - * find RocketMQ bean by annotations + * find RocketMQ bean by annotations. * * @author junboXiang * diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java index fcf6de804..dfe65fd94 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -27,7 +27,7 @@ public interface ErrorAcknowledgeHandler { /** * Ack state handling, including receive, reject, and retry, when a consumption * exception occurs. - * @param message + * @param message message * @return see {@link Status} */ Status handler(Message message); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java index 876249581..7f7e1bf26 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java @@ -41,6 +41,9 @@ import org.springframework.util.StringUtils; */ public final class RocketMQConsumerFactory { + private RocketMQConsumerFactory() { + } + private final static Logger log = LoggerFactory .getLogger(RocketMQConsumerFactory.class); @@ -91,7 +94,8 @@ public final class RocketMQConsumerFactory { /** * todo Compatible with versions less than 4.6 ? - * @return + * @param extendedConsumerProperties extendedConsumerProperties + * @return DefaultLitePullConsumer */ public static DefaultLitePullConsumer initPullConsumer( ExtendedConsumerProperties extendedConsumerProperties) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java index d0aec5523..61c0eedd3 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java @@ -48,7 +48,6 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; /** - * TODO Describe what it does * @author Jim */ public class RocketMQInboundChannelAdapter extends MessageProducerSupport @@ -58,10 +57,13 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport .getLogger(RocketMQInboundChannelAdapter.class); private RetryTemplate retryTemplate; + private RecoveryCallback recoveryCallback; + private DefaultMQPushConsumer pushConsumer; private final String topic; + private final ExtendedConsumerProperties extendedConsumerProperties; public RocketMQInboundChannelAdapter(String topic, @@ -146,11 +148,11 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport * The actual execution of a user-defined input consumption service method. * @param messageExtList rocket mq message list * @param failSupplier {@link ConsumeConcurrentlyStatus} or - * {@link ConsumeOrderlyStatus} + * {@link ConsumeOrderlyStatus} * @param sucSupplier {@link ConsumeConcurrentlyStatus} or - * {@link ConsumeOrderlyStatus} - * @param - * @return + * {@link ConsumeOrderlyStatus} + * @param object + * @return R */ private R consumeMessage(List messageExtList, Supplier failSupplier, Supplier sucSupplier) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java index 3296a128e..458324741 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -29,15 +29,16 @@ import org.springframework.messaging.Message; * @author zkzlx */ public class DefaultErrorAcknowledgeHandler implements ErrorAcknowledgeHandler { + /** * Ack state handling, including receive, reject, and retry, when a consumption * exception occurs. - * - * @param message + * @param message message * @return see {@link Status} */ @Override public Status handler(Message message) { return Status.REQUEUE; } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java index f617dd097..56e50ca4a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -31,16 +31,23 @@ import org.springframework.util.Assert; /** * A pollable {@link org.springframework.integration.core.MessageSource} for RocketMQ. + * * @author zkzlx */ public class RocketMQAckCallback implements AcknowledgmentCallback { + private final static Logger log = LoggerFactory.getLogger(RocketMQAckCallback.class); private boolean acknowledged; + private boolean autoAckEnabled = true; + private MessageExt messageExt; + private AssignedMessageQueue assignedMessageQueue; + private DefaultLitePullConsumer consumer; + private final MessageQueue messageQueue; public RocketMQAckCallback(DefaultLitePullConsumer consumer, @@ -109,4 +116,4 @@ public class RocketMQAckCallback implements AcknowledgmentCallback { } } -} \ No newline at end of file +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java index a378fc615..a7d7e73da 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java @@ -56,14 +56,18 @@ public class RocketMQMessageSource extends AbstractMessageSource .getLogger(RocketMQMessageSource.class); private DefaultLitePullConsumer consumer; + private AssignedMessageQueue assignedMessageQueue; + private volatile boolean running; private final String topic; + private final MessageSelector messageSelector; + private final ExtendedConsumerProperties extendedConsumerProperties; - private volatile Iterator messageExtIterator=null; + private volatile Iterator messageExtIterator = null; public RocketMQMessageSource(String name, ExtendedConsumerProperties extendedConsumerProperties) { @@ -85,7 +89,7 @@ public class RocketMQMessageSource extends AbstractMessageSource this.consumer = RocketMQConsumerFactory .initPullConsumer(extendedConsumerProperties); // This parameter must be 1, otherwise doReceive cannot be handled singly. -// this.consumer.setPullBatchSize(1); + // this.consumer.setPullBatchSize(1); this.consumer.subscribe(topic, messageSelector); this.consumer.setAutoCommit(false); this.assignedMessageQueue = acquireAssignedMessageQueue(this.consumer); @@ -135,18 +139,18 @@ public class RocketMQMessageSource extends AbstractMessageSource @Override protected synchronized Object doReceive() { - if(messageExtIterator == null){ + if (messageExtIterator == null) { List messageExtList = consumer.poll(); if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) { return null; } messageExtIterator = messageExtList.iterator(); } - MessageExt messageExt=messageExtIterator.next(); - if(!messageExtIterator.hasNext()){ + MessageExt messageExt = messageExtIterator.next(); + if (!messageExtIterator.hasNext()) { messageExtIterator = null; } - if(null == messageExt){ + if (null == messageExt) { return null; } MessageQueue messageQueue = null; @@ -156,8 +160,9 @@ public class RocketMQMessageSource extends AbstractMessageSource break; } } - if(messageQueue == null){ - throw new IllegalArgumentException("The message queue is not in assigned list"); + if (messageQueue == null) { + throw new IllegalArgumentException( + "The message queue is not in assigned list"); } Message message = RocketMQMessageConverterSupport .convertMessage2Spring(messageExt); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java index 7017ba46e..463868438 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java @@ -39,18 +39,23 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Extended function related to producer . eg:initial + * Extended function related to producer . eg:initial . * * @author zkzlx */ public final class RocketMQProduceFactory { + private RocketMQProduceFactory() { + } + private final static Logger log = LoggerFactory .getLogger(RocketMQProduceFactory.class); /** * init for the producer,including convert producer params. - * @return + * @param topic topic + * @param producerProperties producerProperties + * @return DefaultMQProducer */ public static DefaultMQProducer initRocketMQProducer(String topic, RocketMQProducerProperties producerProperties) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java index 3d58b8af0..56c208759 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -61,16 +61,23 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler .getLogger(RocketMQProducerMessageHandler.class); private volatile boolean running = false; + private volatile boolean isTrans = false; private ErrorMessageStrategy errorMessageStrategy; + private MessageChannel sendFailureChannel; + private MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor; + private DefaultMQProducer defaultMQProducer; + private MessageQueueSelector messageQueueSelector; private final ProducerDestination destination; + private final ExtendedProducerProperties extendedProducerProperties; + private final RocketMQProducerProperties mqProducerProperties; public RocketMQProducerMessageHandler(ProducerDestination destination, @@ -93,10 +100,8 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler // Use the default if the partition is on and no customization is available. this.messageQueueSelector = RocketMQBeanContainerCache.getBean( mqProducerProperties.getMessageQueueSelector(), - MessageQueueSelector.class, - extendedProducerProperties.isPartitioned() - ? new PartitionMessageQueueSelector() - : null); + MessageQueueSelector.class, extendedProducerProperties.isPartitioned() + ? new PartitionMessageQueueSelector() : null); } @Override @@ -226,9 +231,9 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler } /** - * https://github.com/alibaba/spring-cloud-alibaba/issues/1408 - * @param message - * @return + * https://github.com/alibaba/spring-cloud-alibaba/issues/1408 . + * @param message message + * @return SendCallback */ private SendCallback getSendCallback(Message message) { SendCallback sendCallback = RocketMQBeanContainerCache @@ -283,4 +288,5 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler this.partitioningInterceptor = partitioningInterceptor; return this; } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java index 397e62854..e26482855 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java @@ -28,6 +28,7 @@ import org.springframework.context.Lifecycle; public class Instrumentation { private final String name; + private Lifecycle actuator; protected final AtomicBoolean started = new AtomicBoolean(false); @@ -88,4 +89,17 @@ public class Instrumentation { public int hashCode() { return Objects.hash(getName(), getActuator()); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Instrumentation that = (Instrumentation) o; + return name.equals(that.name) && actuator.equals(that.actuator); + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java index de6e1e794..ad7958e44 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java @@ -26,6 +26,9 @@ import java.util.Map; */ public final class InstrumentationManager { + private InstrumentationManager() { + } + private static final Map HEALTH_INSTRUMENTATIONS = new HashMap<>(); public static Collection getHealthInstrumentations() { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java index fd5e77919..3da04ea18 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -20,6 +20,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; /** * binding rocketMq properties. + * * @author Jim */ @ConfigurationProperties(prefix = "spring.cloud.stream.rocketmq.binder") diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java index 00e7d30dd..9e9114641 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -26,6 +26,7 @@ import org.apache.rocketmq.remoting.netty.TlsSystemConfig; * @author zkzlx */ public class RocketMQCommonProperties implements Serializable { + private static final long serialVersionUID = -6724870154343284715L; private boolean enabled = true; @@ -41,38 +42,36 @@ public class RocketMQCommonProperties implements Serializable { * The property of "secret-key". */ private String secretKey; + /** * Consumers of the same role is required to have exactly same subscriptions and * consumerGroup to correctly achieve load balance. It's required and needs to be - * globally unique. - *

- * Producer group conceptually aggregates all producer instances of exactly same role, - * which is particularly important when transactional messages are involved. - *

- *

- * For non-transactional messages, it does not matter as long as it's unique per - * process. - *

- *

- * See here for further - * discussion. + * globally unique. Producer group conceptually aggregates all producer instances of + * exactly same role, which is particularly important when transactional messages are + * involved. For non-transactional messages, it does not matter as long as it's unique + * per process. See here + * for further discussion. */ private String group; private String namespace; + private String accessChannel = AccessChannel.LOCAL.name(); + /** * Pulling topic information interval from the named server. * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask * updateTopicRouteInfoFromNameServer. */ private int pollNameServerInterval = 1000 * 30; + /** * Heartbeat interval in microseconds with message broker. * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask * sendHeartbeatToAllBroker . */ private int heartbeatBrokerInterval = 1000 * 30; + /** * Offset persistent interval for consumer. * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask @@ -85,6 +84,7 @@ public class RocketMQCommonProperties implements Serializable { private boolean useTLS = TlsSystemConfig.tlsEnable; private boolean enableMsgTrace = true; + private String customizedTraceTopic; public boolean getEnabled() { @@ -198,4 +198,5 @@ public class RocketMQCommonProperties implements Serializable { public void setCustomizedTraceTopic(String customizedTraceTopic) { this.customizedTraceTopic = customizedTraceTopic; } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java index 1a889f6d7..ebe2c1c43 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -37,8 +37,6 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { /** * Message model defines the way how messages are delivered to each consumer clients. - *

- * * This field defaults to clustering. */ private String messageModel = MessageModel.CLUSTERING.getModeCN(); @@ -60,13 +58,12 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { private String subscription; /** - * Delay some time when exception occur + * Delay some time when exception occur . */ private long pullTimeDelayMillsWhenException = 1000; /** * Consuming point on consumer booting. - *

* * There are three consuming points: *
    @@ -90,6 +87,7 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { *
*/ private ConsumeFromWhere consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET; + /** * Backtracking consumption time with second precision. Time format is * 20131223171201
@@ -102,13 +100,14 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { /** * Flow control threshold on queue level, each message queue will cache at most 1000 * messages by default, Consider the {@link #pullBatchSize}, the instantaneous value - * may exceed the limit + * may exceed the limit . */ private int pullThresholdForQueue = 1000; + /** * Limit the cached message size on queue level, each message queue will cache at most * 100 MiB messages by default, Consider the {@link #pullBatchSize}, the instantaneous - * value may exceed the limit + * value may exceed the limit . * *

* The size of a message only measured by message body, so it's not accurate @@ -126,6 +125,7 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { private int consumeMaxSpan = 2000; private Push push = new Push(); + private Pull pull = new Pull(); public String getMessageModel() { @@ -238,6 +238,7 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { } public static class Push implements Serializable { + private static final long serialVersionUID = -7398468554978817630L; /** @@ -245,6 +246,7 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { * false, using {@link MessageListenerConcurrently}. */ private boolean orderly = false; + /** * Suspending pulling time for cases requiring slow pulling like flow-control * scenario. see{@link ConsumeMessageOrderlyService#processConsumeResult}. @@ -254,10 +256,9 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { /** * https://github.com/alibaba/spring-cloud-alibaba/issues/1866 Max re-consume - * times. -1 means 16 times. - *

- * If messages are re-consumed more than {@link #maxReconsumeTimes} before - * success, it's be directed to a deletion queue waiting. + * times. -1 means 16 times. If messages are re-consumed more than + * {@link #maxReconsumeTimes} before success, it's be directed to a deletion queue + * waiting. */ private int maxReconsumeTimes; @@ -285,21 +286,21 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { * MiB(Unlimited) *

* The value of {@code pullThresholdSizeForQueue} will be overwrote and calculated - * based on {@code pullThresholdSizeForTopic} if it is't unlimited + * based on {@code pullThresholdSizeForTopic} if it is't unlimited . *

* For example, if the value of pullThresholdSizeForTopic is 1000 MiB and 10 * message queues are assigned to this consumer, then pullThresholdSizeForQueue - * will be set to 100 MiB + * will be set to 100 MiB . */ private int pullThresholdSizeForTopic = -1; /** - * Message pull Interval + * Message pull Interval. */ private long pullInterval = 0; /** - * Batch consumption size + * Batch consumption size. */ private int consumeMessageBatchMaxSize = 1; @@ -366,15 +367,18 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { public void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) { this.consumeMessageBatchMaxSize = consumeMessageBatchMaxSize; } + } public static class Pull implements Serializable { + /** - * The poll timeout in milliseconds + * The poll timeout in milliseconds. */ private long pollTimeoutMillis = 1000 * 5; + /** - * Pull thread number + * Pull thread number. */ private int pullThreadNums = 20; @@ -385,13 +389,13 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { /** * Long polling mode, the Consumer connection timeout(must greater than - * brokerSuspendMaxTimeMillis), it is not recommended to modify + * brokerSuspendMaxTimeMillis), it is not recommended to modify. */ private long consumerTimeoutMillisWhenSuspend = 1000 * 30; /** * Ack state handling, including receive, reject, and retry, when a consumption - * exception occurs. see {@link } + * exception occurs. */ private String errAcknowledge; @@ -446,6 +450,7 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties { public void setPullThresholdForAll(long pullThresholdForAll) { this.pullThresholdForAll = pullThresholdForAll; } + } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java index 5fc34ed08..6c4af119d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java index 8f73cf93f..4035f1483 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -37,7 +37,6 @@ public class RocketMQProducerProperties extends RocketMQCommonProperties { /** * Maximum number of retry to perform internally before claiming sending failure in * synchronous mode. - *

* * This may potentially cause message duplication which is up to application * developers to resolve. @@ -47,7 +46,6 @@ public class RocketMQProducerProperties extends RocketMQCommonProperties { /** * Maximum number of retry to perform internally before claiming sending failure in * asynchronous mode. - *

* * This may potentially cause message duplication which is up to application * developers to resolve. @@ -203,19 +201,41 @@ public class RocketMQProducerProperties extends RocketMQCommonProperties { } public enum ProducerType { - Normal, Trans; + + /** + * Is not a transaction. + */ + Normal, + /** + * a transaction. + */ + Trans; public boolean equalsName(String name) { return this.name().equalsIgnoreCase(name); } + } public enum SendType { - OneWay, Async, Sync,; + + /** + * one way. + */ + OneWay, + /** + * Asynchronization Model. + */ + Async, + /** + * synchronization. + */ + Sync,; public boolean equalsName(String name) { return this.name().equalsIgnoreCase(name); } + } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java index 99a1a36fb..990a211ce 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java index d4b62e5fa..0509805ea 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -36,10 +36,12 @@ import org.springframework.util.MimeTypeUtils; import org.springframework.util.StringUtils; /** - * * @author zkzlx */ -public class RocketMQMessageConverterSupport { +public final class RocketMQMessageConverterSupport { + + private RocketMQMessageConverterSupport() { + } private static final CompositeMessageConverter MESSAGE_CONVERTER = RocketMQBeanContainerCache .getBean(RocketMQMessageConverter.DEFAULT_NAME, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java index 85165955d..1aed546a0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2018 the original author or authors. + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -28,11 +28,12 @@ import org.apache.rocketmq.remoting.RPCHook; import org.springframework.util.StringUtils; /** - * TODO Describe what it does - * * @author Jim */ -public class RocketMQUtils { +public final class RocketMQUtils { + + private RocketMQUtils() { + } public static T mergeRocketMQProperties( RocketMQBinderConfigurationProperties binderConfigurationProperties, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java index 02d0de9f9..f850afb4e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java @@ -16,8 +16,6 @@ package com.alibaba.cloud.stream.binder.rocketmq; -import java.util.Arrays; - import com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; @@ -61,13 +59,12 @@ public class RocketMQAutoConfigurationTests { .isEqualTo("127.0.0.1:9876,127.0.0.1:9877"); RocketMQExtendedBindingProperties bindingProperties = context .getBean(RocketMQExtendedBindingProperties.class); - assertThat( - bindingProperties.getExtendedConsumerProperties("input2").getSubscription()) - .isEqualTo("tag1"); - assertThat(bindingProperties.getExtendedConsumerProperties("input2").getPush().getOrderly() - ).isFalse(); - assertThat(bindingProperties.getExtendedConsumerProperties("input1") - .getPush().getOrderly()).isTrue(); + assertThat(bindingProperties.getExtendedConsumerProperties("input2") + .getSubscription()).isEqualTo("tag1"); + assertThat(bindingProperties.getExtendedConsumerProperties("input2").getPush() + .getOrderly()).isFalse(); + assertThat(bindingProperties.getExtendedConsumerProperties("input1").getPush() + .getOrderly()).isTrue(); }); } From eaab60ebdb9b9d2bb866adb5b1d0efa1829385b7 Mon Sep 17 00:00:00 2001 From: tangyuewei <472680811@qq.com> Date: Tue, 30 Mar 2021 17:26:07 +0800 Subject: [PATCH 19/99] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E7=A9=BA=E6=A0=BC=EF=BC=8C=E6=9B=B4=E7=AC=A6=E5=90=88?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/bootstrap.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties index 4d880443f..c9c1c9f64 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties @@ -18,18 +18,18 @@ spring.cloud.nacos.password=nacos #spring.cloud.nacos.config.shared-data-ids=common.properties,base-common.properties ## recommended. -spring.cloud.nacos.config.shared-configs[0].data-id= test2.yaml +spring.cloud.nacos.config.shared-configs[0].data-id=test2.yaml spring.cloud.nacos.config.shared-configs[0].refresh=true ## the default value is 'DEFAULT_GROUP' , if not specified. -spring.cloud.nacos.config.shared-configs[0].group= GROUP_APP1 +spring.cloud.nacos.config.shared-configs[0].group=GROUP_APP1 ## not recommended. #spring.cloud.nacos.config.ext-config[0]=ext.properties ## recommended. -spring.cloud.nacos.config.extension-configs[0].data-id= extension1.properties +spring.cloud.nacos.config.extension-configs[0].data-id=extension1.properties spring.cloud.nacos.config.extension-configs[0].refresh=true -spring.cloud.nacos.config.extension-configs[1].data-id= test1.yml -spring.cloud.nacos.config.extension-configs[1].refresh= true +spring.cloud.nacos.config.extension-configs[1].data-id=test1.yml +spring.cloud.nacos.config.extension-configs[1].refresh=true From a869ef7ed651d983020106676682d515470ad888 Mon Sep 17 00:00:00 2001 From: eden-yuan <916928826@qq.com> Date: Wed, 31 Mar 2021 16:44:06 +0800 Subject: [PATCH 20/99] fix adoc --- spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc | 2 +- spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc index 540d42c41..305813e8f 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc @@ -57,7 +57,7 @@ Send messages: sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer ``` -Output when the message is successfuly sent: `SendResult [sendStatus=SEND_OK, msgId= ...` +Output when the message is successfully sent: `SendResult [sendStatus=SEND_OK, msgId= ...` Receive messages: diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc index 38c79c50e..ea68fd8a9 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/schedulerx.adoc @@ -82,7 +82,7 @@ Job Description: Empty Custom Parameters: Empty ---- -The job above is a “Simple Single-Server Job”, and speficied a Cron expression of "0 * * * * ?" . This means that the job will be executed once and once only in every minute. +The job above is a “Simple Single-Server Job”, and specified a Cron expression of "0 * * * * ?" . This means that the job will be executed once and once only in every minute. For more job types, refer to https://help.aliyun.com/document_detail/43136.html[SchedulerX Documentation]. From d653a1447667bfb7a8c6343511647ab5a11ed8b3 Mon Sep 17 00:00:00 2001 From: tangyuewei <472680811@qq.com> Date: Wed, 31 Mar 2021 16:54:15 +0800 Subject: [PATCH 21/99] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E6=A1=88=E4=BE=8B?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sentinel-example/sentinel-dubbo-example/readme-zh.md | 4 ++-- .../java/com/alibaba/cloud/examples/FooServiceConsumer.java | 4 ++-- .../main/java/com/alibaba/cloud/examples/FooServiceImpl.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/readme-zh.md index ca7459db7..b721036bd 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/readme-zh.md @@ -73,7 +73,7 @@ Provider端在application.properties文件中定义dubbo相关的配置,比如 定义具体的服务: - @Service( + @DubboService( version = "${foo.service.version}", application = "${dubbo.application.id}", protocol = "${dubbo.protocol.id}", @@ -111,7 +111,7 @@ Consumer端在服务调用之前,先定义限流规则。 根据Provider端中发布的定义,使用Dubbo的@Reference注解注入服务对应的Bean: - @Reference(version = "${foo.service.version}", application = "${dubbo.application.id}", + @DubboReference(version = "${foo.service.version}", application = "${dubbo.application.id}", path = "dubbo://localhost:12345", timeout = 30000) private FooService fooService; diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/src/main/java/com/alibaba/cloud/examples/FooServiceConsumer.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/src/main/java/com/alibaba/cloud/examples/FooServiceConsumer.java index c92f0bf10..877e4b81b 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/src/main/java/com/alibaba/cloud/examples/FooServiceConsumer.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-consumer-example/src/main/java/com/alibaba/cloud/examples/FooServiceConsumer.java @@ -16,14 +16,14 @@ package com.alibaba.cloud.examples; -import org.apache.dubbo.config.annotation.Reference; +import org.apache.dubbo.config.annotation.DubboReference; /** * @author fangjian */ public class FooServiceConsumer { - @Reference(version = "${foo.service.version}", + @DubboReference(version = "${foo.service.version}", application = "${dubbo.application.id}", url = "dubbo://localhost:12345?version=1.0.0", timeout = 30000) private FooService fooService; diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/src/main/java/com/alibaba/cloud/examples/FooServiceImpl.java b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/src/main/java/com/alibaba/cloud/examples/FooServiceImpl.java index 0d280ee8b..11ebe1516 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/src/main/java/com/alibaba/cloud/examples/FooServiceImpl.java +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-dubbo-example/sentinel-dubbo-provider-example/src/main/java/com/alibaba/cloud/examples/FooServiceImpl.java @@ -16,12 +16,12 @@ package com.alibaba.cloud.examples; -import org.apache.dubbo.config.annotation.Service; +import org.apache.dubbo.config.annotation.DubboService; /** * @author fangjian */ -@Service(version = "${foo.service.version}", application = "${dubbo.application.id}", +@DubboService(version = "${foo.service.version}", application = "${dubbo.application.id}", protocol = "${dubbo.protocol.id}", registry = "${dubbo.registry.id}") public class FooServiceImpl implements FooService { From 8894793ce14c9e81493592b29819adf31834451f Mon Sep 17 00:00:00 2001 From: theonefx Date: Mon, 12 Apr 2021 14:56:33 +0800 Subject: [PATCH 22/99] update readme --- README-zh.md | 15 ++++++++------- README.md | 16 +++++++++------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/README-zh.md b/README-zh.md index a52b26ffb..373608c4b 100644 --- a/README-zh.md +++ b/README-zh.md @@ -48,15 +48,16 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 更多组件请参考 [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap-zh.md)。 ## 如何构建 - -* master 分支对应的是 Spring Cloud Greenwich,最低支持 JDK 1.8。 +* 2020.0 分支对应的是 Spring Cloud 2020,最低支持 JDK 1.8。 +* master 分支对应的是 Spring Cloud Hoxton,最低支持 JDK 1.8。 +* greenwich 分支对应的是 Spring Cloud Greenwich,最低支持 JDK 1.8。 * finchley 分支对应的是 Spring Cloud Finchley,最低支持 JDK 1.8。 * 1.x 分支对应的是 Spring Cloud Edgware,最低支持 JDK 1.7。 Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone 到本地,然后执行以下命令: - +```bash ./mvnw install - +``` 执行完毕后,项目将被安装到本地 Maven 仓库。 ## 如何使用 @@ -64,7 +65,7 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone ### 如何引入依赖 如果需要使用已发布的版本,在 `dependencyManagement` 中添加如下配置。 - +```xml @@ -76,7 +77,7 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone - +``` 然后在 `dependencies` 中添加自己所需使用的依赖即可使用。 ## 演示 Demo @@ -111,7 +112,7 @@ Example 列表: * 2.0.x 版本适用于 Spring Boot 2.0.x * 2.1.x 版本适用于 Spring Boot 2.1.x * 2.2.x 版本适用于 Spring Boot 2.2.x - +* 2021.x 版本适用于 Spring Boot 2.4.x ## 社区交流 diff --git a/README.md b/README.md index df9a1d1aa..559683cfe 100644 --- a/README.md +++ b/README.md @@ -51,22 +51,23 @@ For more features, please refer to [Roadmap](https://github.com/alibaba/spring-c For more features please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md). ## How to build - -* **master branch**: Corresponds to Spring Cloud Greenwich & Spring Boot 2.x. JDK 1.8 or later versions are supported. -* **finchley branch**: Corresponds to Spring Cloud Finchley & Spring Boot 2.x. JDK 1.8 or later versions are supported. +* **2020.0 branch**: Corresponds to Spring Cloud 2020 & Spring Boot 2.4.x. JDK 1.8 or later versions are supported. +* **master branch**: Corresponds to Spring Cloud Hoxton & Spring Boot 2.2.x. JDK 1.8 or later versions are supported. +* **greenwich branch**: Corresponds to Spring Cloud Greenwich & Spring Boot 2.1.x. JDK 1.8 or later versions are supported. +* **finchley branch**: Corresponds to Spring Cloud Finchley & Spring Boot 2.0.x. JDK 1.8 or later versions are supported. * **1.x branch**: Corresponds to Spring Cloud Edgware & Spring Boot 1.x, JDK 1.7 or later versions are supported. Spring Cloud uses Maven for most build-related activities, and you should be able to get off the ground quite quickly by cloning the project you are interested in and typing: - +```bash ./mvnw install - +``` ## How to Use ### Add maven dependency These artifacts are available from Maven Central and Spring Release repository via BOM: - +```xml @@ -78,7 +79,7 @@ These artifacts are available from Maven Central and Spring Release repository v - +``` add the module in `dependencies`. @@ -118,6 +119,7 @@ As the interfaces and annotations of Spring Boot 1 and Spring Boot 2 have been c * 2.0.x for Spring Boot 2.0.x * 2.1.x for Spring Boot 2.1.x * 2.2.x for Spring Boot 2.2.x +* 2020.x for Spring Boot 2.4.x ## Code of Conduct This project is a sub-project of Spring Cloud, it adheres to the Contributor Covenant [code of conduct](https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io. From e3c791179b6b9e5a08493d6677b70431a7ac8c37 Mon Sep 17 00:00:00 2001 From: panzhi33 Date: Tue, 13 Apr 2021 17:51:24 +0800 Subject: [PATCH 23/99] =?UTF-8?q?=E5=8D=87=E7=BA=A7rocketmq-spring-boot-st?= =?UTF-8?q?arter=E7=89=88=E6=9C=AC=EF=BC=8C=E5=95=86=E4=B8=9A=E7=89=88?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E8=BD=A8=E8=BF=B9=E6=97=A0=E9=9C=80=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E9=85=8D=E7=BD=AE=E8=BD=A8=E8=BF=B9topic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../src/main/asciidoc-zh/rocketmq.adoc | 6 ++++++ .../src/main/asciidoc/rocketmq.adoc | 6 +++++- .../stream/binder/rocketmq/RocketMQBinderUtils.java | 7 +++++++ .../rocketmq/RocketMQMessageChannelBinder.java | 4 ++++ .../RocketMQComponent4BinderAutoConfiguration.java | 6 ++++++ .../consuming/RocketMQListenerBindingContainer.java | 5 +++++ .../RocketMQBinderConfigurationProperties.java | 13 +++++++++++++ .../rocketmq/RocketMQAutoConfigurationTests.java | 4 +++- 9 files changed, 50 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 0208a34b4..3fb48600e 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,7 @@ 4.0.1 - 2.0.2 + 2.0.4 3.7.0 diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq.adoc index 340da4d8b..7823c649f 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq.adoc @@ -249,6 +249,11 @@ spring.cloud.stream.rocketmq.binder.customized-trace-topic:: 消息轨迹开启后存储的 topic 名称。 + Default: `RMQ_SYS_TRACE_TOPIC`. ++ +spring.cloud.stream.rocketmq.binder.access-channel:: +商业版rocketmq消息轨迹topic自适应,值为CLOUD ++ +Default: null. ==== RocketMQ Consumer Properties @@ -346,6 +351,7 @@ NOTE: 0.1.2 & 0.2.2 & 0.9.0 才支持该功能 spring.cloud.stream.rocketmq.binder.access-key=YourAccessKey spring.cloud.stream.rocketmq.binder.secret-key=YourSecretKey spring.cloud.stream.rocketmq.binder.name-server=NameServerInMQ +spring.cloud.stream.rocketmq.binder.access-channel=CLOUD ``` NOTE: topic 和 group 请以 实例id% 为前缀进行配置。比如 topic 为 "test",需要配置成 "实例id%test" diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc index 540d42c41..08cad42cf 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/rocketmq.adoc @@ -246,7 +246,11 @@ spring.cloud.stream.rocketmq.binder.customized-trace-topic:: The trace topic for message trace. + Default: `RMQ_SYS_TRACE_TOPIC`. - ++ +spring.cloud.stream.rocketmq.binder.access-channel:: +The commercial version of rocketmq message trajectory topic is adaptive,the value is CLOUD ++ +Default: null. ==== RocketMQ Consumer Properties diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java index c7daff0ef..83a1c3604 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java @@ -76,6 +76,13 @@ public final class RocketMQBinderUtils { result.setEnableMsgTrace( rocketBinderConfigurationProperties.isEnableMsgTrace()); } + if (StringUtils.isEmpty(rocketMQProperties.getAccessChannel())) { + result.setAccessChannel(rocketBinderConfigurationProperties.getAccessChannel()); + } + else { + result.setAccessChannel( + rocketMQProperties.getAccessChannel()); + } return result; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java index e5a2e24b1..7d0d997cc 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java @@ -38,6 +38,7 @@ import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.remoting.RPCHook; @@ -158,6 +159,9 @@ public class RocketMQMessageChannelBinder extends producerProperties.getExtension().isRetryNextServer()); producer.setMaxMessageSize( producerProperties.getExtension().getMaxMessageSize()); + if (!StringUtils.isEmpty(mergedProperties.getAccessChannel())) { + producer.setAccessChannel(AccessChannel.valueOf(mergedProperties.getAccessChannel())); + } rocketMQTemplate.setProducer(producer); if (producerProperties.isPartitioned()) { rocketMQTemplate diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java index 6968ead86..5b1fb513a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java @@ -20,6 +20,7 @@ import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; import org.apache.rocketmq.spring.config.RocketMQConfigUtils; @@ -59,6 +60,8 @@ public class RocketMQComponent4BinderAutoConfiguration { "${spring.cloud.stream.rocketmq.binder.access-key:${rocketmq.producer.access-key:}}"); String sk = environment.resolveRequiredPlaceholders( "${spring.cloud.stream.rocketmq.binder.secret-key:${rocketmq.producer.secret-key:}}"); + String accessChannel = environment.resolveRequiredPlaceholders( + "${spring.cloud.stream.rocketmq.binder.access-channel:${rocketmq.access-channel:}}"); if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { producer = new DefaultMQProducer(RocketMQBinderConstants.DEFAULT_GROUP, new AclClientRPCHook(new SessionCredentials(ak, sk))); @@ -71,6 +74,9 @@ public class RocketMQComponent4BinderAutoConfiguration { configNameServer = RocketMQBinderConstants.DEFAULT_NAME_SERVER; } producer.setNamesrvAddr(configNameServer); + if (!StringUtils.isEmpty(configNameServer)) { + producer.setAccessChannel(AccessChannel.valueOf(accessChannel)); + } return producer; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java index fb167c697..ecf5f2a01 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java @@ -26,6 +26,7 @@ import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerPrope import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.MessageSelector; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; @@ -238,6 +239,10 @@ public class RocketMQListenerBindingContainer consumer.setConsumeThreadMax(rocketMQConsumerProperties.getConcurrency()); consumer.setConsumeThreadMin(rocketMQConsumerProperties.getConcurrency()); + if (!StringUtils.isEmpty(rocketBinderConfigurationProperties.getAccessChannel())) { + consumer.setAccessChannel(AccessChannel.valueOf(rocketBinderConfigurationProperties.getAccessChannel())); + } + switch (messageModel) { case BROADCASTING: consumer.setMessageModel( diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java index 3a9dcb403..686b46a7e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java @@ -47,6 +47,11 @@ public class RocketMQBinderConfigurationProperties { */ private String secretKey; + /** + * Enum type for accessChannel, values: LOCAL, CLOUD + */ + private String accessChannel; + /** * Switch flag instance for message trace. */ @@ -82,6 +87,14 @@ public class RocketMQBinderConfigurationProperties { this.secretKey = secretKey; } + public String getAccessChannel() { + return accessChannel; + } + + public void setAccessChannel(String accessChannel) { + this.accessChannel = accessChannel; + } + public boolean isEnableMsgTrace() { return enableMsgTrace; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java index 8207f9893..6feee3b97 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java @@ -50,7 +50,8 @@ public class RocketMQAutoConfigurationTests { "spring.cloud.stream.bindings.input2.content-type=application/json", "spring.cloud.stream.bindings.input2.group=test-group2", "spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false", - "spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tag1"); + "spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tag1", + "spring.cloud.stream.rocketmq.binder.access-channel=CLOUD"); @Test public void testProperties() { @@ -68,6 +69,7 @@ public class RocketMQAutoConfigurationTests { .getOrderly()).isFalse(); assertThat(bindingProperties.getExtendedConsumerProperties("input1") .getOrderly()).isTrue(); + assertThat(binderConfigurationProperties.getAccessChannel()).isEqualTo("CLOUD"); }); } From f8ee5dc71c9d173f6062915156bd631ebbf40909 Mon Sep 17 00:00:00 2001 From: panzhi33 Date: Tue, 13 Apr 2021 18:36:19 +0800 Subject: [PATCH 24/99] fix style code --- .../properties/RocketMQBinderConfigurationProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java index 686b46a7e..ae735840c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java @@ -48,7 +48,7 @@ public class RocketMQBinderConfigurationProperties { private String secretKey; /** - * Enum type for accessChannel, values: LOCAL, CLOUD + * Enum type for accessChannel, values: LOCAL, CLOUD. */ private String accessChannel; From 3ad550f211e652677b9776766944b5249f0fa6ab Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 14 Apr 2021 09:59:49 +0800 Subject: [PATCH 25/99] bugfix invokers metadata tag error --- .../cloud/dubbo/registry/DubboCloudRegistry.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index 2101a217b..04d9c99e5 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -308,6 +308,16 @@ public class DubboCloudRegistry extends FailbackRegistry { String protocol = templateURL.getProtocol(); Integer port = repository.getDubboProtocolPort(serviceInstance, protocol); + + // reserve tag + String tag = null; + List urls = jsonUtils.toURLs(serviceInstance.getMetadata() + .get("dubbo.metadata-service.urls")); + if (urls != null && urls.size() > 0) { + Map parameters = urls.get(0).getParameters(); + tag = parameters.get("dubbo.tag"); + } + if (Objects.equals(templateURL.getHost(), host) && Objects.equals(templateURL.getPort(), port)) { // use // templateURL @@ -331,7 +341,8 @@ public class DubboCloudRegistry extends FailbackRegistry { // the template // URL .setHost(host) // reset the host - .setPort(port); // reset the port + .setPort(port) // reset the port + .addParameter("dubbo.tag", tag); // reset the tag return clonedURLBuilder.build(); } From 3ee8d4bf562fef6ce32c2f033534baa5ebd9dbe2 Mon Sep 17 00:00:00 2001 From: Spike Date: Thu, 15 Apr 2021 13:29:15 +0800 Subject: [PATCH 26/99] =?UTF-8?q?=E4=BA=8B=E5=8A=A1=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E6=96=B9=E5=BC=8F=E5=8F=98=E6=9B=B4=E4=B8=BA?= =?UTF-8?q?producerType=3DTrans?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties index 08ab26ca0..428991930 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties @@ -9,7 +9,7 @@ spring.cloud.stream.rocketmq.bindings.output1.producer.sync=true spring.cloud.stream.bindings.output2.destination=TransactionTopic spring.cloud.stream.bindings.output2.content-type=application/json -spring.cloud.stream.rocketmq.bindings.output2.producer.transactional=true +spring.cloud.stream.rocketmq.bindings.output2.producer.producerType=Trans spring.cloud.stream.rocketmq.bindings.output2.producer.group=myTxProducerGroup spring.cloud.stream.rocketmq.bindings.output2.producer.transactionListener=myTransactionListener From 1f9f10ce901b8dc538a67a6dee143470e9d24d1c Mon Sep 17 00:00:00 2001 From: Spike Date: Thu, 15 Apr 2021 13:32:13 +0800 Subject: [PATCH 27/99] =?UTF-8?q?issue#2040=20=E7=A7=BB=E9=99=A4RocketMQCo?= =?UTF-8?q?nfigBeanPostProcessor=E5=9C=A8RocketMQBinderAutoConfiguration?= =?UTF-8?q?=E7=B1=BB=E4=B8=AD=E7=9A=84=E6=B3=A8=E5=85=A5=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E9=80=9A=E8=BF=87spirng.factories=E6=B3=A8=E5=85=A5?= =?UTF-8?q?=EF=BC=8C=E5=8E=9F=E6=9D=A5=E6=98=AF=E9=80=9A=E8=BF=87spirng.bi?= =?UTF-8?q?nders=E7=BB=8F=E8=BF=87spring-cloud-stream=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../autoconfigurate/RocketMQBinderAutoConfiguration.java | 5 ----- .../src/main/resources/META-INF/spring.factories | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java index ec47e951a..2ddcaf8a1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java @@ -50,11 +50,6 @@ public class RocketMQBinderAutoConfiguration { @Autowired private RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties; - @Bean - public RocketMQConfigBeanPostProcessor rocketMQConfigBeanPostProcessor() { - return new RocketMQConfigBeanPostProcessor(); - } - @Bean(RocketMQMessageConverter.DEFAULT_NAME) @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME }) public CompositeMessageConverter rocketMQMessageConverter() { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories index e18651dc4..3fa0357ad 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration +com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration,\ +com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor \ No newline at end of file From ba80fcac2f3b5a4c71bd8f9aeb696ab9b0804a05 Mon Sep 17 00:00:00 2001 From: Spike Date: Thu, 15 Apr 2021 15:40:39 +0800 Subject: [PATCH 28/99] #checkstyle removed unused import --- .../autoconfigurate/RocketMQBinderAutoConfiguration.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java index 2ddcaf8a1..85ca379e5 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java @@ -19,7 +19,6 @@ package com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate; import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder; import com.alibaba.cloud.stream.binder.rocketmq.actuator.RocketMQBinderHealthIndicator; import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter; -import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner; From 10e9a99d08b1c317cc296e7f35721393b7ca2a6f Mon Sep 17 00:00:00 2001 From: Spike Date: Fri, 30 Apr 2021 10:07:51 +0800 Subject: [PATCH 29/99] =?UTF-8?q?issue#2040=20=E8=BD=AC=E7=A7=BBRocketMQCo?= =?UTF-8?q?nfigBeanPostProcessor=E5=92=8CCompositeMessageConverter?= =?UTF-8?q?=E4=BB=8ERocketMQBinderAutoConfiguration=E8=87=B3ExtendedBindin?= =?UTF-8?q?gHandlerMappingsProviderConfiguration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 从RocketMQBinderAutoConfiguration中注入会被stream代理生成一个新的上下文层,上层使用者和它会被隔离导致无法使用 原来是通过spirng.binders经过spring-cloud-stream代理 --- ...dingHandlerMappingsProviderConfiguration.java | 16 ++++++++++++++++ .../RocketMQBinderAutoConfiguration.java | 9 --------- .../src/main/resources/META-INF/spring.factories | 3 +-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java index eb6e6ce52..626ab7b16 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java @@ -19,10 +19,14 @@ package com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate; import java.util.HashMap; import java.util.Map; +import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter; +import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.cloud.stream.config.BindingHandlerAdvise.MappingsProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.converter.CompositeMessageConverter; @Configuration public class ExtendedBindingHandlerMappingsProviderConfiguration { @@ -42,4 +46,16 @@ public class ExtendedBindingHandlerMappingsProviderConfiguration { }; } + @Bean + public RocketMQConfigBeanPostProcessor rocketMQConfigBeanPostProcessor() { + return new RocketMQConfigBeanPostProcessor(); + } + + + @Bean(RocketMQMessageConverter.DEFAULT_NAME) + @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME }) + public CompositeMessageConverter rocketMQMessageConverter() { + return new RocketMQMessageConverter().getMessageConverter(); + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java index 85ca379e5..b9b85db24 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java @@ -18,7 +18,6 @@ package com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate; import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder; import com.alibaba.cloud.stream.binder.rocketmq.actuator.RocketMQBinderHealthIndicator; -import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties; import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner; @@ -26,11 +25,9 @@ import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvis import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; 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; -import org.springframework.messaging.converter.CompositeMessageConverter; /** * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681 . @@ -49,12 +46,6 @@ public class RocketMQBinderAutoConfiguration { @Autowired private RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties; - @Bean(RocketMQMessageConverter.DEFAULT_NAME) - @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME }) - public CompositeMessageConverter rocketMQMessageConverter() { - return new RocketMQMessageConverter().getMessageConverter(); - } - @Bean @ConditionalOnEnabledHealthIndicator("rocketmq") @ConditionalOnClass(name = "org.springframework.boot.actuate.health.HealthIndicator") diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories index 3fa0357ad..b67a42530 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories @@ -1,3 +1,2 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration,\ -com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor \ No newline at end of file +com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration \ No newline at end of file From c138dd17ac54af9a1d9b9630a2afce2fd0f1c9c2 Mon Sep 17 00:00:00 2001 From: Spike Date: Fri, 30 Apr 2021 10:29:05 +0800 Subject: [PATCH 30/99] fix check style --- .../ExtendedBindingHandlerMappingsProviderConfiguration.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java index 626ab7b16..ce48fccb0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java @@ -21,6 +21,7 @@ import java.util.Map; import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter; import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor; + import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.cloud.stream.config.BindingHandlerAdvise.MappingsProvider; From 3d5eaefe1c3151e79cdc93673b85f77fd817b3ab Mon Sep 17 00:00:00 2001 From: theonefx Date: Wed, 12 May 2021 09:36:33 +0800 Subject: [PATCH 31/99] resolve @order not effect when handle ServiceInstanceChangedEvent --- .../dubbo/registry/DubboCloudRegistry.java | 71 ++++++++++--------- .../ServiceInstanceChangeListener.java | 35 +++++++++ 2 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ServiceInstanceChangeListener.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index 04d9c99e5..81464733d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -45,12 +45,10 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; import org.springframework.util.CollectionUtils; import static java.lang.String.format; import static java.util.Collections.emptyList; -import static java.util.stream.StreamSupport.stream; import static org.apache.dubbo.common.URLBuilder.from; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; @@ -188,18 +186,24 @@ public class DubboCloudRegistry extends FailbackRegistry { // Async subscription registerServiceInstancesChangedListener(url, - new ApplicationListener() { + new ServiceInstanceChangeListener() { - private final URL url2subscribe = url; + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } @Override - @Order public void onApplicationEvent(ServiceInstancesChangedEvent event) { + Set serviceNames = getServices(url); String serviceName = event.getServiceName(); if (serviceNames.contains(serviceName)) { + logger.debug( + "handle serviceInstanceChange of general service, serviceName = {}, subscribeUrl={}", + event.getServiceName(), url.getServiceKey()); subscribeURLs(url, serviceNames, listener); } } @@ -419,11 +423,6 @@ public class DubboCloudRegistry extends FailbackRegistry { listener.notify(subscribedURLs); } - private List getServiceInstances(Iterable serviceNames) { - return stream(serviceNames.spliterator(), false).map(this::getServiceInstances) - .flatMap(Collection::stream).collect(Collectors.toList()); - } - private List getServiceInstances(String serviceName) { return hasText(serviceName) ? doGetServiceInstances(serviceName) : emptyList(); } @@ -471,27 +470,38 @@ public class DubboCloudRegistry extends FailbackRegistry { private void subscribeDubboMetadataServiceURLs(URL subscribedURL, NotifyListener listener) { - // Sync subscription - subscribeDubboMetadataServiceURLs(subscribedURL, listener, - getServiceName(subscribedURL)); - // Sync subscription if (containsProviderCategory(subscribedURL)) { + + subscribeDubboMetadataServiceURLs(subscribedURL, listener, + getServiceName(subscribedURL)); + registerServiceInstancesChangedListener(subscribedURL, - new ApplicationListener() { + new ServiceInstanceChangeListener() { - private final URL url2subscribe = subscribedURL; + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 1; + } @Override - @Order(Ordered.LOWEST_PRECEDENCE - 1) public void onApplicationEvent( ServiceInstancesChangedEvent event) { String sourceServiceName = event.getServiceName(); + List serviceInstances = event + .getServiceInstances(); String serviceName = getServiceName(subscribedURL); if (Objects.equals(sourceServiceName, serviceName)) { + logger.debug( + "handle serviceInstanceChange of metadata service, serviceName = {}, subscribeUrl={}", + event.getServiceName(), + subscribedURL.getServiceKey()); + + // only update serviceInstances of the specified + // serviceName subscribeDubboMetadataServiceURLs(subscribedURL, listener, - sourceServiceName); + sourceServiceName, serviceInstances); } } @@ -509,34 +519,25 @@ public class DubboCloudRegistry extends FailbackRegistry { } private void subscribeDubboMetadataServiceURLs(URL subscribedURL, - NotifyListener listener, String serviceName) { + NotifyListener listener, String serviceName, + List serviceInstances) { String serviceInterface = subscribedURL.getServiceInterface(); String version = subscribedURL.getParameter(VERSION_KEY); String protocol = subscribedURL.getParameter(PROTOCOL_KEY); - List serviceInstances = getServiceInstances(serviceName); - List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, serviceInterface, version, protocol); notifyAllSubscribedURLs(subscribedURL, urls, listener); } - // private void subscribeDubboMetadataServiceURLs(URL subscribedURL, - // NotifyListener listener, Set serviceNames) { - // - // String serviceInterface = subscribedURL.getServiceInterface(); - // String version = subscribedURL.getParameter(VERSION_KEY); - // String protocol = subscribedURL.getParameter(PROTOCOL_KEY); - // - // List serviceInstances = getServiceInstances(serviceNames); - // - // List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, - // serviceInterface, version, protocol); - // - // notifyAllSubscribedURLs(subscribedURL, urls, listener); - // } + private void subscribeDubboMetadataServiceURLs(URL subscribedURL, + NotifyListener listener, String serviceName) { + List serviceInstances = getServiceInstances(serviceName); + subscribeDubboMetadataServiceURLs(subscribedURL, listener, serviceName, + serviceInstances); + } private boolean containsProviderCategory(URL subscribedURL) { String category = subscribedURL.getParameter(CATEGORY_KEY); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ServiceInstanceChangeListener.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ServiceInstanceChangeListener.java new file mode 100644 index 000000000..123214831 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ServiceInstanceChangeListener.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.registry; + +import com.alibaba.cloud.dubbo.registry.event.ServiceInstancesChangedEvent; + +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; + +/** + * The interface of ServiceInstanceChange event Listener. + * + * @author theonefx + * @see ServiceInstancesChangedEvent + * @see Ordered + * @see ApplicationListener + */ +public interface ServiceInstanceChangeListener + extends ApplicationListener, Ordered { + +} From f8161141224157aea0bcc08b36332aa2c2e58a80 Mon Sep 17 00:00:00 2001 From: theonefx Date: Wed, 12 May 2021 20:27:50 +0800 Subject: [PATCH 32/99] re subscribe when failed --- .../cloud/dubbo/env/DubboCloudProperties.java | 20 +++++ .../dubbo/registry/DubboCloudRegistry.java | 65 +++++++++++++-- .../registry/ReSubscribeMetadataJob.java | 82 +++++++++++++++++++ .../registry/SpringCloudRegistryFactory.java | 4 +- 4 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java index 577d19e59..5135c5a8c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/env/DubboCloudProperties.java @@ -51,6 +51,10 @@ public class DubboCloudProperties { private String registryType = DUBBO_CLOUD_REGISTRY_PROPERTY_VALUE; + private int maxReSubscribeMetadataTimes = 1000; + + private int reSubscribeMetadataIntervial = 5; + public String getSubscribedServices() { return subscribedServices; } @@ -91,4 +95,20 @@ public class DubboCloudProperties { this.registryType = registryType; } + public int getMaxReSubscribeMetadataTimes() { + return maxReSubscribeMetadataTimes; + } + + public void setMaxReSubscribeMetadataTimes(int maxReSubscribeMetadataTimes) { + this.maxReSubscribeMetadataTimes = maxReSubscribeMetadataTimes; + } + + public int getReSubscribeMetadataIntervial() { + return reSubscribeMetadataIntervial; + } + + public void setReSubscribeMetadataIntervial(int reSubscribeMetadataIntervial) { + this.reSubscribeMetadataIntervial = reSubscribeMetadataIntervial; + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index 81464733d..b7768c307 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -23,6 +23,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -108,11 +111,23 @@ public class DubboCloudRegistry extends FailbackRegistry { private final String currentApplicationName; + private final Map urlNotifyListenerMap = new ConcurrentHashMap<>(); + + private final Map reConnectJobMap = new ConcurrentHashMap<>(); + + private final ScheduledThreadPoolExecutor reConnectPool = new ScheduledThreadPoolExecutor( + 2); + + private final int maxReSubscribeMetadataTimes; + + private final int reSubscribeMetadataIntervial; + public DubboCloudRegistry(URL url, DiscoveryClient discoveryClient, DubboServiceMetadataRepository repository, DubboMetadataServiceProxy dubboMetadataConfigServiceProxy, JSONUtils jsonUtils, DubboGenericServiceFactory dubboGenericServiceFactory, - ConfigurableApplicationContext applicationContext) { + ConfigurableApplicationContext applicationContext, + int maxReSubscribeMetadataTimes, int reSubscribeMetadataIntervial) { super(url); this.servicesLookupInterval = url @@ -125,6 +140,11 @@ public class DubboCloudRegistry extends FailbackRegistry { this.applicationContext = applicationContext; this.dubboMetadataUtils = getBean(DubboMetadataUtils.class); this.currentApplicationName = dubboMetadataUtils.getCurrentApplicationName(); + this.maxReSubscribeMetadataTimes = maxReSubscribeMetadataTimes; + this.reSubscribeMetadataIntervial = reSubscribeMetadataIntervial; + + reConnectPool.setKeepAliveTime(10, TimeUnit.MINUTES); + reConnectPool.allowCoreThreadTimeOut(true); } private T getBean(Class beanClass) { @@ -175,6 +195,7 @@ public class DubboCloudRegistry extends FailbackRegistry { } else { // for general Dubbo Services subscribeURLs(url, listener); + urlNotifyListenerMap.put(url, listener); } } @@ -204,7 +225,16 @@ public class DubboCloudRegistry extends FailbackRegistry { logger.debug( "handle serviceInstanceChange of general service, serviceName = {}, subscribeUrl={}", event.getServiceName(), url.getServiceKey()); - subscribeURLs(url, serviceNames, listener); + try { + subscribeURLs(url, serviceNames, listener); + reConnectJobMap.remove(serviceName); + } + catch (Exception e) { + logger.warn(String.format( + "subscribeURLs failed, serviceName = %s, try reSubscribe again", + serviceName), e); + addReSubscribeMetadataJob(serviceName, 0); + } } } @@ -216,8 +246,19 @@ public class DubboCloudRegistry extends FailbackRegistry { }); } - private void subscribeURLs(URL url, Set serviceNames, - NotifyListener listener) { + void addReSubscribeMetadataJob(String serviceName, int count) { + if (count > maxReSubscribeMetadataTimes) { + logger.error( + "reSubscribe failed too many times, serviceName = {}, count = {}", + serviceName, count); + return; + } + ReSubscribeMetadataJob job = new ReSubscribeMetadataJob(serviceName, this, count); + reConnectJobMap.put(serviceName, job); + reConnectPool.schedule(job, reSubscribeMetadataIntervial, TimeUnit.SECONDS); + } + + void subscribeURLs(URL url, Set serviceNames, NotifyListener listener) { List subscribedURLs = new LinkedList<>(); @@ -393,7 +434,7 @@ public class DubboCloudRegistry extends FailbackRegistry { return metadata.containsKey(METADATA_SERVICE_URLS_PROPERTY_NAME); } - private Set getServices(URL url) { + Set getServices(URL url) { Set subscribedServices = repository.getSubscribedServices(); // TODO Add the filter feature return subscribedServices; @@ -470,12 +511,12 @@ public class DubboCloudRegistry extends FailbackRegistry { private void subscribeDubboMetadataServiceURLs(URL subscribedURL, NotifyListener listener) { + subscribeDubboMetadataServiceURLs(subscribedURL, listener, + getServiceName(subscribedURL)); + // Sync subscription if (containsProviderCategory(subscribedURL)) { - subscribeDubboMetadataServiceURLs(subscribedURL, listener, - getServiceName(subscribedURL)); - registerServiceInstancesChangedListener(subscribedURL, new ServiceInstanceChangeListener() { @@ -558,6 +599,14 @@ public class DubboCloudRegistry extends FailbackRegistry { return ADMIN_PROTOCOL.equals(url.getProtocol()); } + public Map getUrlNotifyListenerMap() { + return urlNotifyListenerMap; + } + + public Map getReConnectJobMap() { + return reConnectJobMap; + } + protected boolean isDubboMetadataServiceURL(URL url) { return DUBBO_METADATA_SERVICE_CLASS_NAME.equals(url.getServiceInterface()); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java new file mode 100644 index 000000000..68e0f42cb --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java @@ -0,0 +1,82 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.registry; + +import java.util.Map; +import java.util.Set; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.NotifyListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * For re subscribe URL from provider. + * + * @author theonefx + */ +public class ReSubscribeMetadataJob implements Runnable { + + protected final Logger logger = LoggerFactory.getLogger(ReSubscribeMetadataJob.class); + + private final String serviceName; + + private final DubboCloudRegistry dubboCloudRegistry; + + private final int errorCounts; + + public ReSubscribeMetadataJob(String serviceName, + DubboCloudRegistry dubboCloudRegistry, int errorCounts) { + this.errorCounts = errorCounts; + this.serviceName = serviceName; + this.dubboCloudRegistry = dubboCloudRegistry; + } + + public ReSubscribeMetadataJob(String serviceName, + DubboCloudRegistry dubboCloudRegistry) { + this(serviceName, dubboCloudRegistry, 0); + } + + @Override + public void run() { + if (dubboCloudRegistry.getReConnectJobMap().get(serviceName) != this) { + return; + } + try { + for (Map.Entry entry : dubboCloudRegistry + .getUrlNotifyListenerMap().entrySet()) { + doRun(entry.getKey(), entry.getValue()); + } + dubboCloudRegistry.getReConnectJobMap().remove(serviceName); + } + catch (Exception e) { + logger.warn(String.format( + "reSubscribe failed, serviceName = %s, try refresh again", + serviceName), e); + dubboCloudRegistry.addReSubscribeMetadataJob(serviceName, errorCounts + 1); + } + } + + private void doRun(URL url, NotifyListener listener) { + Set serviceNames = dubboCloudRegistry.getServices(url); + + if (serviceNames.contains(serviceName)) { + dubboCloudRegistry.subscribeURLs(url, serviceNames, listener); + } + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java index f8b7896dc..d13c5179c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java @@ -100,7 +100,9 @@ public class SpringCloudRegistryFactory extends AbstractRegistryFactory { default: registry = new DubboCloudRegistry(url, discoveryClient, dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy, - jsonUtils, dubboGenericServiceFactory, applicationContext); + jsonUtils, dubboGenericServiceFactory, applicationContext, + dubboCloudProperties.getMaxReSubscribeMetadataTimes(), + dubboCloudProperties.getReSubscribeMetadataIntervial()); break; } From cf71b7aa26764c98009fbf5cd2ef34963e111e02 Mon Sep 17 00:00:00 2001 From: theonefx Date: Wed, 12 May 2021 22:23:24 +0800 Subject: [PATCH 33/99] add more log --- .../com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java | 4 ++++ .../alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java | 2 ++ 2 files changed, 6 insertions(+) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index b7768c307..cce75ba39 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -297,6 +297,10 @@ public class DubboCloudRegistry extends FailbackRegistry { serviceName)); } } + else { + logger.debug("subscribe from serviceName = {}, size = {}", serviceName, + serviceInstances.size()); + } List exportedURLs = getExportedURLs(subscribedURL, serviceName, serviceInstances); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java index 68e0f42cb..74d917f07 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java @@ -57,6 +57,8 @@ public class ReSubscribeMetadataJob implements Runnable { return; } try { + logger.info("reSubscribe, serviceName = {}, count = {}", serviceName, + errorCounts); for (Map.Entry entry : dubboCloudRegistry .getUrlNotifyListenerMap().entrySet()) { doRun(entry.getKey(), entry.getValue()); From 39d6a3e1ae884af901e856f7682233143fb5fe5f Mon Sep 17 00:00:00 2001 From: qukun Date: Wed, 19 May 2021 15:45:54 +0800 Subject: [PATCH 34/99] fix word "namespae" -> "namespace" --- PULL_REQUEST_TEMPLATE.md | 8 ++++---- .../src/main/asciidoc-zh/nacos-config.adoc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 7261357c5..2286f0578 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,15 +1,15 @@ ### Describe what this PR does / why we need it - +fix words that we can read more friendly ### Does this pull request fix one issue? - +no ### Describe how you did it - +when I read wiki-document, I find it ### Describe how to verify it - +By google translate ### Special notes for reviews diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc index 4f7de3127..0332d68c5 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc @@ -260,7 +260,7 @@ Nacos 内部有 https://nacos.io/zh-cn/docs/concepts.html[Namespace 的概念]: [quote] 用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 -在没有明确指定 `${spring.cloud.nacos.config.namespace}` 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespae。如果需要使用自定义的命名空间,可以通过以下配置来实现: +在没有明确指定 `${spring.cloud.nacos.config.namespace}` 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespace。如果需要使用自定义的命名空间,可以通过以下配置来实现: [source,properties] ---- spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7 From 0612c9c7266d41ff6de670581486215691a94ef4 Mon Sep 17 00:00:00 2001 From: captainkun <44936259+captainkun@users.noreply.github.com> Date: Wed, 19 May 2021 16:38:18 +0800 Subject: [PATCH 35/99] Update PULL_REQUEST_TEMPLATE.md rollback --- PULL_REQUEST_TEMPLATE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 2286f0578..7261357c5 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,15 +1,15 @@ ### Describe what this PR does / why we need it -fix words that we can read more friendly + ### Does this pull request fix one issue? -no + ### Describe how you did it -when I read wiki-document, I find it + ### Describe how to verify it -By google translate + ### Special notes for reviews From c3d393b09e4c74b91a191494115c85f2a1ab5d70 Mon Sep 17 00:00:00 2001 From: eden-yuan <916928826@qq.com> Date: Mon, 24 May 2021 15:22:25 +0800 Subject: [PATCH 36/99] =?UTF-8?q?1.=20try=E6=89=A7=E8=A1=8C=E5=90=8E?= =?UTF-8?q?=E6=97=A0catch=20=E4=BE=9D=E7=84=B6=E6=98=AFreturn=20null=202.?= =?UTF-8?q?=20=E5=8F=98=E9=87=8F=E5=90=8E=E7=BB=AD=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E5=88=B0=E5=8F=AF=E5=AE=9A=E4=B9=89=E5=88=B0=20try=20=E5=86=85?= =?UTF-8?q?=203.=20=E6=B7=BB=E5=8A=A0UP/DOWN=20=E5=B8=B8=E9=87=8F=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/DataSourcePropertiesConfiguration.java | 1 - .../datasource/converter/SentinelConverter.java | 3 +-- .../nacos/endpoint/NacosConfigHealthIndicator.java | 14 ++++++++++++-- .../health/NacosDiscoveryHealthIndicator.java | 14 ++++++++++++-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/DataSourcePropertiesConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/DataSourcePropertiesConfiguration.java index a0a5526f3..330a0a04b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/DataSourcePropertiesConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/DataSourcePropertiesConfiguration.java @@ -132,7 +132,6 @@ public class DataSourcePropertiesConfiguration { if (!ObjectUtils.isEmpty(field.get(this))) { return field.getName(); } - return null; } catch (IllegalAccessException e) { // won't happen diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/SentinelConverter.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/SentinelConverter.java index 306dd1a0b..1cc8c725d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/SentinelConverter.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/SentinelConverter.java @@ -86,9 +86,8 @@ public abstract class SentinelConverter }); for (Object obj : sourceArray) { - String item = null; try { - item = objectMapper.writeValueAsString(obj); + String item = objectMapper.writeValueAsString(obj); Optional.ofNullable(convertRule(item)) .ifPresent(convertRule -> ruleCollection.add(convertRule)); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigHealthIndicator.java index affd0139f..37e3c2463 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigHealthIndicator.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/endpoint/NacosConfigHealthIndicator.java @@ -32,6 +32,16 @@ public class NacosConfigHealthIndicator extends AbstractHealthIndicator { private final ConfigService configService; + /** + * status up . + */ + private final String STATUS_UP = "UP"; + + /** + * status down . + */ + private final String STATUS_DOWN = "DOWN"; + public NacosConfigHealthIndicator(ConfigService configService) { this.configService = configService; } @@ -43,10 +53,10 @@ public class NacosConfigHealthIndicator extends AbstractHealthIndicator { // Set the status to Builder builder.status(status); switch (status) { - case "UP": + case STATUS_UP: builder.up(); break; - case "DOWN": + case STATUS_DOWN: builder.down(); break; default: diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/actuate/health/NacosDiscoveryHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/actuate/health/NacosDiscoveryHealthIndicator.java index 5a925ec30..32e523bb1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/actuate/health/NacosDiscoveryHealthIndicator.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/discovery/actuate/health/NacosDiscoveryHealthIndicator.java @@ -31,6 +31,16 @@ import org.springframework.boot.actuate.health.HealthIndicator; */ public class NacosDiscoveryHealthIndicator extends AbstractHealthIndicator { + /** + * status up. + */ + private static final String STATUS_UP = "UP"; + + /** + * status down. + */ + private static final String STATUS_DOWN = "DOWN"; + private final NamingService namingService; public NacosDiscoveryHealthIndicator(NamingService namingService) { @@ -44,10 +54,10 @@ public class NacosDiscoveryHealthIndicator extends AbstractHealthIndicator { // Set the status to Builder builder.status(status); switch (status) { - case "UP": + case STATUS_UP: builder.up(); break; - case "DOWN": + case STATUS_DOWN: builder.down(); break; default: From 66bdd10ac93824296cf3cfe555af96734cd2918c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E9=B9=8F?= Date: Mon, 24 May 2021 22:32:20 +0800 Subject: [PATCH 37/99] =?UTF-8?q?add=20Wiki=20=E6=96=87=E6=A1=A3=E2=80=9C?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=9A=84=E4=BC=98=E5=85=88=E7=BA=A7=E2=80=9D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E5=AE=B9=E6=98=93=E6=B7=B7=E6=B7=86=E7=9A=84?= =?UTF-8?q?=E8=A1=A8=E8=BF=B0=20#1874?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/asciidoc-zh/nacos-config.adoc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc index 4f7de3127..0c1237629 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc @@ -348,7 +348,13 @@ Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置 * B: 通过 `spring.cloud.nacos.config.ext-config[n].data-id` 的方式支持多个扩展 Data Id 的配置 * C: 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置 -当三种方式共同使用时,他们的一个优先级关系是:A < B < C +当三种方式共同使用时,他们的一个优先级关系是: + +->A为优先级最高的 + +->B的优先级低于A, + +->C的优先级是最低的 === Nacos Config 对外暴露的 Endpoint From a0ad31f11c94eb3ac85657a91bd01ca265517b7e Mon Sep 17 00:00:00 2001 From: theonefx Date: Thu, 27 May 2021 11:52:48 +0800 Subject: [PATCH 38/99] update nacos-client to 1.2.4 --- spring-cloud-alibaba-dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index e1e58b0b1..1adf679d2 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -21,7 +21,7 @@ 2.2.6-SNAPSHOT 1.8.1 1.3.0 - 1.4.1 + 1.4.2 0.8.0 1.0.10 From 479540c8357ef8e95b9005ed4bc8aaff3f2ca4d7 Mon Sep 17 00:00:00 2001 From: theonefx Date: Tue, 1 Jun 2021 11:15:14 +0800 Subject: [PATCH 39/99] optimize dubbo registry --- .../metadata/DefaultMetadataParamsFilter.java | 55 ++ .../dubbo/metadata/MetadataParamsFilter.java | 35 + .../dubbo/metadata/RevisionResolver.java | 74 ++ .../cloud/dubbo/metadata/ServiceInfo.java | 351 +++++++++ .../DubboServiceMetadataRepository.java | 71 +- .../AbstractServiceSubscribeHandler.java | 90 +++ .../dubbo/registry/DubboCloudRegistry.java | 673 ++++++++---------- .../GenearalServiceSubscribeHandler.java | 270 +++++++ .../MetadataServiceSubscribeHandler.java | 75 ++ .../dubbo/registry/ReSubscribeManager.java | 125 ++++ .../registry/ReSubscribeMetadataJob.java | 84 --- .../registry/SpringCloudRegistryFactory.java | 6 +- ....cloud.dubbo.metadata.MetadataParamsFilter | 1 + 13 files changed, 1419 insertions(+), 491 deletions(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractServiceSubscribeHandler.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeManager.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java new file mode 100644 index 000000000..53d090f1c --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java @@ -0,0 +1,55 @@ +/* + * 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; + +import org.apache.dubbo.common.extension.Activate; + +import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.remoting.Constants.CODEC_KEY; +import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY; +import static org.apache.dubbo.remoting.Constants.EXCHANGER_KEY; +import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY; +import static org.apache.dubbo.rpc.Constants.DEPRECATED_KEY; +import static org.apache.dubbo.rpc.Constants.MOCK_KEY; +import static org.apache.dubbo.rpc.Constants.TOKEN_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.WARMUP_KEY; +import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY; + +/** + * Copy from org.apache.dubbo.metadata.DefaultMetadataParamsFilter. + * + * @author theonefx + */ +@Activate +public class DefaultMetadataParamsFilter implements MetadataParamsFilter { + + @Override + public String[] serviceParamsIncluded() { + return new String[] { CODEC_KEY, EXCHANGER_KEY, SERIALIZATION_KEY, CLUSTER_KEY, + CONNECTIONS_KEY, DEPRECATED_KEY, GROUP_KEY, LOADBALANCE_KEY, MOCK_KEY, + PATH_KEY, TIMEOUT_KEY, TOKEN_KEY, VERSION_KEY, WARMUP_KEY, WEIGHT_KEY, + DUBBO_VERSION_KEY, RELEASE_KEY }; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java new file mode 100644 index 000000000..f7b4dc7d1 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java @@ -0,0 +1,35 @@ +/* + * 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; + +import org.apache.dubbo.common.extension.SPI; + +/** + * Copy from org.apache.dubbo.metadata.MetadataParamsFilter. + * + * @author theonefx + */ +@SPI +public interface MetadataParamsFilter { + + /** + * params that need to be sent to metadata center. + * @return arrays of keys + */ + String[] serviceParamsIncluded(); + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java new file mode 100644 index 000000000..53f9f1bf4 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java @@ -0,0 +1,74 @@ +/* + * 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; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; + +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Copy from org.apache.dubbo.metadata.RevisionResolver. + * + * @author theonefx + */ +public final class RevisionResolver { + + private static final Logger logger = LoggerFactory.getLogger(RevisionResolver.class); + + private static final String EMPTY_REVISION = "0"; + + private static final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + private static MessageDigest mdInst; + + static { + try { + mdInst = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException e) { + logger.error("Failed to calculate metadata revision", e); + } + } + + private RevisionResolver() { + + } + + public static String getEmptyRevision() { + return EMPTY_REVISION; + } + + public static String calRevision(String metadata) { + mdInst.update(metadata.getBytes(UTF_8)); + byte[] md5 = mdInst.digest(); + + int j = md5.length; + char[] str = new char[j * 2]; + int k = 0; + for (byte byte0 : md5) { + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; + str[k++] = hexDigits[byte0 & 0xf]; + } + return new String(str); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java new file mode 100644 index 000000000..a734a8e7e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java @@ -0,0 +1,351 @@ +/* + * 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; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.compiler.support.ClassUtils; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.common.utils.StringUtils; + +import static org.apache.dubbo.common.constants.CommonConstants.DOT_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; + +/** + * Copy from org.apache.dubbo.metadata.MetadataInfo.ServiceInfo. + * + * @author theonefx + */ +public class ServiceInfo implements Serializable { + + private static final long serialVersionUID = -258557978718735302L; + + private static ExtensionLoader loader = ExtensionLoader + .getExtensionLoader(MetadataParamsFilter.class); + + private String name; + + private String group; + + private String version; + + private String protocol; + + private String path; // most of the time, path is the same with the interface name. + + private Map params; + + // params configured on consumer side, + private transient Map consumerParams; + + // cached method params + private transient Map> methodParams; + + private transient Map> consumerMethodParams; + + // cached numbers + private transient Map numbers; + + private transient Map> methodNumbers; + + // service + group + version + private transient String serviceKey; + + // service + group + version + protocol + private transient String matchKey; + + private transient URL url; + + public ServiceInfo() { + } + + public ServiceInfo(URL url) { + this(url.getServiceInterface(), url.getParameter(GROUP_KEY), + url.getParameter(VERSION_KEY), url.getProtocol(), url.getPath(), null); + + this.url = url; + Map params = new HashMap<>(); + List filters = loader.getActivateExtension(url, + "params-filter"); + for (MetadataParamsFilter filter : filters) { + String[] paramsIncluded = filter.serviceParamsIncluded(); + if (ArrayUtils.isNotEmpty(paramsIncluded)) { + for (String p : paramsIncluded) { + String value = url.getParameter(p); + if (StringUtils.isNotEmpty(value) && params.get(p) == null) { + params.put(p, value); + } + String[] methods = url.getParameter(METHODS_KEY, (String[]) null); + if (methods != null) { + for (String method : methods) { + String mValue = getMethodParameterStrict(url, method, p); + if (StringUtils.isNotEmpty(mValue)) { + params.put(method + DOT_SEPARATOR + p, mValue); + } + } + } + } + } + } + this.params = params; + } + + public String getMethodParameterStrict(URL url, String method, String key) { + Map keyMap = url.getMethodParameters().get(method); + String value = null; + if (keyMap != null) { + value = keyMap.get(key); + } + return value; + } + + public ServiceInfo(String name, String group, String version, String protocol, + String path, Map params) { + this.name = name; + this.group = group; + this.version = version; + this.protocol = protocol; + this.path = path; + this.params = params == null ? new HashMap<>() : params; + + this.serviceKey = URL.buildKey(name, group, version); + this.matchKey = buildMatchKey(); + } + + public String getMatchKey() { + if (matchKey != null) { + return matchKey; + } + buildMatchKey(); + return matchKey; + } + + private String buildMatchKey() { + matchKey = getServiceKey(); + if (StringUtils.isNotEmpty(protocol)) { + matchKey = getServiceKey() + GROUP_CHAR_SEPARATOR + protocol; + } + return matchKey; + } + + public String getServiceKey() { + if (serviceKey != null) { + return serviceKey; + } + this.serviceKey = URL.buildKey(name, group, version); + return serviceKey; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Map getParams() { + if (params == null) { + return Collections.emptyMap(); + } + return params; + } + + public void setParams(Map params) { + this.params = params; + } + + public Map getAllParams() { + if (consumerParams != null) { + Map allParams = new HashMap<>( + (int) ((params.size() + consumerParams.size()) / 0.75f + 1)); + allParams.putAll(params); + allParams.putAll(consumerParams); + return allParams; + } + return params; + } + + public String getParameter(String key) { + if (consumerParams != null) { + String value = consumerParams.get(key); + if (value != null) { + return value; + } + } + return params.get(key); + } + + public String getMethodParameter(String method, String key, String defaultValue) { + if (methodParams == null) { + methodParams = URL.toMethodParameters(params); + consumerMethodParams = URL.toMethodParameters(consumerParams); + } + + String value = getMethodParameter(method, key, consumerMethodParams); + if (value != null) { + return value; + } + value = getMethodParameter(method, key, methodParams); + return value == null ? defaultValue : value; + } + + private String getMethodParameter(String method, String key, + Map> map) { + Map keyMap = map.get(method); + String value = null; + if (keyMap != null) { + value = keyMap.get(key); + } + if (StringUtils.isEmpty(value)) { + value = getParameter(key); + } + return value; + } + + public boolean hasMethodParameter(String method, String key) { + String value = this.getMethodParameter(method, key, (String) null); + return StringUtils.isNotEmpty(value); + } + + public boolean hasMethodParameter(String method) { + if (methodParams == null) { + methodParams = URL.toMethodParameters(params); + consumerMethodParams = URL.toMethodParameters(consumerParams); + } + + return consumerMethodParams.containsKey(method) + || methodParams.containsKey(method); + } + + public String toDescString() { + return this.getMatchKey() + getMethodSignaturesString() + getParams(); + } + + private String getMethodSignaturesString() { + SortedSet methodStrings = new TreeSet(); + + Method[] methods = ClassUtils.forName(name).getMethods(); + for (Method method : methods) { + methodStrings.add(method.toString()); + } + return methodStrings.toString(); + } + + public void addParameter(String key, String value) { + if (consumerParams != null) { + this.consumerParams.put(key, value); + } + } + + public void addParameterIfAbsent(String key, String value) { + if (consumerParams != null) { + this.consumerParams.putIfAbsent(key, value); + } + } + + public void addConsumerParams(Map params) { + // copy once for one service subscription + if (consumerParams == null) { + consumerParams = new HashMap<>(params); + } + } + + public Map getNumbers() { + // concurrent initialization is tolerant + if (numbers == null) { + numbers = new ConcurrentHashMap<>(); + } + return numbers; + } + + public Map> getMethodNumbers() { + if (methodNumbers == null) { // concurrent initialization is tolerant + methodNumbers = new ConcurrentHashMap<>(); + } + return methodNumbers; + } + + public URL getUrl() { + return url; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof ServiceInfo)) { + return false; + } + + ServiceInfo serviceInfo = (ServiceInfo) obj; + return this.getMatchKey().equals(serviceInfo.getMatchKey()) + && this.getParams().equals(serviceInfo.getParams()); + } + + @Override + public int hashCode() { + return Objects.hash(getMatchKey(), getParams()); + } + + @Override + public String toString() { + return "service{" + "name='" + name + "'," + "group='" + group + "'," + + "version='" + version + "'," + "protocol='" + protocol + "'," + + "params=" + params + "," + "consumerParams=" + consumerParams + "}"; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java index 85c507384..7e85e624c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -16,6 +16,7 @@ package com.alibaba.cloud.dubbo.metadata.repository; +import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -32,6 +33,8 @@ import com.alibaba.cloud.dubbo.env.DubboCloudProperties; import com.alibaba.cloud.dubbo.http.matcher.RequestMetadataMatcher; import com.alibaba.cloud.dubbo.metadata.DubboRestServiceMetadata; import com.alibaba.cloud.dubbo.metadata.RequestMetadata; +import com.alibaba.cloud.dubbo.metadata.RevisionResolver; +import com.alibaba.cloud.dubbo.metadata.ServiceInfo; import com.alibaba.cloud.dubbo.metadata.ServiceRestMetadata; import com.alibaba.cloud.dubbo.registry.event.SubscribedServicesChangedEvent; import com.alibaba.cloud.dubbo.service.DubboMetadataService; @@ -43,6 +46,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.utils.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,6 +100,12 @@ public class DubboServiceMetadataRepository @Deprecated public static final String DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME = METADATA_SERVICE_URLS_PROPERTY_NAME; + /** + * The key of dubbo metadata revision. copyed from + * ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_PROPERTY_NAME. + */ + public static String EXPORTED_SERVICES_REVISION_PROPERTY_NAME = "dubbo.metadata.revision"; + /** * The {@link String#format(String, Object...) pattern} of dubbo protocols port. */ @@ -117,14 +127,11 @@ public class DubboServiceMetadataRepository */ private final MultiValueMap allExportedURLs = new LinkedMultiValueMap<>(); - // =================================== Registration - // =================================== // + // ======================== Registration ======================== // - // ==================================================================================== - // // + // ============================================================== // - // =================================== Subscription - // =================================== // + // ======================== Subscription ======================== // /** * A Map to store REST metadata temporary, its' key is the special service name for a * Dubbo service, the value is a JSON content of JAX-RS or Spring MVC REST metadata @@ -134,11 +141,9 @@ public class DubboServiceMetadataRepository private ApplicationEventPublisher applicationEventPublisher; - // ==================================================================================== - // // + // =============================================================== // - // =================================== REST Metadata - // ================================== // + // ======================== REST Metadata ======================== // private volatile Set subscribedServices = emptySet(); /** @@ -147,11 +152,9 @@ public class DubboServiceMetadataRepository */ private Map> dubboRestServiceMetadataRepository = newHashMap(); - // ==================================================================================== - // // + // =============================================================== // - // =================================== Dependencies - // =================================== // + // ======================== Dependencies ========================= // @Autowired private DubboCloudProperties dubboCloudProperties; @@ -180,8 +183,7 @@ public class DubboServiceMetadataRepository @Autowired private DubboMetadataServiceExporter dubboMetadataServiceExporter; - // ==================================================================================== - // // + // =============================================================== // private static Map getMap(Map> repository, String key) { @@ -189,12 +191,7 @@ public class DubboServiceMetadataRepository } private static V getOrDefault(Map source, K key, V defaultValue) { - V value = source.get(key); - if (value == null) { - value = defaultValue; - source.put(key, value); - } - return value; + return source.computeIfAbsent(key, k -> defaultValue); } private static Map newHashMap() { @@ -248,13 +245,13 @@ public class DubboServiceMetadataRepository @Override public void afterSingletonsInstantiated() { - initializeMetadata(); + // initializeMetadata(); } /** * Initialize the metadata. */ - private void initializeMetadata() { + public void initializeMetadata() { doGetSubscribedServices().forEach(this::initializeMetadata); if (logger.isInfoEnabled()) { logger.info("The metadata of Dubbo services has been initialized"); @@ -301,12 +298,36 @@ public class DubboServiceMetadataRepository addDubboMetadataServiceURLsMetadata(metadata, dubboMetadataServiceURLs); addDubboProtocolsPortMetadata(metadata); + addRevision(metadata); return Collections.unmodifiableMap(metadata); } + private void addRevision(Map metadata) { + metadata.put(EXPORTED_SERVICES_REVISION_PROPERTY_NAME, calAndGetRevision()); + } + + public String calAndGetRevision() { + if (CollectionUtils.isEmptyMap(allExportedURLs)) { + return RevisionResolver.getEmptyRevision(); + } + else { + List descs = new ArrayList<>(allExportedURLs.size()); + for (Map.Entry> entry : allExportedURLs.entrySet()) { + entry.getValue().stream().map(ServiceInfo::new) + .map(ServiceInfo::toDescString).forEach(descs::add); + } + + descs.sort(String::compareTo); + + return RevisionResolver.calRevision(descs.toString()); + } + } + private void removeDubboMetadataServiceURLs(List dubboMetadataServiceURLs) { - dubboMetadataServiceURLs.forEach(this::unexportURL); + dubboMetadataServiceURLs.stream().map(URL::getServiceKey).distinct() + .forEach(allExportedURLs::remove); + // dubboMetadataServiceURLs.forEach(this::unexportURL); } private void addDubboMetadataServiceURLsMetadata(Map metadata, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractServiceSubscribeHandler.java new file mode 100644 index 000000000..aa642c3c6 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/AbstractServiceSubscribeHandler.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.registry; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.NotifyListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.dubbo.common.URLBuilder.from; +import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; +import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty; + +/** + * @author theonefx + */ +public abstract class AbstractServiceSubscribeHandler { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + protected final URL url; + + protected final NotifyListener listener; + + protected final DubboCloudRegistry registry; + + public AbstractServiceSubscribeHandler(URL url, NotifyListener listener, + DubboCloudRegistry registry) { + this.url = url; + this.listener = listener; + this.registry = registry; + } + + protected void notifyAllSubscribedURLs(URL url, List subscribedURLs, + NotifyListener listener) { + + if (isEmpty(subscribedURLs)) { + // Add the EMPTY_PROTOCOL URL + listener.notify(Collections.singletonList(emptyURL(url))); + // if (isDubboMetadataServiceURL(url)) { + // if meta service change, and serviceInstances is zero, will clean up + // information about this client + // String serviceName = url.getParameter(GROUP_KEY); + // repository.removeMetadataAndInitializedService(serviceName, url); + // } + } + else { + // Notify all + listener.notify(subscribedURLs); + } + } + + private URL emptyURL(URL url) { + // issue : When the last service provider is closed, the client still periodically + // connects to the last provider.n + // fix https://github.com/alibaba/spring-cloud-alibaba/issues/1259 + return from(url).setProtocol(EMPTY_PROTOCOL).removeParameter(CATEGORY_KEY) + .build(); + } + + private final AtomicBoolean inited = new AtomicBoolean(false); + + public void init() { + if (inited.compareAndSet(false, true)) { + doInit(); + } + } + + protected abstract void doInit(); + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index cce75ba39..1fe831834 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -16,54 +16,47 @@ package com.alibaba.cloud.dubbo.registry; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; +import com.alibaba.cloud.commons.lang.StringUtils; +import com.alibaba.cloud.dubbo.metadata.RevisionResolver; import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; import com.alibaba.cloud.dubbo.registry.event.ServiceInstancesChangedEvent; -import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory; import com.alibaba.cloud.dubbo.service.DubboMetadataService; import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy; import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; import com.alibaba.cloud.dubbo.util.JSONUtils; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.support.FailbackRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.Ordered; -import org.springframework.util.CollectionUtils; +import org.springframework.context.event.ContextRefreshedEvent; -import static java.lang.String.format; +import static com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository.EXPORTED_SERVICES_REVISION_PROPERTY_NAME; import static java.util.Collections.emptyList; -import static org.apache.dubbo.common.URLBuilder.from; +import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; -import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL; -import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty; import static org.apache.dubbo.registry.Constants.ADMIN_PROTOCOL; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME; import static org.springframework.util.StringUtils.hasText; @@ -72,22 +65,14 @@ import static org.springframework.util.StringUtils.hasText; * Dubbo Cloud {@link FailbackRegistry} is based on Spring Cloud {@link DiscoveryClient}. * * @author Mercy + * @author theonefx */ -public class DubboCloudRegistry extends FailbackRegistry { - - /** - * The parameter name of {@link #servicesLookupInterval}. - */ - public static final String SERVICES_LOOKUP_INTERVAL_PARAM_NAME = "dubbo.services.lookup.interval"; +public class DubboCloudRegistry extends FailbackRegistry + implements ApplicationListener { protected static final String DUBBO_METADATA_SERVICE_CLASS_NAME = DubboMetadataService.class .getName(); - /** - * Caches the IDs of {@link ApplicationListener}. - */ - private static final Set REGISTER_LISTENERS = new HashSet<>(); - protected final Logger logger = LoggerFactory.getLogger(getClass()); private final DiscoveryClient discoveryClient; @@ -98,56 +83,84 @@ public class DubboCloudRegistry extends FailbackRegistry { private final JSONUtils jsonUtils; - private final DubboGenericServiceFactory dubboGenericServiceFactory; - private final DubboMetadataUtils dubboMetadataUtils; - /** - * The interval in second of lookup service names(only for Dubbo-OPS). - */ - private final long servicesLookupInterval; - private final ConfigurableApplicationContext applicationContext; - private final String currentApplicationName; - - private final Map urlNotifyListenerMap = new ConcurrentHashMap<>(); + private final ReSubscribeManager reSubscribeManager; - private final Map reConnectJobMap = new ConcurrentHashMap<>(); + private final AtomicBoolean inited = new AtomicBoolean(false); - private final ScheduledThreadPoolExecutor reConnectPool = new ScheduledThreadPoolExecutor( - 2); + /** + * {subscribedURL : ServiceSubscribeHandler}. + */ + private final Map urlSubscribeHandlerMap = new ConcurrentHashMap<>(); - private final int maxReSubscribeMetadataTimes; + /** + * {appName: MetadataServiceSubscribeHandler}. + */ + private final Map metadataSubscribeHandlerMap = new ConcurrentHashMap<>(); - private final int reSubscribeMetadataIntervial; + /** + * {appName : {revision: [instances]}}. + */ + private final Map>> serviceRevisionInstanceMap = new ConcurrentHashMap<>(); public DubboCloudRegistry(URL url, DiscoveryClient discoveryClient, DubboServiceMetadataRepository repository, DubboMetadataServiceProxy dubboMetadataConfigServiceProxy, - JSONUtils jsonUtils, DubboGenericServiceFactory dubboGenericServiceFactory, - ConfigurableApplicationContext applicationContext, - int maxReSubscribeMetadataTimes, int reSubscribeMetadataIntervial) { + JSONUtils jsonUtils, ConfigurableApplicationContext applicationContext) { super(url); - this.servicesLookupInterval = url - .getParameter(SERVICES_LOOKUP_INTERVAL_PARAM_NAME, 60L); this.discoveryClient = discoveryClient; this.repository = repository; this.dubboMetadataConfigServiceProxy = dubboMetadataConfigServiceProxy; this.jsonUtils = jsonUtils; - this.dubboGenericServiceFactory = dubboGenericServiceFactory; this.applicationContext = applicationContext; this.dubboMetadataUtils = getBean(DubboMetadataUtils.class); - this.currentApplicationName = dubboMetadataUtils.getCurrentApplicationName(); - this.maxReSubscribeMetadataTimes = maxReSubscribeMetadataTimes; - this.reSubscribeMetadataIntervial = reSubscribeMetadataIntervial; + this.reSubscribeManager = new ReSubscribeManager(this); - reConnectPool.setKeepAliveTime(10, TimeUnit.MINUTES); - reConnectPool.allowCoreThreadTimeOut(true); + applicationContext.addApplicationListener( + (ApplicationListener) event -> preInit()); } - private T getBean(Class beanClass) { + private void preInit() { + if (inited.compareAndSet(false, true)) { + Set subscribeApps = getServices(null); + + for (String appName : subscribeApps) { + List instances = discoveryClient.getInstances(appName); + + Map> map = serviceRevisionInstanceMap + .computeIfAbsent(appName, k -> new HashMap<>()); + + for (ServiceInstance instance : instances) { + String revision = getRevision(instance); + List list = map.computeIfAbsent(revision, + k -> new ArrayList<>()); + list.add(instance); + } + + if (map.size() == 0) { + logger.debug("APP {} preInited, instance siez is zero!!", appName); + } + else { + map.forEach((revision, list) -> logger.debug( + "APP {} revision {} preInited, instance size = {}", appName, + revision, list.size())); + } + } + + metadataSubscribeHandlerMap.forEach((url, handler) -> handler.init()); + urlSubscribeHandlerMap.forEach((url, handler) -> handler.init()); + repository.initializeMetadata(); + applicationContext.addApplicationListener(this); + + logger.info("DubboCloudRegistry preInit Done."); + } + } + + protected T getBean(Class beanClass) { return this.applicationContext.getBean(beanClass); } @@ -183,249 +196,248 @@ public class DubboCloudRegistry extends FailbackRegistry { @Override public final void doSubscribe(URL url, NotifyListener listener) { - - if (isAdminURL(url)) { - // TODO in future - if (logger.isWarnEnabled()) { - logger.warn("This feature about admin will be supported in the future."); + synchronized (this) { + if (isAdminURL(url)) { + // TODO in future + if (logger.isWarnEnabled()) { + logger.warn( + "This feature about admin will be supported in the future."); + } + } + else if (isDubboMetadataServiceURL(url) && containsProviderCategory(url)) { + // for DubboMetadataService + String appName = getServiceName(url); + MetadataServiceSubscribeHandler handler = new MetadataServiceSubscribeHandler( + appName, url, listener, this, dubboMetadataUtils); + if (inited.get()) { + handler.init(); + } + metadataSubscribeHandlerMap.put(appName, handler); + } + else if (isConsumerServiceURL(url)) { + // for general Dubbo Services + GenearalServiceSubscribeHandler handler = new GenearalServiceSubscribeHandler( + url, listener, this, repository, jsonUtils, + dubboMetadataConfigServiceProxy); + if (inited.get()) { + handler.init(); + } + urlSubscribeHandlerMap.put(url, handler); } - } - else if (isDubboMetadataServiceURL(url)) { // for DubboMetadataService - subscribeDubboMetadataServiceURLs(url, listener); - } - else { // for general Dubbo Services - subscribeURLs(url, listener); - urlNotifyListenerMap.put(url, listener); } } - private void subscribeURLs(URL url, NotifyListener listener) { - - // Sync subscription - subscribeURLs(url, getServices(url), listener); - - // Async subscription - registerServiceInstancesChangedListener(url, + /** + * Process ServiceInstanceChangedEvent, refresh dubbo reference and metadata info. + */ + @Override + public void onApplicationEvent(ServiceInstancesChangedEvent event) { - new ServiceInstanceChangeListener() { + String appName = event.getServiceName(); - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; - } + List instances = filter(event.getServiceInstances() != null + ? event.getServiceInstances() : Collections.emptyList()); - @Override - public void onApplicationEvent(ServiceInstancesChangedEvent event) { - - Set serviceNames = getServices(url); - - String serviceName = event.getServiceName(); - - if (serviceNames.contains(serviceName)) { - logger.debug( - "handle serviceInstanceChange of general service, serviceName = {}, subscribeUrl={}", - event.getServiceName(), url.getServiceKey()); - try { - subscribeURLs(url, serviceNames, listener); - reConnectJobMap.remove(serviceName); - } - catch (Exception e) { - logger.warn(String.format( - "subscribeURLs failed, serviceName = %s, try reSubscribe again", - serviceName), e); - addReSubscribeMetadataJob(serviceName, 0); - } - } - } - - @Override - public String toString() { - return "ServiceInstancesChangedEventListener:" - + url.getServiceKey(); - } - }); - } + Set subscribedServiceNames = getServices(null); - void addReSubscribeMetadataJob(String serviceName, int count) { - if (count > maxReSubscribeMetadataTimes) { - logger.error( - "reSubscribe failed too many times, serviceName = {}, count = {}", - serviceName, count); + if (!subscribedServiceNames.contains(appName)) { return; } - ReSubscribeMetadataJob job = new ReSubscribeMetadataJob(serviceName, this, count); - reConnectJobMap.put(serviceName, job); - reConnectPool.schedule(job, reSubscribeMetadataIntervial, TimeUnit.SECONDS); - } - void subscribeURLs(URL url, Set serviceNames, NotifyListener listener) { + if (instances.size() == 0) { + logger.warn("APP {} instance changed, size changed zero!!!", appName); + } + else { + logger.info("APP {} instance changed, size changed to {}", appName, + instances.size()); + } + // group by revision + Map> newGroup = instances.stream() + .collect(Collectors.groupingBy(this::getRevision)); + + synchronized (this) { - List subscribedURLs = new LinkedList<>(); + Map> oldGroup = serviceRevisionInstanceMap + .computeIfAbsent(appName, k -> new HashMap<>()); - serviceNames.forEach(serviceName -> { + if (serviceInstanceNotChanged(oldGroup, newGroup)) { + logger.debug("APP {} instance changed, but nothing different", appName); + return; + } - subscribeURLs(url, subscribedURLs, serviceName, - () -> getServiceInstances(serviceName)); + try { - }); + // ensure that the service metadata is correct + refreshServiceMetadataInfo(appName, instances); - // Notify all - notifyAllSubscribedURLs(url, subscribedURLs, listener); - } + // then , refresh general service associated with current application + refreshGeneralServiceInfo(appName, oldGroup, newGroup); - private void registerServiceInstancesChangedListener(URL url, - ApplicationListener listener) { - String listenerId = generateId(url); - if (REGISTER_LISTENERS.add(listenerId)) { - applicationContext.addApplicationListener(listener); + // mark process successful + reSubscribeManager.onRefreshSuccess(event); + } + catch (Exception e) { + logger.error(String.format( + "APP %s instance changed, handler faild, try resubscribe", + appName), e); + reSubscribeManager.onRefreshFail(event); + } } } - private void subscribeURLs(URL subscribedURL, List subscribedURLs, - String serviceName, - Supplier> serviceInstancesSupplier) { - List serviceInstances = serviceInstancesSupplier.get(); - subscribeURLs(subscribedURL, subscribedURLs, serviceName, serviceInstances); - } + private void refreshGeneralServiceInfo(String appName, + Map> oldGroup, + Map> newGroup) { + + Set urls2refresh = new HashSet<>(); - private void subscribeURLs(URL subscribedURL, List subscribedURLs, - String serviceName, List serviceInstances) { + // compare with local + for (String revision : oldGroup.keySet()) { - if (CollectionUtils.isEmpty(serviceInstances)) { - if (logger.isWarnEnabled()) { - logger.warn(format("There is no instance in service[name : %s]", - serviceName)); + if (!newGroup.containsKey(revision)) { + // all instances of this list with revision has losted + urlSubscribeHandlerMap.forEach((url, handler) -> { + if (handler.relatedWith(appName, revision)) { + handler.removeAppNameWithRevision(appName, revision); + urls2refresh.add(url); + } + }); + logger.debug("Subscription app {} revision {} has all losted", appName, + revision); } } - else { - logger.debug("subscribe from serviceName = {}, size = {}", serviceName, - serviceInstances.size()); - } - List exportedURLs = getExportedURLs(subscribedURL, serviceName, - serviceInstances); + for (Map.Entry> entry : newGroup.entrySet()) { + String revision = entry.getKey(); + List instanceList = entry.getValue(); - /** - * Add the exported URLs from {@link MetadataService} - */ - subscribedURLs.addAll(exportedURLs); - } - - private List getExportedURLs(URL subscribedURL, String serviceName, - List serviceInstances) { + if (!oldGroup.containsKey(revision)) { + // this instance list of revision not exists + // should acquire urls + urlSubscribeHandlerMap.forEach( + (url, handler) -> handler.init(appName, revision, instanceList)); + } - List validServiceInstances = filter(serviceInstances); + urlSubscribeHandlerMap.forEach((url, handler) -> { + if (handler.relatedWith(appName, revision)) { + urls2refresh.add(url); + } + }); - // If there is no valid ServiceInstance, return empty result - if (isEmpty(validServiceInstances)) { - if (logger.isWarnEnabled()) { - logger.warn( - "There is no instance from service[name : {}], and then Dubbo Service[key : {}] will not be " - + "available , please make sure the further impact", - serviceName, subscribedURL.getServiceKey()); + if (logger.isDebugEnabled()) { + logger.debug("Subscription app {} revision {} changed, instance list {}", + appName, revision, + instanceList.stream().map( + instance -> instance.getHost() + ":" + instance.getPort()) + .collect(Collectors.toList())); } - return emptyList(); } - List subscribedURLs = cloneExportedURLs(subscribedURL, serviceInstances); - - // clear local service instances, help GC - validServiceInstances.clear(); + serviceRevisionInstanceMap.put(appName, newGroup); - return subscribedURLs; + if (urls2refresh.size() == 0) { + logger.debug("Subscription app {}, no urls will be refreshed", appName); + } + else { + logger.debug("Subscription app {}, the following url will be refresh:{}", + appName, urls2refresh.stream().map(URL::getServiceKey) + .collect(Collectors.toList())); + + for (URL url : urls2refresh) { + GenearalServiceSubscribeHandler handler = urlSubscribeHandlerMap.get(url); + if (handler == null) { + logger.warn("Subscription app {}, can't find handler for service {}", + appName, url.getServiceKey()); + continue; + } + handler.refresh(); + } + } } - /** - * Clone the subscribed URLs based on the template URLs. - * @param subscribedURL the URL to be subscribed - * @param serviceInstances the list of {@link ServiceInstance service instances} - * @return non-null - */ - private List cloneExportedURLs(URL subscribedURL, + private void refreshServiceMetadataInfo(String serviceName, List serviceInstances) { + MetadataServiceSubscribeHandler handler = metadataSubscribeHandlerMap + .get(serviceName); - List clonedExportedURLs = new LinkedList<>(); - - serviceInstances.forEach(serviceInstance -> { - - String host = serviceInstance.getHost(); - - getTemplateExportedURLs(subscribedURL, serviceInstances).stream() - .map(templateURL -> templateURL.removeParameter(TIMESTAMP_KEY)) - .map(templateURL -> templateURL.removeParameter(PID_KEY)) - .map(templateURL -> { - String protocol = templateURL.getProtocol(); - Integer port = repository.getDubboProtocolPort(serviceInstance, - protocol); - - // reserve tag - String tag = null; - List urls = jsonUtils.toURLs(serviceInstance.getMetadata() - .get("dubbo.metadata-service.urls")); - if (urls != null && urls.size() > 0) { - Map parameters = urls.get(0).getParameters(); - tag = parameters.get("dubbo.tag"); - } - - if (Objects.equals(templateURL.getHost(), host) - && Objects.equals(templateURL.getPort(), port)) { // use - // templateURL - // if - // equals - return templateURL; - } - - if (port == null) { - if (logger.isWarnEnabled()) { - logger.warn( - "The protocol[{}] port of Dubbo service instance[host : {}] " - + "can't be resolved", - protocol, host); - } - return null; - } - else { - URLBuilder clonedURLBuilder = from(templateURL) // remove the - // parameters from - // the template - // URL - .setHost(host) // reset the host - .setPort(port) // reset the port - .addParameter("dubbo.tag", tag); // reset the tag - - return clonedURLBuilder.build(); - } - - }).filter(Objects::nonNull).forEach(clonedExportedURLs::add); - }); - return clonedExportedURLs; + if (handler == null) { + logger.warn("Subscription app {}, can't find metadata handler", serviceName); + return; + } + handler.refresh(serviceInstances); } - private List getTemplateExportedURLs(URL subscribedURL, - List serviceInstances) { + private boolean serviceInstanceNotChanged(Map> oldGroup, + Map> newGroup) { + if (newGroup.size() != oldGroup.size()) { + return false; + } - DubboMetadataService dubboMetadataService = getProxy(serviceInstances); + for (Map.Entry> entry : newGroup.entrySet()) { + String appName = entry.getKey(); + List newInstances = entry.getValue(); - List templateExportedURLs = emptyList(); + if (!oldGroup.containsKey(appName)) { + return false; + } - if (dubboMetadataService != null) { - templateExportedURLs = getExportedURLs(dubboMetadataService, subscribedURL); - } - else { - if (logger.isWarnEnabled()) { - logger.warn( - "The metadata of Dubbo service[key : {}] still can't be found, it could effect the further " - + "Dubbo service invocation", - subscribedURL.getServiceKey()); + List oldInstances = oldGroup.get(appName); + if (newInstances.size() != oldInstances.size()) { + return false; } + boolean matched = newInstances.stream().allMatch(newInstance -> { + + for (ServiceInstance oldInstance : oldInstances) { + if (instanceSame(newInstance, oldInstance)) { + return true; + } + } + + return false; + }); + if (!matched) { + return false; + } } - return templateExportedURLs; + return true; } - private DubboMetadataService getProxy(List serviceInstances) { - return dubboMetadataConfigServiceProxy.getProxy(serviceInstances); + private boolean instanceSame(ServiceInstance newInstance, + ServiceInstance oldInstance) { + if (!StringUtils.equals(newInstance.getInstanceId(), + oldInstance.getInstanceId())) { + return false; + } + if (!StringUtils.equals(newInstance.getHost(), oldInstance.getHost())) { + return false; + } + if (!StringUtils.equals(newInstance.getServiceId(), oldInstance.getServiceId())) { + return false; + } + if (!StringUtils.equals(newInstance.getScheme(), oldInstance.getScheme())) { + return false; + } + if (oldInstance.getPort() != newInstance.getPort()) { + return false; + } + + if (!oldInstance.getMetadata().equals(newInstance.getMetadata())) { + return false; + } + + return true; + } + + String getRevision(ServiceInstance instance) { + Map metadata = instance.getMetadata(); + String revision = metadata.get(EXPORTED_SERVICES_REVISION_PROPERTY_NAME); + + if (revision == null) { + revision = RevisionResolver.getEmptyRevision(); + } + return revision; } private List filter(Collection serviceInstances) { @@ -440,35 +452,14 @@ public class DubboCloudRegistry extends FailbackRegistry { Set getServices(URL url) { Set subscribedServices = repository.getSubscribedServices(); + if (subscribedServices.contains("*")) { + subscribedServices = new HashSet<>(discoveryClient.getServices()); + } // TODO Add the filter feature return subscribedServices; } - private void notifyAllSubscribedURLs(URL url, List subscribedURLs, - NotifyListener listener) { - - if (isEmpty(subscribedURLs)) { - // Add the EMPTY_PROTOCOL URL - subscribedURLs.add(emptyURL(url)); - - // if (isDubboMetadataServiceURL(url)) { - // if meta service change, and serviceInstances is zero, will clean up - // information about this client - // String serviceName = url.getParameter(GROUP_KEY); - // repository.removeMetadataAndInitializedService(serviceName, url); - // } - } - - if (logger.isDebugEnabled()) { - logger.debug("The subscribed URL[{}] will notify all URLs : {}", url, - subscribedURLs); - } - - // Notify all - listener.notify(subscribedURLs); - } - - private List getServiceInstances(String serviceName) { + List getServiceInstances(String serviceName) { return hasText(serviceName) ? doGetServiceInstances(serviceName) : emptyList(); } @@ -485,108 +476,14 @@ public class DubboCloudRegistry extends FailbackRegistry { return serviceInstances; } - private String generateId(URL url) { - return url.toString(); - } - - private URL emptyURL(URL url) { - // issue : When the last service provider is closed, the client still periodically - // connects to the last provider.n - // fix https://github.com/alibaba/spring-cloud-alibaba/issues/1259 - return from(url).setProtocol(EMPTY_PROTOCOL).removeParameter(CATEGORY_KEY) - .build(); - } - - private List getExportedURLs(DubboMetadataService dubboMetadataService, - URL subscribedURL) { - String serviceInterface = subscribedURL.getServiceInterface(); - String group = subscribedURL.getParameter(GROUP_KEY); - String version = subscribedURL.getParameter(VERSION_KEY); - // The subscribed protocol may be null - String subscribedProtocol = subscribedURL.getParameter(PROTOCOL_KEY); - String exportedURLsJSON = dubboMetadataService.getExportedURLs(serviceInterface, - group, version); - return jsonUtils.toURLs(exportedURLsJSON).stream() - .filter(exportedURL -> subscribedProtocol == null - || subscribedProtocol.equalsIgnoreCase(exportedURL.getProtocol())) - .collect(Collectors.toList()); - } - - private void subscribeDubboMetadataServiceURLs(URL subscribedURL, - NotifyListener listener) { - - subscribeDubboMetadataServiceURLs(subscribedURL, listener, - getServiceName(subscribedURL)); - - // Sync subscription - if (containsProviderCategory(subscribedURL)) { - - registerServiceInstancesChangedListener(subscribedURL, - new ServiceInstanceChangeListener() { - - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE - 1; - } - - @Override - public void onApplicationEvent( - ServiceInstancesChangedEvent event) { - String sourceServiceName = event.getServiceName(); - List serviceInstances = event - .getServiceInstances(); - String serviceName = getServiceName(subscribedURL); - - if (Objects.equals(sourceServiceName, serviceName)) { - logger.debug( - "handle serviceInstanceChange of metadata service, serviceName = {}, subscribeUrl={}", - event.getServiceName(), - subscribedURL.getServiceKey()); - - // only update serviceInstances of the specified - // serviceName - subscribeDubboMetadataServiceURLs(subscribedURL, listener, - sourceServiceName, serviceInstances); - } - } - - @Override - public String toString() { - return "ServiceInstancesChangedEventListener:" - + subscribedURL.getServiceKey(); - } - }); - } - } - + // the group of DubboMetadataService is current application name private String getServiceName(URL subscribedURL) { return subscribedURL.getParameter(GROUP_KEY); } - private void subscribeDubboMetadataServiceURLs(URL subscribedURL, - NotifyListener listener, String serviceName, - List serviceInstances) { - - String serviceInterface = subscribedURL.getServiceInterface(); - String version = subscribedURL.getParameter(VERSION_KEY); - String protocol = subscribedURL.getParameter(PROTOCOL_KEY); - - List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, - serviceInterface, version, protocol); - - notifyAllSubscribedURLs(subscribedURL, urls, listener); - } - - private void subscribeDubboMetadataServiceURLs(URL subscribedURL, - NotifyListener listener, String serviceName) { - List serviceInstances = getServiceInstances(serviceName); - subscribeDubboMetadataServiceURLs(subscribedURL, listener, serviceName, - serviceInstances); - } - private boolean containsProviderCategory(URL subscribedURL) { String category = subscribedURL.getParameter(CATEGORY_KEY); - return category == null ? false : category.contains(PROVIDER); + return category != null && category.contains(PROVIDER); } @Override @@ -603,16 +500,36 @@ public class DubboCloudRegistry extends FailbackRegistry { return ADMIN_PROTOCOL.equals(url.getProtocol()); } - public Map getUrlNotifyListenerMap() { - return urlNotifyListenerMap; + protected boolean isDubboMetadataServiceURL(URL url) { + return DUBBO_METADATA_SERVICE_CLASS_NAME.equals(url.getServiceInterface()); } - public Map getReConnectJobMap() { - return reConnectJobMap; + protected boolean isConsumerServiceURL(URL url) { + return CONSUMER.equals(url.getProtocol()); } - protected boolean isDubboMetadataServiceURL(URL url) { - return DUBBO_METADATA_SERVICE_CLASS_NAME.equals(url.getServiceInterface()); + public List getServiceInstances(Map> providers) { + List instances = new ArrayList<>(); + + providers.forEach((appName, revisions) -> { + Map> revisionMap = serviceRevisionInstanceMap + .get(appName); + if (revisionMap == null) { + return; + } + for (String revision : revisions) { + List list = revisionMap.get(revision); + if (list != null) { + instances.addAll(list); + } + } + }); + + return instances; + } + + public Map>> getServiceRevisionInstanceMap() { + return serviceRevisionInstanceMap; } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java new file mode 100644 index 000000000..a2f3ca4f7 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java @@ -0,0 +1,270 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.registry; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; +import com.alibaba.cloud.dubbo.service.DubboMetadataService; +import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy; +import com.alibaba.cloud.dubbo.util.JSONUtils; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.registry.NotifyListener; + +import org.springframework.cloud.client.ServiceInstance; + +import static java.util.Collections.emptyList; +import static org.apache.dubbo.common.URLBuilder.from; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; + +/** + * @author theonefx + */ +public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHandler { + + private final Map> providers = new HashMap<>(); + + private final Map urlTemplateMap = new HashMap<>(); + + private final JSONUtils jsonUtils; + + private final DubboServiceMetadataRepository repository; + + private final DubboMetadataServiceProxy dubboMetadataConfigServiceProxy; + + public GenearalServiceSubscribeHandler(URL url, NotifyListener listener, + DubboCloudRegistry registry, DubboServiceMetadataRepository repository, + JSONUtils jsonUtils, + DubboMetadataServiceProxy dubboMetadataConfigServiceProxy) { + super(url, listener, registry); + this.repository = repository; + this.jsonUtils = jsonUtils; + this.dubboMetadataConfigServiceProxy = dubboMetadataConfigServiceProxy; + } + + public boolean relatedWith(String appName, String revision) { + Set list = providers.get(appName); + if (list != null && list.size() > 0) { + if (list.contains(revision)) { + return true; + } + } + return false; + } + + public void removeAppNameWithRevision(String appName, String revision) { + Set list = providers.get(appName); + if (list != null) { + list.remove(revision); + if (list.size() == 0) { + providers.remove(appName); + } + } + } + + public void addAppNameWithRevision(String appName, String revision) { + Set set = providers.computeIfAbsent(appName, k -> new HashSet<>()); + set.add(revision); + } + + public synchronized void doInit() { + logger.debug("Subscription interface {}, GenearalServiceSubscribeHandler init", + url.getServiceKey()); + Map>> map = registry + .getServiceRevisionInstanceMap(); + for (Map.Entry>> entry : map + .entrySet()) { + String appName = entry.getKey(); + Map> revisionMap = entry.getValue(); + + for (Map.Entry> revisionEntity : revisionMap + .entrySet()) { + String revision = revisionEntity.getKey(); + List instances = revisionEntity.getValue(); + init(appName, revision, instances); + } + } + refresh(); + } + + public void init(String appName, String revision, + List instanceList) { + List urls = getTemplateExportedURLs(url, instanceList); + if (urls != null && urls.size() > 0) { + addAppNameWithRevision(appName, revision); + setUrlTemplate(appName, revision, urls); + } + } + + public synchronized void refresh() { + List urls = getProviderURLs(); + notifyAllSubscribedURLs(url, urls, listener); + } + + private List getProviderURLs() { + List instances = registry.getServiceInstances(providers); + + logger.debug("Subscription interfece {}, providers {}, total {}", + url.getServiceKey(), providers, instances.size()); + + if (instances.size() == 0) { + return Collections.emptyList(); + } + + return cloneExportedURLs(instances); + } + + void setUrlTemplate(String appName, String revision, List urls) { + if (urls == null || urls.size() == 0) { + return; + } + String key = getAppRevisionKey(appName, revision); + if (urlTemplateMap.containsKey(key)) { + return; + } + urlTemplateMap.put(key, urls.get(0)); + } + + private String getAppRevisionKey(String appName, String revision) { + return appName + "@" + revision; + } + + /** + * Clone the subscribed URLs based on the template URLs. + * @param serviceInstances the list of + * {@link org.springframework.cloud.client.ServiceInstance service instances} + * @return + */ + List cloneExportedURLs(List serviceInstances) { + + List urlsCloneTo = new ArrayList<>(); + serviceInstances.forEach(serviceInstance -> { + + String host = serviceInstance.getHost(); + String appName = serviceInstance.getServiceId(); + String revision = registry.getRevision(serviceInstance); + + URL template = urlTemplateMap.get(getAppRevisionKey(appName, revision)); + + Stream.of(template) + .map(templateURL -> templateURL.removeParameter(TIMESTAMP_KEY)) + .map(templateURL -> templateURL.removeParameter(PID_KEY)) + .map(templateURL -> { + String protocol = templateURL.getProtocol(); + Integer port = repository.getDubboProtocolPort(serviceInstance, + protocol); + + // reserve tag + String tag = null; + List urls = jsonUtils.toURLs(serviceInstance.getMetadata() + .get("dubbo.metadata-service.urls")); + if (urls != null && urls.size() > 0) { + Map parameters = urls.get(0).getParameters(); + tag = parameters.get("dubbo.tag"); + } + + if (Objects.equals(templateURL.getHost(), host) + && Objects.equals(templateURL.getPort(), port)) { // use + // templateURL + // if + // equals + return templateURL; + } + + if (port == null) { + if (logger.isWarnEnabled()) { + logger.warn( + "The protocol[{}] port of Dubbo service instance[host : {}] " + + "can't be resolved", + protocol, host); + } + return null; + } + else { + URLBuilder clonedURLBuilder = from(templateURL) // remove the + // parameters from + // the template + // URL + .setHost(host) // reset the host + .setPort(port) // reset the port + .addParameter("dubbo.tag", tag); // reset the tag + + return clonedURLBuilder.build(); + } + + }).filter(Objects::nonNull).forEach(urlsCloneTo::add); + }); + return urlsCloneTo; + } + + private List getTemplateExportedURLs(URL subscribedURL, + List serviceInstances) { + + DubboMetadataService dubboMetadataService = getProxy(serviceInstances); + + List templateExportedURLs = emptyList(); + + if (dubboMetadataService != null) { + templateExportedURLs = getExportedURLs(dubboMetadataService, subscribedURL); + } + else { + if (logger.isWarnEnabled()) { + logger.warn( + "The metadata of Dubbo service[key : {}] still can't be found, it could effect the further " + + "Dubbo service invocation", + subscribedURL.getServiceKey()); + } + + } + + return templateExportedURLs; + } + + private DubboMetadataService getProxy(List serviceInstances) { + return dubboMetadataConfigServiceProxy.getProxy(serviceInstances); + } + + private List getExportedURLs(DubboMetadataService dubboMetadataService, + URL subscribedURL) { + String serviceInterface = subscribedURL.getServiceInterface(); + String group = subscribedURL.getParameter(GROUP_KEY); + String version = subscribedURL.getParameter(VERSION_KEY); + // The subscribed protocol may be null + String subscribedProtocol = subscribedURL.getParameter(PROTOCOL_KEY); + String exportedURLsJSON = dubboMetadataService.getExportedURLs(serviceInterface, + group, version); + return jsonUtils.toURLs(exportedURLsJSON).stream() + .filter(exportedURL -> subscribedProtocol == null + || subscribedProtocol.equalsIgnoreCase(exportedURL.getProtocol())) + .collect(Collectors.toList()); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java new file mode 100644 index 000000000..9a9f99325 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.registry; + +import java.util.List; + +import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.NotifyListener; + +import org.springframework.cloud.client.ServiceInstance; + +import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; + +/** + * @author theonefx + */ +public class MetadataServiceSubscribeHandler extends AbstractServiceSubscribeHandler { + + private final String appName; + + private final DubboMetadataUtils dubboMetadataUtils; + + public MetadataServiceSubscribeHandler(String appName, URL url, + NotifyListener listener, DubboCloudRegistry registry, + DubboMetadataUtils dubboMetadataUtils) { + super(url, listener, registry); + this.appName = appName; + this.dubboMetadataUtils = dubboMetadataUtils; + } + + public void doInit() { + logger.debug("Subscription app {} MetadataService handler init", appName); + List serviceInstances = registry.getServiceInstances(appName); + subscribeDubboMetadataServiceURLs(url, listener, serviceInstances); + } + + public void refresh(List serviceInstances) { + logger.debug("Subscription app {}, instance changed, new size = {}", appName, + serviceInstances.size()); + subscribeDubboMetadataServiceURLs(url, listener, serviceInstances); + } + + private void subscribeDubboMetadataServiceURLs(URL subscribedURL, + NotifyListener listener, List serviceInstances) { + + logger.debug("Subscription app {}, service instance changed to size {}", appName, + serviceInstances.size()); + + String serviceInterface = subscribedURL.getServiceInterface(); + String version = subscribedURL.getParameter(VERSION_KEY); + String protocol = subscribedURL.getParameter(PROTOCOL_KEY); + + List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, + serviceInterface, version, protocol); + + notifyAllSubscribedURLs(subscribedURL, urls, listener); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeManager.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeManager.java new file mode 100644 index 000000000..5de52dbf6 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeManager.java @@ -0,0 +1,125 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.dubbo.registry; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import com.alibaba.cloud.dubbo.env.DubboCloudProperties; +import com.alibaba.cloud.dubbo.registry.event.ServiceInstancesChangedEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.client.ServiceInstance; + +/** + * @author theonefx + */ +public class ReSubscribeManager { + + private final Logger logger = LoggerFactory.getLogger(ReSubscribeManager.class); + + private final Map reConnectJobMap = new ConcurrentHashMap<>(); + + private final ScheduledThreadPoolExecutor reConnectPool = new ScheduledThreadPoolExecutor( + 5); + + private final DubboCloudRegistry registry; + + private final DubboCloudProperties properties; + + public ReSubscribeManager(DubboCloudRegistry registry) { + this.registry = registry; + this.properties = registry.getBean(DubboCloudProperties.class); + + reConnectPool.setKeepAliveTime(10, TimeUnit.MINUTES); + reConnectPool.allowCoreThreadTimeOut(true); + } + + public void onRefreshSuccess(ServiceInstancesChangedEvent event) { + reConnectJobMap.remove(event.getServiceName()); + } + + public void onRefreshFail(ServiceInstancesChangedEvent event) { + String serviceName = event.getServiceName(); + + int count = 1; + + if (event instanceof FakeServiceInstancesChangedEvent) { + count = ((FakeServiceInstancesChangedEvent) event).getCount() + 1; + } + + if (count >= properties.getMaxReSubscribeMetadataTimes()) { + logger.error( + "reSubscribe failed too many times, serviceName = {}, count = {}", + serviceName, count); + return; + } + + ReSubscribeMetadataJob job = new ReSubscribeMetadataJob(serviceName, count); + reConnectPool.schedule(job, properties.getReSubscribeMetadataIntervial(), + TimeUnit.SECONDS); + } + + private final class ReSubscribeMetadataJob implements Runnable { + + private final String serviceName; + + private final int errorCounts; + + private ReSubscribeMetadataJob(String serviceName, int errorCounts) { + this.errorCounts = errorCounts; + this.serviceName = serviceName; + } + + @Override + public void run() { + if (!reConnectJobMap.containsKey(serviceName) + || reConnectJobMap.get(serviceName) != this) { + return; + } + List list = registry.getServiceInstances(serviceName); + FakeServiceInstancesChangedEvent event = new FakeServiceInstancesChangedEvent( + serviceName, list, errorCounts); + registry.onApplicationEvent(event); + } + + } + + private static final class FakeServiceInstancesChangedEvent + extends ServiceInstancesChangedEvent { + + private static final long serialVersionUID = -2832478604601472915L; + + private final int count; + + private FakeServiceInstancesChangedEvent(String serviceName, + List serviceInstances, int count) { + super(serviceName, serviceInstances); + this.count = count; + } + + public int getCount() { + return count; + } + + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java deleted file mode 100644 index 74d917f07..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/ReSubscribeMetadataJob.java +++ /dev/null @@ -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.dubbo.registry; - -import java.util.Map; -import java.util.Set; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.registry.NotifyListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * For re subscribe URL from provider. - * - * @author theonefx - */ -public class ReSubscribeMetadataJob implements Runnable { - - protected final Logger logger = LoggerFactory.getLogger(ReSubscribeMetadataJob.class); - - private final String serviceName; - - private final DubboCloudRegistry dubboCloudRegistry; - - private final int errorCounts; - - public ReSubscribeMetadataJob(String serviceName, - DubboCloudRegistry dubboCloudRegistry, int errorCounts) { - this.errorCounts = errorCounts; - this.serviceName = serviceName; - this.dubboCloudRegistry = dubboCloudRegistry; - } - - public ReSubscribeMetadataJob(String serviceName, - DubboCloudRegistry dubboCloudRegistry) { - this(serviceName, dubboCloudRegistry, 0); - } - - @Override - public void run() { - if (dubboCloudRegistry.getReConnectJobMap().get(serviceName) != this) { - return; - } - try { - logger.info("reSubscribe, serviceName = {}, count = {}", serviceName, - errorCounts); - for (Map.Entry entry : dubboCloudRegistry - .getUrlNotifyListenerMap().entrySet()) { - doRun(entry.getKey(), entry.getValue()); - } - dubboCloudRegistry.getReConnectJobMap().remove(serviceName); - } - catch (Exception e) { - logger.warn(String.format( - "reSubscribe failed, serviceName = %s, try refresh again", - serviceName), e); - dubboCloudRegistry.addReSubscribeMetadataJob(serviceName, errorCounts + 1); - } - } - - private void doRun(URL url, NotifyListener listener) { - Set serviceNames = dubboCloudRegistry.getServices(url); - - if (serviceNames.contains(serviceName)) { - dubboCloudRegistry.subscribeURLs(url, serviceNames, listener); - } - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java index d13c5179c..2b3b676a3 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/SpringCloudRegistryFactory.java @@ -89,7 +89,7 @@ public class SpringCloudRegistryFactory extends AbstractRegistryFactory { DubboCloudProperties dubboCloudProperties = applicationContext .getBean(DubboCloudProperties.class); - Registry registry = null; + Registry registry; switch (dubboCloudProperties.getRegistryType()) { case SPRING_CLOUD_REGISTRY_PROPERTY_VALUE: @@ -100,9 +100,7 @@ public class SpringCloudRegistryFactory extends AbstractRegistryFactory { default: registry = new DubboCloudRegistry(url, discoveryClient, dubboServiceMetadataRepository, dubboMetadataConfigServiceProxy, - jsonUtils, dubboGenericServiceFactory, applicationContext, - dubboCloudProperties.getMaxReSubscribeMetadataTimes(), - dubboCloudProperties.getReSubscribeMetadataIntervial()); + jsonUtils, applicationContext); break; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter new file mode 100644 index 000000000..ce4f0db1e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter @@ -0,0 +1 @@ +default=com.alibaba.cloud.dubbo.metadata.DefaultMetadataParamsFilter \ No newline at end of file From df2bced6f2a01ca6254f26ad221f6edc081353f8 Mon Sep 17 00:00:00 2001 From: theonefx Date: Tue, 1 Jun 2021 11:18:47 +0800 Subject: [PATCH 40/99] optimize dubbo registry --- .../repository/DubboServiceMetadataRepository.java | 1 + .../alibaba/cloud/dubbo/registry/DubboCloudRegistry.java | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java index 7e85e624c..8b687cd19 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -245,6 +245,7 @@ public class DubboServiceMetadataRepository @Override public void afterSingletonsInstantiated() { + // inited by DubboCloudRegistry.preInit() @theonefx // initializeMetadata(); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index 1fe831834..a18823947 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -42,7 +42,6 @@ import org.apache.dubbo.registry.support.FailbackRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.ApplicationListener; @@ -154,6 +153,8 @@ public class DubboCloudRegistry extends FailbackRegistry metadataSubscribeHandlerMap.forEach((url, handler) -> handler.init()); urlSubscribeHandlerMap.forEach((url, handler) -> handler.init()); repository.initializeMetadata(); + + // meke sure everything prepared, then can listening ServiceInstanceChangeEvent applicationContext.addApplicationListener(this); logger.info("DubboCloudRegistry preInit Done."); @@ -235,8 +236,9 @@ public class DubboCloudRegistry extends FailbackRegistry String appName = event.getServiceName(); - List instances = filter(event.getServiceInstances() != null - ? event.getServiceInstances() : Collections.emptyList()); + List instances = filter( + event.getServiceInstances() != null ? event.getServiceInstances() + : Collections.emptyList()); Set subscribedServiceNames = getServices(null); From 87d0939411e284d59a64a999ab359a20b3596702 Mon Sep 17 00:00:00 2001 From: joeqiaoyao Date: Tue, 1 Jun 2021 21:06:52 +0800 Subject: [PATCH 41/99] =?UTF-8?q?feat:=20=E9=85=8D=E7=BD=AE=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0unitName=EF=BC=8C=E6=94=AF=E6=8C=81=E5=90=8C=E4=B8=80?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E8=BF=9E=E6=8E=A5=E5=A4=9A=E4=B8=AA=E9=9B=86?= =?UTF-8?q?=E7=BE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/inbound/RocketMQConsumerFactory.java | 2 ++ .../integration/outbound/RocketMQProduceFactory.java | 1 + .../properties/RocketMQCommonProperties.java | 12 ++++++++++++ .../stream/binder/rocketmq/utils/RocketMQUtils.java | 3 +++ 4 files changed, 18 insertions(+) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java index 7f7e1bf26..2aeb1a19f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java @@ -89,6 +89,7 @@ public final class RocketMQConsumerFactory { consumer.setPullInterval(consumerProperties.getPush().getPullInterval()); consumer.setConsumeThreadMin(extendedConsumerProperties.getConcurrency()); consumer.setConsumeThreadMax(extendedConsumerProperties.getConcurrency()); + consumer.setUnitName(consumerProperties.getUnitName()); return consumer; } @@ -145,6 +146,7 @@ public final class RocketMQConsumerFactory { // The internal queues are cached by a maximum of 1000 consumer.setPullThresholdForAll(extendedConsumerProperties.getExtension() .getPull().getPullThresholdForAll()); + consumer.setUnitName(consumerProperties.getUnitName()); return consumer; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java index 463868438..509aae652 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java @@ -118,6 +118,7 @@ public final class RocketMQProduceFactory { producerProperties.getRetryAnotherBroker()); producer.setMaxMessageSize(producerProperties.getMaxMessageSize()); producer.setUseTLS(producerProperties.getUseTLS()); + producer.setUnitName(producerProperties.getUnitName()); CheckForbiddenHook checkForbiddenHook = RocketMQBeanContainerCache.getBean( producerProperties.getCheckForbiddenHook(), CheckForbiddenHook.class); if (null != checkForbiddenHook) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java index 9e9114641..4973dd759 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java @@ -56,6 +56,11 @@ public class RocketMQCommonProperties implements Serializable { private String namespace; + /** + * The property of "unitName". + */ + private String unitName; + private String accessChannel = AccessChannel.LOCAL.name(); /** @@ -199,4 +204,11 @@ public class RocketMQCommonProperties implements Serializable { this.customizedTraceTopic = customizedTraceTopic; } + public String getUnitName() { + return unitName; + } + + public void setUnitName(String unitName) { + this.unitName = unitName; + } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java index 1aed546a0..6bc969d24 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java @@ -64,6 +64,9 @@ public final class RocketMQUtils { mqProperties.setCustomizedTraceTopic( binderConfigurationProperties.getCustomizedTraceTopic()); } + if (StringUtils.isEmpty(mqProperties.getUnitName())) { + mqProperties.setUnitName(binderConfigurationProperties.getUnitName()); + } mqProperties.setNameServer(getNameServerStr(mqProperties.getNameServer())); return mqProperties; } From a2b2c2f8c1fd81a9af9675ab864d27067b168f31 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Thu, 3 Jun 2021 12:36:21 +0800 Subject: [PATCH 42/99] Nacos Discovery supports registration for quick failed configurations --- .../src/main/resources/application.properties | 1 + .../cloud/nacos/NacosDiscoveryProperties.java | 19 +++++++++++++++++-- .../nacos/registry/NacosServiceRegistry.java | 14 +++++++++----- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/resources/application.properties index cd4cc01d0..c1071da86 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-consumer-example/src/main/resources/application.properties @@ -2,6 +2,7 @@ spring.application.name=service-consumer server.port=18083 management.endpoints.web.exposure.include=* spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 +spring.cloud.nacos.discovery.fail-fast=true spring.cloud.nacos.username=nacos spring.cloud.nacos.password=nacos diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java index 632448dbd..0b0d27a90 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java @@ -207,6 +207,12 @@ public class NacosDiscoveryProperties { */ private boolean ephemeral = true; + /** + * Throw exceptions during service registration if true, otherwise, log error + * (defaults to true). + */ + private boolean failFast = true; + @Autowired private InetUtils inetUtils; @@ -486,6 +492,14 @@ public class NacosDiscoveryProperties { this.ephemeral = ephemeral; } + public boolean isFailFast() { + return failFast; + } + + public void setFailFast(boolean failFast) { + this.failFast = failFast; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -510,6 +524,7 @@ public class NacosDiscoveryProperties { && Objects.equals(secretKey, that.secretKey) && Objects.equals(heartBeatInterval, that.heartBeatInterval) && Objects.equals(heartBeatTimeout, that.heartBeatTimeout) + && Objects.equals(failFast, that.failFast) && Objects.equals(ipDeleteTimeout, that.ipDeleteTimeout); } @@ -519,7 +534,7 @@ public class NacosDiscoveryProperties { watchDelay, logName, service, weight, clusterName, group, namingLoadCacheAtStart, registerEnabled, ip, networkInterface, port, secure, accessKey, secretKey, heartBeatInterval, heartBeatTimeout, - ipDeleteTimeout, instanceEnabled, ephemeral); + ipDeleteTimeout, instanceEnabled, ephemeral, failFast); } @Override @@ -535,7 +550,7 @@ public class NacosDiscoveryProperties { + ", port=" + port + ", secure=" + secure + ", accessKey='" + accessKey + '\'' + ", secretKey='" + secretKey + '\'' + ", heartBeatInterval=" + heartBeatInterval + ", heartBeatTimeout=" + heartBeatTimeout - + ", ipDeleteTimeout=" + ipDeleteTimeout + '}'; + + ", ipDeleteTimeout=" + ipDeleteTimeout + ", failFast=" + failFast + '}'; } public void overrideFromEnv(Environment env) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java index 9a79a568f..aabac3a9c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java @@ -76,11 +76,15 @@ public class NacosServiceRegistry implements ServiceRegistry { instance.getIp(), instance.getPort()); } catch (Exception e) { - log.error("nacos registry, {} register failed...{},", serviceId, - registration.toString(), e); - // rethrow a RuntimeException if the registration is failed. - // issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132 - rethrowRuntimeException(e); + if (nacosDiscoveryProperties.isFailFast()) { + log.error("nacos registry, {} register failed...{},", serviceId, + registration.toString(), e); + rethrowRuntimeException(e); + } + else { + log.warn("Failfast is false. {} register failed...{},", serviceId, + registration.toString(), e); + } } } From 4786725e8e84d5463e3bb28a92c77b9d8581c28e Mon Sep 17 00:00:00 2001 From: HuGuirong Date: Thu, 10 Jun 2021 20:27:22 +0800 Subject: [PATCH 43/99] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BD=93=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B=E4=B8=8D=E5=9C=A8=E9=BB=98=E8=AE=A4=E5=88=86=E7=BB=84?= =?UTF-8?q?=E4=B8=8B=E6=97=B6=E8=8E=B7=E5=8F=96=E4=B8=8D=E5=88=B0=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B=E7=8A=B6=E6=80=81=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java index aabac3a9c..16010b373 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java @@ -159,8 +159,9 @@ public class NacosServiceRegistry implements ServiceRegistry { public Object getStatus(Registration registration) { String serviceName = registration.getServiceId(); + String group = nacosDiscoveryProperties.getGroup(); try { - List instances = namingService().getAllInstances(serviceName); + List instances = namingService().getAllInstances(serviceName, group); for (Instance instance : instances) { if (instance.getIp().equalsIgnoreCase(nacosDiscoveryProperties.getIp()) && instance.getPort() == nacosDiscoveryProperties.getPort()) { From e4f2f4150c8e79d811a13d4bbbe3858fb3c3c09f Mon Sep 17 00:00:00 2001 From: theonefx Date: Tue, 22 Jun 2021 17:14:34 +0800 Subject: [PATCH 44/99] init DubboCloudRegistry when subscribe or unsubscribe --- .../spring-cloud-dubbo-client-sample/pom.xml | 1 - .../src/main/resources/bootstrap.yaml | 10 +++-- .../src/main/resources/bootstrap.yaml | 2 + .../dubbo/registry/DubboCloudRegistry.java | 42 +++++++++++-------- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml index c37db212c..1a675b438 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/pom.xml @@ -10,7 +10,6 @@ 4.0.0 - com.alibaba.cloud spring-cloud-dubbo-client-sample Spring Cloud Dubbo Client Sample diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml index 6801b6c4b..19d22ad11 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-client-sample/src/main/resources/bootstrap.yaml @@ -12,7 +12,11 @@ spring: allow-bean-definition-overriding: true cloud: nacos: - username: nacos - password: nacos discovery: - server-addr: 127.0.0.1:8848 \ No newline at end of file + username: nacos + password: nacos + server-addr: 127.0.0.1:8848 + namespace: public + +server: + port: 8080 \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/resources/bootstrap.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/resources/bootstrap.yaml index 650b9861c..db7e38c0d 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/resources/bootstrap.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-server-sample/src/main/resources/bootstrap.yaml @@ -1,4 +1,6 @@ dubbo: + cloud: + subscribed-services: ${spring.application.name} scan: base-packages: com.alibaba.cloud.dubbo.bootstrap protocol: diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index a18823947..f02ebe1a2 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -46,7 +46,6 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.event.ContextRefreshedEvent; import static com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository.EXPORTED_SERVICES_REVISION_PROPERTY_NAME; import static java.util.Collections.emptyList; @@ -118,9 +117,6 @@ public class DubboCloudRegistry extends FailbackRegistry this.applicationContext = applicationContext; this.dubboMetadataUtils = getBean(DubboMetadataUtils.class); this.reSubscribeManager = new ReSubscribeManager(this); - - applicationContext.addApplicationListener( - (ApplicationListener) event -> preInit()); } private void preInit() { @@ -154,7 +150,8 @@ public class DubboCloudRegistry extends FailbackRegistry urlSubscribeHandlerMap.forEach((url, handler) -> handler.init()); repository.initializeMetadata(); - // meke sure everything prepared, then can listening ServiceInstanceChangeEvent + // meke sure everything prepared, then can listening + // ServiceInstanceChangeEvent applicationContext.addApplicationListener(this); logger.info("DubboCloudRegistry preInit Done."); @@ -165,39 +162,50 @@ public class DubboCloudRegistry extends FailbackRegistry return this.applicationContext.getBean(beanClass); } - protected boolean shouldRegister(URL url) { + protected boolean shouldNotRegister(URL url) { String side = url.getParameter(SIDE_KEY); boolean should = PROVIDER_SIDE.equals(side); // Only register the Provider. - if (!should) { - if (logger.isDebugEnabled()) { - logger.debug("The URL[{}] should not be registered.", url.toString()); + if (logger.isDebugEnabled()) { + if (!should) { + logger.debug("The URL should NOT!! be registered & unregistered [{}] .", + url); + } + else { + logger.debug("The URL should be registered & unregistered [{}] .", url); } } - return should; + return !should; } @Override public final void doRegister(URL url) { - if (!shouldRegister(url)) { - return; + synchronized (this) { + preInit(); + if (shouldNotRegister(url)) { + return; + } + repository.exportURL(url); } - repository.exportURL(url); } @Override public final void doUnregister(URL url) { - if (!shouldRegister(url)) { - return; + synchronized (this) { + preInit(); + if (shouldNotRegister(url)) { + return; + } + repository.unexportURL(url); } - repository.unexportURL(url); } @Override public final void doSubscribe(URL url, NotifyListener listener) { synchronized (this) { + preInit(); if (isAdminURL(url)) { // TODO in future if (logger.isWarnEnabled()) { @@ -452,7 +460,7 @@ public class DubboCloudRegistry extends FailbackRegistry return metadata.containsKey(METADATA_SERVICE_URLS_PROPERTY_NAME); } - Set getServices(URL url) { + private Set getServices(URL url) { Set subscribedServices = repository.getSubscribedServices(); if (subscribedServices.contains("*")) { subscribedServices = new HashSet<>(discoveryClient.getServices()); From fb9521b2e6649c913995ca96012dd5a4b8a78465 Mon Sep 17 00:00:00 2001 From: theonefx Date: Wed, 23 Jun 2021 16:26:54 +0800 Subject: [PATCH 45/99] remove unused code; make sure param not lost, so that different param calculate different revision. --- .../nacos/registry/NacosServiceRegistry.java | 3 +- .../metadata/DefaultMetadataParamsFilter.java | 55 ------ .../dubbo/metadata/MetadataParamsFilter.java | 35 ---- .../cloud/dubbo/metadata/ServiceInfo.java | 172 ++++-------------- .../dubbo/registry/DubboCloudRegistry.java | 5 +- ....cloud.dubbo.metadata.MetadataParamsFilter | 1 - 6 files changed, 39 insertions(+), 232 deletions(-) delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java index 16010b373..9b91ce48e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java @@ -161,7 +161,8 @@ public class NacosServiceRegistry implements ServiceRegistry { String serviceName = registration.getServiceId(); String group = nacosDiscoveryProperties.getGroup(); try { - List instances = namingService().getAllInstances(serviceName, group); + List instances = namingService().getAllInstances(serviceName, + group); for (Instance instance : instances) { if (instance.getIp().equalsIgnoreCase(nacosDiscoveryProperties.getIp()) && instance.getPort() == nacosDiscoveryProperties.getPort()) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java deleted file mode 100644 index 53d090f1c..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/DefaultMetadataParamsFilter.java +++ /dev/null @@ -1,55 +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.dubbo.metadata; - -import org.apache.dubbo.common.extension.Activate; - -import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.apache.dubbo.remoting.Constants.CODEC_KEY; -import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY; -import static org.apache.dubbo.remoting.Constants.EXCHANGER_KEY; -import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY; -import static org.apache.dubbo.rpc.Constants.DEPRECATED_KEY; -import static org.apache.dubbo.rpc.Constants.MOCK_KEY; -import static org.apache.dubbo.rpc.Constants.TOKEN_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.WARMUP_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY; - -/** - * Copy from org.apache.dubbo.metadata.DefaultMetadataParamsFilter. - * - * @author theonefx - */ -@Activate -public class DefaultMetadataParamsFilter implements MetadataParamsFilter { - - @Override - public String[] serviceParamsIncluded() { - return new String[] { CODEC_KEY, EXCHANGER_KEY, SERIALIZATION_KEY, CLUSTER_KEY, - CONNECTIONS_KEY, DEPRECATED_KEY, GROUP_KEY, LOADBALANCE_KEY, MOCK_KEY, - PATH_KEY, TIMEOUT_KEY, TOKEN_KEY, VERSION_KEY, WARMUP_KEY, WEIGHT_KEY, - DUBBO_VERSION_KEY, RELEASE_KEY }; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java deleted file mode 100644 index f7b4dc7d1..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/MetadataParamsFilter.java +++ /dev/null @@ -1,35 +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.dubbo.metadata; - -import org.apache.dubbo.common.extension.SPI; - -/** - * Copy from org.apache.dubbo.metadata.MetadataParamsFilter. - * - * @author theonefx - */ -@SPI -public interface MetadataParamsFilter { - - /** - * params that need to be sent to metadata center. - * @return arrays of keys - */ - String[] serviceParamsIncluded(); - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java index a734a8e7e..7e1095f98 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java @@ -20,23 +20,32 @@ import java.io.Serializable; import java.lang.reflect.Method; import java.util.Collections; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.SortedSet; +import java.util.TreeMap; import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.compiler.support.ClassUtils; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.StringUtils; -import static org.apache.dubbo.common.constants.CommonConstants.DOT_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY; import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; /** @@ -48,9 +57,6 @@ public class ServiceInfo implements Serializable { private static final long serialVersionUID = -258557978718735302L; - private static ExtensionLoader loader = ExtensionLoader - .getExtensionLoader(MetadataParamsFilter.class); - private String name; private String group; @@ -66,16 +72,6 @@ public class ServiceInfo implements Serializable { // params configured on consumer side, private transient Map consumerParams; - // cached method params - private transient Map> methodParams; - - private transient Map> consumerMethodParams; - - // cached numbers - private transient Map numbers; - - private transient Map> methodNumbers; - // service + group + version private transient String serviceKey; @@ -84,7 +80,20 @@ public class ServiceInfo implements Serializable { private transient URL url; - public ServiceInfo() { + private static final Set IGNORE_KEYS = new HashSet<>(); + static { + IGNORE_KEYS.add(TIMESTAMP_KEY); + IGNORE_KEYS.add(PID_KEY); + IGNORE_KEYS.add(INTERFACE_KEY); + IGNORE_KEYS.add(METHODS_KEY); + IGNORE_KEYS.add(THREADS_KEY); + IGNORE_KEYS.add(QUEUES_KEY); + IGNORE_KEYS.add(TIMEOUT_KEY); + IGNORE_KEYS.add(USERNAME_KEY); + IGNORE_KEYS.add(PASSWORD_KEY); + IGNORE_KEYS.add(HOST_KEY); + IGNORE_KEYS.add(PORT_KEY); + IGNORE_KEYS.add(RETRIES_KEY); } public ServiceInfo(URL url) { @@ -92,40 +101,16 @@ public class ServiceInfo implements Serializable { url.getParameter(VERSION_KEY), url.getProtocol(), url.getPath(), null); this.url = url; - Map params = new HashMap<>(); - List filters = loader.getActivateExtension(url, - "params-filter"); - for (MetadataParamsFilter filter : filters) { - String[] paramsIncluded = filter.serviceParamsIncluded(); - if (ArrayUtils.isNotEmpty(paramsIncluded)) { - for (String p : paramsIncluded) { - String value = url.getParameter(p); - if (StringUtils.isNotEmpty(value) && params.get(p) == null) { - params.put(p, value); - } - String[] methods = url.getParameter(METHODS_KEY, (String[]) null); - if (methods != null) { - for (String method : methods) { - String mValue = getMethodParameterStrict(url, method, p); - if (StringUtils.isNotEmpty(mValue)) { - params.put(method + DOT_SEPARATOR + p, mValue); - } - } - } - } + Map params = new TreeMap<>(); + url.getParameters().forEach((k, v) -> { + if (IGNORE_KEYS.contains(k)) { + return; } - } + params.put(k, v); + }); this.params = params; } - public String getMethodParameterStrict(URL url, String method, String key) { - Map keyMap = url.getMethodParameters().get(method); - String value = null; - if (keyMap != null) { - value = keyMap.get(key); - } - return value; - } public ServiceInfo(String name, String group, String version, String protocol, String path, Map params) { @@ -207,17 +192,6 @@ public class ServiceInfo implements Serializable { this.params = params; } - public Map getAllParams() { - if (consumerParams != null) { - Map allParams = new HashMap<>( - (int) ((params.size() + consumerParams.size()) / 0.75f + 1)); - allParams.putAll(params); - allParams.putAll(consumerParams); - return allParams; - } - return params; - } - public String getParameter(String key) { if (consumerParams != null) { String value = consumerParams.get(key); @@ -228,54 +202,12 @@ public class ServiceInfo implements Serializable { return params.get(key); } - public String getMethodParameter(String method, String key, String defaultValue) { - if (methodParams == null) { - methodParams = URL.toMethodParameters(params); - consumerMethodParams = URL.toMethodParameters(consumerParams); - } - - String value = getMethodParameter(method, key, consumerMethodParams); - if (value != null) { - return value; - } - value = getMethodParameter(method, key, methodParams); - return value == null ? defaultValue : value; - } - - private String getMethodParameter(String method, String key, - Map> map) { - Map keyMap = map.get(method); - String value = null; - if (keyMap != null) { - value = keyMap.get(key); - } - if (StringUtils.isEmpty(value)) { - value = getParameter(key); - } - return value; - } - - public boolean hasMethodParameter(String method, String key) { - String value = this.getMethodParameter(method, key, (String) null); - return StringUtils.isNotEmpty(value); - } - - public boolean hasMethodParameter(String method) { - if (methodParams == null) { - methodParams = URL.toMethodParameters(params); - consumerMethodParams = URL.toMethodParameters(consumerParams); - } - - return consumerMethodParams.containsKey(method) - || methodParams.containsKey(method); - } - public String toDescString() { return this.getMatchKey() + getMethodSignaturesString() + getParams(); } private String getMethodSignaturesString() { - SortedSet methodStrings = new TreeSet(); + SortedSet methodStrings = new TreeSet<>(); Method[] methods = ClassUtils.forName(name).getMethods(); for (Method method : methods) { @@ -284,40 +216,6 @@ public class ServiceInfo implements Serializable { return methodStrings.toString(); } - public void addParameter(String key, String value) { - if (consumerParams != null) { - this.consumerParams.put(key, value); - } - } - - public void addParameterIfAbsent(String key, String value) { - if (consumerParams != null) { - this.consumerParams.putIfAbsent(key, value); - } - } - - public void addConsumerParams(Map params) { - // copy once for one service subscription - if (consumerParams == null) { - consumerParams = new HashMap<>(params); - } - } - - public Map getNumbers() { - // concurrent initialization is tolerant - if (numbers == null) { - numbers = new ConcurrentHashMap<>(); - } - return numbers; - } - - public Map> getMethodNumbers() { - if (methodNumbers == null) { // concurrent initialization is tolerant - methodNumbers = new ConcurrentHashMap<>(); - } - return methodNumbers; - } - public URL getUrl() { return url; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index f02ebe1a2..f207d7994 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -244,9 +244,8 @@ public class DubboCloudRegistry extends FailbackRegistry String appName = event.getServiceName(); - List instances = filter( - event.getServiceInstances() != null ? event.getServiceInstances() - : Collections.emptyList()); + List instances = filter(event.getServiceInstances() != null + ? event.getServiceInstances() : Collections.emptyList()); Set subscribedServiceNames = getServices(null); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter deleted file mode 100644 index ce4f0db1e..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.cloud.dubbo.metadata.MetadataParamsFilter +++ /dev/null @@ -1 +0,0 @@ -default=com.alibaba.cloud.dubbo.metadata.DefaultMetadataParamsFilter \ No newline at end of file From c448027f34cdab68a740877e410b1406eca199ed Mon Sep 17 00:00:00 2001 From: theonefx Date: Wed, 23 Jun 2021 17:19:10 +0800 Subject: [PATCH 46/99] add spring-cloud-starter-bootstrap to compatible with spring boot bootstrap --- .../cloud/dubbo/metadata/ServiceInfo.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java index 7e1095f98..add184c4f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/ServiceInfo.java @@ -34,18 +34,10 @@ import org.apache.dubbo.common.utils.StringUtils; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY; import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; /** @@ -86,14 +78,6 @@ public class ServiceInfo implements Serializable { IGNORE_KEYS.add(PID_KEY); IGNORE_KEYS.add(INTERFACE_KEY); IGNORE_KEYS.add(METHODS_KEY); - IGNORE_KEYS.add(THREADS_KEY); - IGNORE_KEYS.add(QUEUES_KEY); - IGNORE_KEYS.add(TIMEOUT_KEY); - IGNORE_KEYS.add(USERNAME_KEY); - IGNORE_KEYS.add(PASSWORD_KEY); - IGNORE_KEYS.add(HOST_KEY); - IGNORE_KEYS.add(PORT_KEY); - IGNORE_KEYS.add(RETRIES_KEY); } public ServiceInfo(URL url) { @@ -111,7 +95,6 @@ public class ServiceInfo implements Serializable { this.params = params; } - public ServiceInfo(String name, String group, String version, String protocol, String path, Map params) { this.name = name; From 3009b162a0b78a0de6ba19336d9cad1f8c57c461 Mon Sep 17 00:00:00 2001 From: theonefx Date: Thu, 24 Jun 2021 20:55:41 +0800 Subject: [PATCH 47/99] add a router to make sure that use revision when invoke DubboMetadataService --- .../dubbo/metadata/RevisionResolver.java | 21 +++++- .../DubboServiceMetadataRepository.java | 7 +- .../dubbo/registry/DubboCloudRegistry.java | 15 +--- .../GenearalServiceSubscribeHandler.java | 24 +++++-- .../MetadataServiceSubscribeHandler.java | 10 +++ .../service/DubboMetadataServiceProxy.java | 1 + .../MetadataServiceRevisionRouterFactory.java | 69 +++++++++++++++++++ .../cloud/dubbo/util/DubboMetadataUtils.java | 8 ++- ...org.apache.dubbo.rpc.cluster.RouterFactory | 1 + 9 files changed, 128 insertions(+), 28 deletions(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.cluster.RouterFactory diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java index 53f9f1bf4..8ffc18457 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/RevisionResolver.java @@ -18,10 +18,14 @@ package com.alibaba.cloud.dubbo.metadata; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Map; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.springframework.cloud.client.ServiceInstance; + +import static com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository.EXPORTED_SERVICES_REVISION_PROPERTY_NAME; import static java.nio.charset.StandardCharsets.UTF_8; /** @@ -31,10 +35,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; */ public final class RevisionResolver { - private static final Logger logger = LoggerFactory.getLogger(RevisionResolver.class); + /** + * The param key in url. + */ + public static final String SCA_REVSION_KEY = "sca_revision"; private static final String EMPTY_REVISION = "0"; + private static final Logger logger = LoggerFactory.getLogger(RevisionResolver.class); + private static final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; @@ -71,4 +80,14 @@ public final class RevisionResolver { return new String(str); } + public static String getRevision(ServiceInstance instance) { + Map metadata = instance.getMetadata(); + String revision = metadata.get(EXPORTED_SERVICES_REVISION_PROPERTY_NAME); + + if (revision == null) { + revision = RevisionResolver.getEmptyRevision(); + } + return revision; + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java index 8b687cd19..2579b12ab 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -106,11 +106,6 @@ public class DubboServiceMetadataRepository */ public static String EXPORTED_SERVICES_REVISION_PROPERTY_NAME = "dubbo.metadata.revision"; - /** - * The {@link String#format(String, Object...) pattern} of dubbo protocols port. - */ - public static final String DUBBO_PROTOCOLS_PORT_PROPERTY_NAME_PATTERN = "dubbo.protocols.%s.port"; - private final Logger logger = LoggerFactory.getLogger(getClass()); private final ObjectMapper objectMapper = new ObjectMapper(); @@ -150,7 +145,7 @@ public class DubboServiceMetadataRepository * Key is application name Value is Map<RequestMetadata, * DubboRestServiceMetadata>. */ - private Map> dubboRestServiceMetadataRepository = newHashMap(); + private final Map> dubboRestServiceMetadataRepository = newHashMap(); // =============================================================== // diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java index f207d7994..643acdf1a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/DubboCloudRegistry.java @@ -47,7 +47,6 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; -import static com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository.EXPORTED_SERVICES_REVISION_PROPERTY_NAME; import static java.util.Collections.emptyList; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; @@ -130,7 +129,7 @@ public class DubboCloudRegistry extends FailbackRegistry .computeIfAbsent(appName, k -> new HashMap<>()); for (ServiceInstance instance : instances) { - String revision = getRevision(instance); + String revision = RevisionResolver.getRevision(instance); List list = map.computeIfAbsent(revision, k -> new ArrayList<>()); list.add(instance); @@ -262,7 +261,7 @@ public class DubboCloudRegistry extends FailbackRegistry } // group by revision Map> newGroup = instances.stream() - .collect(Collectors.groupingBy(this::getRevision)); + .collect(Collectors.groupingBy(RevisionResolver::getRevision)); synchronized (this) { @@ -439,16 +438,6 @@ public class DubboCloudRegistry extends FailbackRegistry return true; } - String getRevision(ServiceInstance instance) { - Map metadata = instance.getMetadata(); - String revision = metadata.get(EXPORTED_SERVICES_REVISION_PROPERTY_NAME); - - if (revision == null) { - revision = RevisionResolver.getEmptyRevision(); - } - return revision; - } - private List filter(Collection serviceInstances) { return serviceInstances.stream().filter(this::isDubboServiceInstance) .collect(Collectors.toList()); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java index a2f3ca4f7..b92e8c4e5 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java @@ -27,6 +27,7 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.alibaba.cloud.dubbo.metadata.RevisionResolver; import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository; import com.alibaba.cloud.dubbo.service.DubboMetadataService; import com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy; @@ -34,9 +35,11 @@ import com.alibaba.cloud.dubbo.util.JSONUtils; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.registry.NotifyListener; +import org.apache.dubbo.rpc.RpcContext; import org.springframework.cloud.client.ServiceInstance; +import static com.alibaba.cloud.dubbo.metadata.RevisionResolver.SCA_REVSION_KEY; import static java.util.Collections.emptyList; import static org.apache.dubbo.common.URLBuilder.from; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; @@ -50,6 +53,9 @@ import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; */ public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHandler { + /** + * the provider which can provide service of the url. {appName, [revisions]} + */ private final Map> providers = new HashMap<>(); private final Map urlTemplateMap = new HashMap<>(); @@ -117,7 +123,7 @@ public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHan public void init(String appName, String revision, List instanceList) { - List urls = getTemplateExportedURLs(url, instanceList); + List urls = getTemplateExportedURLs(url, revision, instanceList); if (urls != null && urls.size() > 0) { addAppNameWithRevision(appName, revision); setUrlTemplate(appName, revision, urls); @@ -170,7 +176,7 @@ public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHan String host = serviceInstance.getHost(); String appName = serviceInstance.getServiceId(); - String revision = registry.getRevision(serviceInstance); + String revision = RevisionResolver.getRevision(serviceInstance); URL template = urlTemplateMap.get(getAppRevisionKey(appName, revision)); @@ -225,7 +231,7 @@ public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHan return urlsCloneTo; } - private List getTemplateExportedURLs(URL subscribedURL, + private List getTemplateExportedURLs(URL subscribedURL, String revision, List serviceInstances) { DubboMetadataService dubboMetadataService = getProxy(serviceInstances); @@ -233,7 +239,8 @@ public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHan List templateExportedURLs = emptyList(); if (dubboMetadataService != null) { - templateExportedURLs = getExportedURLs(dubboMetadataService, subscribedURL); + templateExportedURLs = getExportedURLs(dubboMetadataService, revision, + subscribedURL); } else { if (logger.isWarnEnabled()) { @@ -253,14 +260,17 @@ public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHan } private List getExportedURLs(DubboMetadataService dubboMetadataService, - URL subscribedURL) { + String revision, URL subscribedURL) { String serviceInterface = subscribedURL.getServiceInterface(); String group = subscribedURL.getParameter(GROUP_KEY); String version = subscribedURL.getParameter(VERSION_KEY); - // The subscribed protocol may be null - String subscribedProtocol = subscribedURL.getParameter(PROTOCOL_KEY); + + RpcContext.getContext().setAttachment(SCA_REVSION_KEY, revision); String exportedURLsJSON = dubboMetadataService.getExportedURLs(serviceInterface, group, version); + + // The subscribed protocol may be null + String subscribedProtocol = subscribedURL.getParameter(PROTOCOL_KEY); return jsonUtils.toURLs(exportedURLsJSON).stream() .filter(exportedURL -> subscribedProtocol == null || subscribedProtocol.equalsIgnoreCase(exportedURL.getProtocol())) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java index 9a9f99325..089c986da 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java @@ -20,12 +20,15 @@ import java.util.List; import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.registry.NotifyListener; import org.springframework.cloud.client.ServiceInstance; 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.common.constants.RegistryConstants.ROUTE_PROTOCOL; +import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY; /** * @author theonefx @@ -44,6 +47,7 @@ public class MetadataServiceSubscribeHandler extends AbstractServiceSubscribeHan this.dubboMetadataUtils = dubboMetadataUtils; } + @Override public void doInit() { logger.debug("Subscription app {} MetadataService handler init", appName); List serviceInstances = registry.getServiceInstances(appName); @@ -69,6 +73,12 @@ public class MetadataServiceSubscribeHandler extends AbstractServiceSubscribeHan List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, serviceInterface, version, protocol); + URLBuilder builder = new URLBuilder(); + builder.setProtocol(ROUTE_PROTOCOL); + builder.addParameter(ROUTER_KEY, "revisionRouter"); + + urls.add(builder.build()); + notifyAllSubscribedURLs(subscribedURL, urls, listener); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java index b6f65fa67..c653c52ec 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboMetadataServiceProxy.java @@ -125,6 +125,7 @@ public class DubboMetadataServiceProxy implements BeanClassLoaderAware, Disposab private DubboMetadataService createProxyIfAbsent(URL dubboMetadataServiceURL) { String serviceName = dubboMetadataServiceURL.getParameter(APPLICATION_KEY); String version = dubboMetadataServiceURL.getParameter(VERSION_KEY); + // Initialize DubboMetadataService with right version return createProxyIfAbsent(serviceName, version); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java new file mode 100644 index 000000000..340acb32b --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java @@ -0,0 +1,69 @@ +/* + * 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.service; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.cloud.commons.lang.StringUtils; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.cluster.Router; +import org.apache.dubbo.rpc.cluster.RouterFactory; +import org.apache.dubbo.rpc.cluster.router.AbstractRouter; + +import static com.alibaba.cloud.dubbo.metadata.RevisionResolver.SCA_REVSION_KEY; + +/** + * @author theonefx + */ +public class MetadataServiceRevisionRouterFactory implements RouterFactory { + + @Override + public Router getRouter(URL url) { + return new AbstractRouter() { + @Override + public List> route(List> invokers, URL url, + Invocation invocation) throws RpcException { + if (!DubboMetadataService.class.getName() + .equalsIgnoreCase(url.getServiceInterface())) { + return invokers; + } + + String revision = invocation.getAttachment(SCA_REVSION_KEY); + + if (StringUtils.isEmpty(revision)) { + return invokers; + } + + List> list = new ArrayList<>(invokers.size()); + + for (Invoker invoker : invokers) { + if (StringUtils.equals(revision, + invoker.getUrl().getParameter(SCA_REVSION_KEY))) { + list.add(invoker); + } + } + + return list; + } + }; + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboMetadataUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboMetadataUtils.java index af3c59460..acb4c2a14 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboMetadataUtils.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/util/DubboMetadataUtils.java @@ -21,12 +21,14 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import com.alibaba.cloud.dubbo.metadata.RevisionResolver; import com.alibaba.cloud.dubbo.service.DubboMetadataService; import org.apache.dubbo.common.URL; import org.springframework.cloud.client.ServiceInstance; import org.springframework.core.env.Environment; +import static com.alibaba.cloud.dubbo.metadata.RevisionResolver.SCA_REVSION_KEY; import static java.lang.String.format; import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME; @@ -74,7 +76,11 @@ public class DubboMetadataUtils { public List getDubboMetadataServiceURLs(ServiceInstance serviceInstance) { Map metadata = serviceInstance.getMetadata(); String dubboURLsJSON = metadata.get(METADATA_SERVICE_URLS_PROPERTY_NAME); - return jsonUtils.toURLs(dubboURLsJSON); + List urls = jsonUtils.toURLs(dubboURLsJSON); + String revision = RevisionResolver.getRevision(serviceInstance); + urls = urls.stream().map(url -> url.addParameter(SCA_REVSION_KEY, revision)) + .collect(Collectors.toList()); + return urls; } /** diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.cluster.RouterFactory b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.cluster.RouterFactory new file mode 100644 index 000000000..f56d67e6d --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.cluster.RouterFactory @@ -0,0 +1 @@ +revisionRouter=com.alibaba.cloud.dubbo.service.MetadataServiceRevisionRouterFactory \ No newline at end of file From 374964d8dce75f04c3471e48a421892a1e5d0d16 Mon Sep 17 00:00:00 2001 From: theonefx Date: Thu, 24 Jun 2021 21:49:21 +0800 Subject: [PATCH 48/99] add router url when urls is not empty --- .../registry/MetadataServiceSubscribeHandler.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java index 089c986da..50ee604e8 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java @@ -73,11 +73,12 @@ public class MetadataServiceSubscribeHandler extends AbstractServiceSubscribeHan List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, serviceInterface, version, protocol); - URLBuilder builder = new URLBuilder(); - builder.setProtocol(ROUTE_PROTOCOL); - builder.addParameter(ROUTER_KEY, "revisionRouter"); - - urls.add(builder.build()); + if (urls.size() > 0) { + URLBuilder builder = new URLBuilder(); + builder.setProtocol(ROUTE_PROTOCOL); + builder.addParameter(ROUTER_KEY, "revisionRouter"); + urls.add(builder.build()); + } notifyAllSubscribedURLs(subscribedURL, urls, listener); } From 5f7ddab58e43262f57577667c9b23a038bdd2d1d Mon Sep 17 00:00:00 2001 From: theonefx Date: Fri, 25 Jun 2021 17:49:58 +0800 Subject: [PATCH 49/99] avoid defult router impact DubboMetadataService works --- .../registry/MetadataServiceSubscribeHandler.java | 12 ++++++------ .../dubbo/service/DubboGenericServiceFactory.java | 3 +++ .../MetadataServiceRevisionRouterFactory.java | 6 ++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java index 50ee604e8..6e0009ab2 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java @@ -73,12 +73,12 @@ public class MetadataServiceSubscribeHandler extends AbstractServiceSubscribeHan List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, serviceInterface, version, protocol); - if (urls.size() > 0) { - URLBuilder builder = new URLBuilder(); - builder.setProtocol(ROUTE_PROTOCOL); - builder.addParameter(ROUTER_KEY, "revisionRouter"); - urls.add(builder.build()); - } +// if (urls.size() > 0) { +// URLBuilder builder = new URLBuilder(); +// builder.setProtocol(ROUTE_PROTOCOL); +// builder.addParameter(ROUTER_KEY, "revisionRouter"); +// urls.add(builder.build()); +// } notifyAllSubscribedURLs(subscribedURL, urls, listener); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java index d1a68c5f0..9ba24343d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/DubboGenericServiceFactory.java @@ -78,6 +78,9 @@ public class DubboGenericServiceFactory { String interfaceName = serviceClass.getName(); ReferenceBean referenceBean = build(interfaceName, version, serviceName, emptyMap()); + if (DubboMetadataService.class == serviceClass) { + referenceBean.setRouter("-default,revisionRouter"); + } return referenceBean.get(); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java index 340acb32b..9d47c53b7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/service/MetadataServiceRevisionRouterFactory.java @@ -28,6 +28,8 @@ import org.apache.dubbo.rpc.cluster.Router; import org.apache.dubbo.rpc.cluster.RouterFactory; import org.apache.dubbo.rpc.cluster.router.AbstractRouter; +import org.springframework.util.CollectionUtils; + import static com.alibaba.cloud.dubbo.metadata.RevisionResolver.SCA_REVSION_KEY; /** @@ -41,6 +43,10 @@ public class MetadataServiceRevisionRouterFactory implements RouterFactory { @Override public List> route(List> invokers, URL url, Invocation invocation) throws RpcException { + if (CollectionUtils.isEmpty(invokers)) { + return invokers; + } + if (!DubboMetadataService.class.getName() .equalsIgnoreCase(url.getServiceInterface())) { return invokers; From d69f66cc3e227a641dab61a2ca05224197714702 Mon Sep 17 00:00:00 2001 From: theonefx Date: Fri, 25 Jun 2021 18:13:56 +0800 Subject: [PATCH 50/99] avoid defult router impact DubboMetadataService works --- .../registry/MetadataServiceSubscribeHandler.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java index 6e0009ab2..014131cd1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/MetadataServiceSubscribeHandler.java @@ -20,15 +20,12 @@ import java.util.List; import com.alibaba.cloud.dubbo.util.DubboMetadataUtils; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.registry.NotifyListener; import org.springframework.cloud.client.ServiceInstance; 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.common.constants.RegistryConstants.ROUTE_PROTOCOL; -import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY; /** * @author theonefx @@ -73,13 +70,6 @@ public class MetadataServiceSubscribeHandler extends AbstractServiceSubscribeHan List urls = dubboMetadataUtils.getDubboMetadataServiceURLs(serviceInstances, serviceInterface, version, protocol); -// if (urls.size() > 0) { -// URLBuilder builder = new URLBuilder(); -// builder.setProtocol(ROUTE_PROTOCOL); -// builder.addParameter(ROUTER_KEY, "revisionRouter"); -// urls.add(builder.build()); -// } - notifyAllSubscribedURLs(subscribedURL, urls, listener); } From c5949a58632174ac08d9023b2614b29b560d2327 Mon Sep 17 00:00:00 2001 From: theonefx Date: Fri, 2 Jul 2021 10:38:01 +0800 Subject: [PATCH 51/99] support ak/sk authentication when using serverAddr --- .../datasource/factorybean/NacosDataSourceFactoryBean.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java index 6d70e710a..e8bf42e4c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java @@ -60,9 +60,14 @@ public class NacosDataSourceFactoryBean implements FactoryBean properties.setProperty(PropertyKeyConst.SERVER_ADDR, this.serverAddr); } else { + properties.setProperty(PropertyKeyConst.ENDPOINT, this.endpoint); + } + + if (!StringUtils.isEmpty(this.accessKey)) { properties.setProperty(PropertyKeyConst.ACCESS_KEY, this.accessKey); + } + if (!StringUtils.isEmpty(this.secretKey)) { properties.setProperty(PropertyKeyConst.SECRET_KEY, this.secretKey); - properties.setProperty(PropertyKeyConst.ENDPOINT, this.endpoint); } if (!StringUtils.isEmpty(this.namespace)) { properties.setProperty(PropertyKeyConst.NAMESPACE, this.namespace); From ec1f65f99da578f28529116f090f2c9133d8e1f9 Mon Sep 17 00:00:00 2001 From: theonefx Date: Tue, 6 Jul 2021 12:53:03 +0800 Subject: [PATCH 52/99] use aop to save and get FeignClientFactoryBean replace to applicationContext.getBean --- .../cloud/sentinel/feign/SentinelFeign.java | 59 ++++++++++--------- .../feign/SentinelFeignAutoConfiguration.java | 7 +++ .../feign/SentinelTargeterAspect.java | 51 ++++++++++++++++ 3 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java index 5b2f89d85..c0809fa9f 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java @@ -80,34 +80,37 @@ public final class SentinelFeign { // using reflect get fallback and fallbackFactory properties from // FeignClientFactoryBean because FeignClientFactoryBean is a package // level class, we can not use it in our package - Object feignClientFactoryBean = Builder.this.applicationContext - .getBean("&" + target.type().getName()); - - Class fallback = (Class) getFieldValue(feignClientFactoryBean, - "fallback"); - Class fallbackFactory = (Class) getFieldValue(feignClientFactoryBean, - "fallbackFactory"); - String beanName = (String) getFieldValue(feignClientFactoryBean, - "contextId"); - if (!StringUtils.hasText(beanName)) { - beanName = (String) getFieldValue(feignClientFactoryBean, "name"); - } - - Object fallbackInstance; - FallbackFactory fallbackFactoryInstance; - // check fallback and fallbackFactory properties - if (void.class != fallback) { - fallbackInstance = getFromContext(beanName, "fallback", fallback, - target.type()); - return new SentinelInvocationHandler(target, dispatch, - new FallbackFactory.Default(fallbackInstance)); - } - if (void.class != fallbackFactory) { - fallbackFactoryInstance = (FallbackFactory) getFromContext( - beanName, "fallbackFactory", fallbackFactory, - FallbackFactory.class); - return new SentinelInvocationHandler(target, dispatch, - fallbackFactoryInstance); + Object feignClientFactoryBean = SentinelTargeterAspect + .getFeignClientFactoryBean(); + + if (feignClientFactoryBean != null) { + Class fallback = (Class) getFieldValue(feignClientFactoryBean, + "fallback"); + Class fallbackFactory = (Class) getFieldValue( + feignClientFactoryBean, "fallbackFactory"); + String beanName = (String) getFieldValue(feignClientFactoryBean, + "contextId"); + if (!StringUtils.hasText(beanName)) { + beanName = (String) getFieldValue(feignClientFactoryBean, + "name"); + } + + Object fallbackInstance; + FallbackFactory fallbackFactoryInstance; + // check fallback and fallbackFactory properties + if (void.class != fallback) { + fallbackInstance = getFromContext(beanName, "fallback", + fallback, target.type()); + return new SentinelInvocationHandler(target, dispatch, + new FallbackFactory.Default(fallbackInstance)); + } + if (void.class != fallbackFactory) { + fallbackFactoryInstance = (FallbackFactory) getFromContext( + beanName, "fallbackFactory", fallbackFactory, + FallbackFactory.class); + return new SentinelInvocationHandler(target, dispatch, + fallbackFactoryInstance); + } } return new SentinelInvocationHandler(target, dispatch); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java index 5a7ba59c4..d78dd0b2e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java @@ -41,4 +41,11 @@ public class SentinelFeignAutoConfiguration { return SentinelFeign.builder(); } + @Bean + @ConditionalOnProperty(name = "feign.sentinel.enabled") + @ConditionalOnClass(name = "org.springframework.cloud.openfeign.Targeter") + public SentinelTargeterAspect sentinelTargeterAspect() { + return new SentinelTargeterAspect(); + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java new file mode 100644 index 000000000..69873b52c --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java @@ -0,0 +1,51 @@ +/* + * 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.feign; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; + +/** + * Record FeignClientFactoryBean to threadlocal, so that SentinelFeign can get it when + * creating SentinelInvocationHandler. + * + * @see com.alibaba.cloud.sentinel.feign.SentinelFeign.Builder + * @author theonefx + */ +@Aspect +public class SentinelTargeterAspect { + + private static final ThreadLocal FEIGN_CLIENT_FACTORY_BEAN = new ThreadLocal<>(); + + public static Object getFeignClientFactoryBean() { + return FEIGN_CLIENT_FACTORY_BEAN.get(); + } + + @Around("execution(* org.springframework.cloud.openfeign.Targeter.target(..))") + public Object process(ProceedingJoinPoint pjp) throws Throwable { + Object factory = pjp.getArgs()[0]; + try { + FEIGN_CLIENT_FACTORY_BEAN.set(factory); + return pjp.proceed(); + } + finally { + FEIGN_CLIENT_FACTORY_BEAN.remove(); + } + } + +} From aa580ac3b6c61bc7865293734c20a265fb0a111e Mon Sep 17 00:00:00 2001 From: theonefx Date: Wed, 7 Jul 2021 16:49:08 +0800 Subject: [PATCH 53/99] throw exception directly when exception is not an BlockException in SentinelProtectInterceptor --- .../custom/SentinelProtectInterceptor.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java index fbd468b26..63d688aed 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java @@ -86,13 +86,23 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor Tracer.trace( new IllegalStateException("RestTemplate ErrorHandler has error")); } + return response; } catch (Throwable e) { - if (!BlockException.isBlockException(e)) { - Tracer.trace(e); + if (BlockException.isBlockException(e)) { + return handleBlockException(request, body, execution, (BlockException) e); } else { - return handleBlockException(request, body, execution, (BlockException) e); + Tracer.trace(e); + if (e instanceof IOException) { + throw (IOException) e; + } + else if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + else { + throw new IOException(e); + } } } finally { @@ -103,7 +113,6 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor hostEntry.exit(); } } - return response; } private ClientHttpResponse handleBlockException(HttpRequest request, byte[] body, From df096fdfb532a870837d6fba7f8a781cab5799a2 Mon Sep 17 00:00:00 2001 From: theonefx Date: Thu, 8 Jul 2021 11:10:21 +0800 Subject: [PATCH 54/99] Sentinel is called in a more secure way --- .../cloud/sentinel/custom/SentinelProtectInterceptor.java | 2 +- .../alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java index 63d688aed..5fdc0c0d4 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/custom/SentinelProtectInterceptor.java @@ -93,7 +93,7 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor return handleBlockException(request, body, execution, (BlockException) e); } else { - Tracer.trace(e); + Tracer.traceEntry(e, hostEntry); if (e instanceof IOException) { throw (IOException) e; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java index e5f80a62b..22d72c541 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java @@ -109,7 +109,7 @@ public class SentinelInvocationHandler implements InvocationHandler { catch (Throwable ex) { // fallback handle if (!BlockException.isBlockException(ex)) { - Tracer.trace(ex); + Tracer.traceEntry(ex, entry); } if (fallbackFactory != null) { try { From b4adbb65cc6653092306e2a158b12c1ec471b179 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Thu, 8 Jul 2021 16:39:50 +0800 Subject: [PATCH 55/99] NacosWatch use a separate thread pool --- .../discovery/NacosDiscoveryClientConfiguration.java | 8 ++------ .../com/alibaba/cloud/nacos/discovery/NacosWatch.java | 8 ++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) 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 d2f2f8ba6..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 @@ -20,7 +20,6 @@ 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; @@ -32,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.concurrent.ThreadPoolTaskScheduler; /** * @author xiaojing @@ -58,10 +56,8 @@ public class NacosDiscoveryClientConfiguration { @ConditionalOnProperty(value = "spring.cloud.nacos.discovery.watch.enabled", matchIfMissing = true) public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager, - NacosDiscoveryProperties nacosDiscoveryProperties, - ObjectProvider taskExecutorObjectProvider) { - return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties, - taskExecutorObjectProvider); + 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 bcb590351..22a7f6766 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 @@ -66,6 +66,14 @@ public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycl private final ThreadPoolTaskScheduler taskScheduler; + public NacosWatch(NacosServiceManager nacosServiceManager, + NacosDiscoveryProperties properties) { + this.nacosServiceManager = nacosServiceManager; + this.properties = properties; + this.taskScheduler = getTaskScheduler(); + } + + @Deprecated public NacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties, ObjectProvider taskScheduler) { From 7825cb0ceb09ac207e00637fe9f7c6080960f5d5 Mon Sep 17 00:00:00 2001 From: XuDaojie Date: Sat, 10 Jul 2021 12:47:30 +0800 Subject: [PATCH 56/99] update nacos-discovery.adoc --- .../src/main/asciidoc-zh/nacos-discovery.adoc | 11 +++++++++++ .../src/main/asciidoc/nacos-discovery.adoc | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc index 3457e2a86..7ab47d88a 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc @@ -291,6 +291,17 @@ Endpoint 暴露的 json 中包含了两种属性: } ---- +=== 如何开启权重路由 + +==== Ribbon + +.application.properties +[source,properties] +---- +[service_name].ribbon.NFLoadBalancerRuleClassName=com.alibaba.cloud.nacos.ribbon.NacosRule +---- + + === 关于 Nacos Discovery Starter 更多的配置项信息 更多关于 Nacos Discovery Starter 的配置项如下所示: diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-discovery.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-discovery.adoc index 8937bb7b9..27896076b 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-discovery.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-discovery.adoc @@ -294,6 +294,16 @@ The followings shows how a service instance accesses the Endpoint: } ---- +=== Weight Route + +==== Ribbon + +.application.properties +[source,properties] +---- +[service_name].ribbon.NFLoadBalancerRuleClassName=com.alibaba.cloud.nacos.ribbon.NacosRule +---- + === More Information about Nacos Discovery Starter Configurations The following shows the other configurations of the starter of Nacos Discovery: From 4d697bb2948bb00a7453f7888084774882a72753 Mon Sep 17 00:00:00 2001 From: theonefx Date: Sat, 10 Jul 2021 18:13:32 +0800 Subject: [PATCH 57/99] fix #2157 --- ...oServiceRegistrationAutoConfiguration.java | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java index b0897e6ca..d26108005 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java @@ -18,6 +18,7 @@ package com.alibaba.cloud.dubbo.autoconfigure; import java.util.Collection; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -50,6 +51,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.ServiceRegistry; +import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties; import org.springframework.cloud.consul.serviceregistry.ConsulRegistration; import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration; @@ -61,6 +63,7 @@ import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.event.EventListener; +import org.springframework.util.StringUtils; import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_SERVICE_AUTO_CONFIGURATION_CLASS_NAME; import static com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_CLIENT_AUTO_CONFIGURATION_CLASS_NAME; @@ -77,12 +80,11 @@ import static org.springframework.util.ObjectUtils.isEmpty; @Configuration(proxyBeanMethods = false) @Import({ DubboServiceRegistrationEventPublishingAspect.class, DubboBootstrapStartCommandLineRunner.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 { /** @@ -260,6 +262,9 @@ public class DubboServiceRegistrationAutoConfiguration { @AutoConfigureOrder class ConsulConfiguration { + @Autowired + private ConsulDiscoveryProperties consulDiscoveryProperties; + @EventListener(DubboBootstrapStartedEvent.class) public void attachURLsIntoMetadataBeforeReRegist( DubboBootstrapStartedEvent event) { @@ -284,18 +289,41 @@ public class DubboServiceRegistrationAutoConfiguration { })); } + @EventListener(ServiceInstancePreRegisteredEvent.class) + public void onServiceInstancePreRegistered( + ServiceInstancePreRegisteredEvent event) { + Registration registration = event.getSource(); + attachURLsIntoMetadata((ConsulRegistration) registration); + } + private void attachURLsIntoMetadata(ConsulRegistration consulRegistration) { - NewService newService = consulRegistration.getService(); Map serviceMetadata = dubboServiceMetadataRepository .getDubboMetadataServiceMetadata(); - if (!isEmpty(serviceMetadata)) { - List tags = newService.getTags(); + if (isEmpty(serviceMetadata)) { + return; + } + NewService newService = consulRegistration.getService(); + if (consulDiscoveryProperties.isTagsAsMetadata()) { for (Map.Entry entry : serviceMetadata.entrySet()) { - tags.add(entry.getKey() + "=" + entry.getValue()); + attAsTag(newService.getTags(), entry.getKey(), entry.getValue()); } } + else { + newService.getMeta().putAll(serviceMetadata); + } } + private void attAsTag(List tags, String key, String value) { + Iterator iter = tags.iterator(); + while (iter.hasNext()) { + String tag = iter.next(); + String[] tmp = tag.split("="); + if (StringUtils.pathEquals(tmp[0], key)) { + iter.remove(); + } + } + tags.add(key + "=" + value); + } } } From 4356f1be49455ef090082955384b13170cd9a7b2 Mon Sep 17 00:00:00 2001 From: theonefx Date: Sat, 10 Jul 2021 18:41:18 +0800 Subject: [PATCH 58/99] fix #2157 --- .../DubboServiceRegistrationAutoConfiguration.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java index d26108005..8d8d8df12 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java @@ -80,11 +80,12 @@ import static org.springframework.util.ObjectUtils.isEmpty; @Configuration(proxyBeanMethods = false) @Import({ DubboServiceRegistrationEventPublishingAspect.class, DubboBootstrapStartCommandLineRunner.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 { /** @@ -324,6 +325,7 @@ public class DubboServiceRegistrationAutoConfiguration { } tags.add(key + "=" + value); } + } } From ca49df5ca46ff08dc94484275a930061662f9234 Mon Sep 17 00:00:00 2001 From: theonefx Date: Sat, 10 Jul 2021 23:35:36 +0800 Subject: [PATCH 59/99] add dependency of commons --- .../spring-cloud-starter-dubbo/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml index b404252b1..925bb2735 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/pom.xml @@ -17,6 +17,11 @@ + + com.alibaba.cloud + spring-cloud-alibaba-commons + + org.springframework.boot From 7d9751304e58c63932ab8aba26f30d7e763563fd Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Tue, 3 Aug 2021 13:59:44 +0800 Subject: [PATCH 60/99] enhance Nacos shutdown code --- .../com/alibaba/cloud/nacos/NacosServiceManager.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosServiceManager.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosServiceManager.java index c672bbac0..31f68cd99 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosServiceManager.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosServiceManager.java @@ -112,9 +112,14 @@ public class NacosServiceManager { } public void nacosServiceShutDown() throws NacosException { - this.namingService.shutDown(); - namingService = null; - namingMaintainService = null; + if (Objects.nonNull(this.namingService)) { + this.namingService.shutDown(); + this.namingService = null; + } + if (Objects.nonNull(this.namingMaintainService)) { + this.namingMaintainService.shutDown(); + this.namingMaintainService = null; + } } @EventListener From 8cddc0525f3515ff0522dc9030081e1c80ea1727 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Sat, 7 Aug 2021 09:00:39 +0800 Subject: [PATCH 61/99] SidecarHealthChecker customer --- .../sidecar/CustomHealthCheckHandler.java | 26 +++++++++++ .../cloud/sidecar/SidecarHealthChecker.java | 45 ++++++++++++------- ...nceCache.java => SidecarInstanceInfo.java} | 4 +- 3 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/CustomHealthCheckHandler.java rename spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/{SidecarInstanceCache.java => SidecarInstanceInfo.java} (94%) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/CustomHealthCheckHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/CustomHealthCheckHandler.java new file mode 100644 index 000000000..69598f1c0 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/CustomHealthCheckHandler.java @@ -0,0 +1,26 @@ +/* + * 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; + +/** + * @author yuhuangbin + */ +public interface CustomHealthCheckHandler { + + void handler(String applicationName, SidecarInstanceInfo sidecarInstanceInfo); + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java index eaf426392..e5673aaa8 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarHealthChecker.java @@ -25,6 +25,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import reactor.core.scheduler.Schedulers; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.Status; import org.springframework.core.env.ConfigurableEnvironment; @@ -37,7 +39,7 @@ public class SidecarHealthChecker { private static final Logger log = LoggerFactory.getLogger(SidecarHealthChecker.class); - private final Map sidecarInstanceCacheMap = new ConcurrentHashMap<>(); + private final Map sidecarInstanceCacheMap = new ConcurrentHashMap<>(); private final SidecarDiscoveryClient sidecarDiscoveryClient; @@ -47,6 +49,9 @@ public class SidecarHealthChecker { private final ConfigurableEnvironment environment; + @Autowired + private ObjectProvider customHealthCheckHandlerObjectProvider; + public SidecarHealthChecker(SidecarDiscoveryClient sidecarDiscoveryClient, HealthIndicator healthIndicator, SidecarProperties sidecarProperties, ConfigurableEnvironment environment) { @@ -64,9 +69,10 @@ public class SidecarHealthChecker { Status status = healthIndicator.health().getStatus(); - instanceCache(applicationName, ip, port, status); + SidecarInstanceInfo sidecarInstanceInfo = instanceCache(applicationName, ip, + port, status); if (status.equals(Status.UP)) { - if (needRegister(applicationName, ip, port, status)) { + if (needRegister(applicationName, sidecarInstanceInfo)) { this.sidecarDiscoveryClient.registerInstance(applicationName, ip, port); log.info( @@ -84,30 +90,37 @@ public class SidecarHealthChecker { buildCache(ip, port, status)); } + try { + customHealthCheckHandlerObjectProvider + .ifAvailable(customHealthCheckHandler -> customHealthCheckHandler + .handler(applicationName, sidecarInstanceInfo)); + } + catch (Exception e) { + // ignore + } }, 0, sidecarProperties.getHealthCheckInterval(), TimeUnit.MILLISECONDS); } - private void instanceCache(String applicationName, String ip, Integer port, - Status status) { - sidecarInstanceCacheMap.putIfAbsent(applicationName, - buildCache(ip, port, status)); + private SidecarInstanceInfo instanceCache(String applicationName, String ip, + Integer port, Status status) { + SidecarInstanceInfo sidecarInstanceInfo = buildCache(ip, port, status); + sidecarInstanceCacheMap.putIfAbsent(applicationName, sidecarInstanceInfo); + return sidecarInstanceInfo; } - 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)) { + private boolean needRegister(String applicationName, + SidecarInstanceInfo sidecarInstanceInfo) { + SidecarInstanceInfo cacheRecord = sidecarInstanceCacheMap.get(applicationName); + if (!Objects.equals(sidecarInstanceInfo, cacheRecord)) { // modify the cache info - sidecarInstanceCacheMap.put(applicationName, cache); + sidecarInstanceCacheMap.put(applicationName, sidecarInstanceInfo); return true; } return false; } - private SidecarInstanceCache buildCache(String ip, Integer port, Status status) { - SidecarInstanceCache cache = new SidecarInstanceCache(); + private SidecarInstanceInfo buildCache(String ip, Integer port, Status status) { + SidecarInstanceInfo cache = new SidecarInstanceInfo(); cache.setIp(ip); cache.setPort(port); cache.setStatus(status); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceCache.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceInfo.java similarity index 94% rename from spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceCache.java rename to spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceInfo.java index 0c18f1aa4..14892268a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceCache.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sidecar/src/main/java/com/alibaba/cloud/sidecar/SidecarInstanceInfo.java @@ -23,7 +23,7 @@ import org.springframework.boot.actuate.health.Status; /** * @author yuhuangbin */ -public class SidecarInstanceCache { +public class SidecarInstanceInfo { private String ip; @@ -63,7 +63,7 @@ public class SidecarInstanceCache { if (o == null || getClass() != o.getClass()) { return false; } - SidecarInstanceCache that = (SidecarInstanceCache) o; + SidecarInstanceInfo that = (SidecarInstanceInfo) o; return Objects.equals(ip, that.ip) && Objects.equals(port, that.port) && Objects.equals(status, that.status); } From 568c64b1cfb5947e2a491e9e557cf713111a3927 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Wed, 18 Aug 2021 10:03:31 +0800 Subject: [PATCH 62/99] document --- .../src/main/asciidoc-zh/rocketmq-new.adoc | 378 ++++++++++++++++++ .../alibaba/cloud/examples/SenderService.java | 2 +- .../{contants => constant}/RocketMQConst.java | 2 +- .../RocketMQProducerMessageHandler.java | 2 +- .../RocketMQMessageConverterSupport.java | 4 +- .../binder/rocketmq/utils/RocketMQUtils.java | 2 +- 6 files changed, 384 insertions(+), 6 deletions(-) create mode 100644 spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc rename spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/{contants => constant}/RocketMQConst.java (97%) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc new file mode 100644 index 000000000..a08d5f8ca --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc @@ -0,0 +1,378 @@ +== Spring Cloud Alibaba RocketMQ Binder + +=== RocketMQ 介绍 + +https://rocketmq.apache.org[RocketMQ] 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。 + +具有以下特点: + +* 能够保证严格的消息顺序 + +* 提供丰富的消息拉取模式 + +* 高效的订阅者水平扩展能力 + +* 实时的消息订阅机制 + +* 亿级消息堆积能力 + +=== RocketMQ 基本使用 + +* 下载 RocketMQ + +下载 https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip[RocketMQ最新的二进制文件],并解压 + +解压后的目录结构如下: + +``` +apache-rocketmq +├── LICENSE +├── NOTICE +├── README.md +├── benchmark +├── bin +├── conf +└── lib +``` + +* 启动 NameServer + +```bash +nohup sh bin/mqnamesrv & +tail -f ~/logs/rocketmqlogs/namesrv.log +``` + +* 启动 Broker + +```bash +nohup sh bin/mqbroker -n localhost:9876 & +tail -f ~/logs/rocketmqlogs/broker.log +``` + +* 发送、接收消息 + +发送消息: + +```bash +sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer +``` + +发送成功后显示:`SendResult [sendStatus=SEND_OK, msgId= ...` + +接收消息: + +```bash +sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer +``` + +接收成功后显示:`ConsumeMessageThread_%d Receive New Messages: [MessageExt...` + +* 关闭 Server + +```bash +sh bin/mqshutdown broker +sh bin/mqshutdown namesrv +``` + +=== Spring Cloud Stream 介绍 + +Spring Cloud Stream 是一个用于构建基于消息的微服务应用框架。它基于 SpringBoot 来创建具有生产级别的单机 Spring 应用,并且使用 `Spring Integration` 与 Broker 进行连接。 + +Spring Cloud Stream 提供了消息中间件配置的统一抽象,推出了 publish-subscribe、consumer groups、partition 这些统一的概念。 + +Spring Cloud Stream 内部有两个概念:Binder 和 Binding。 + +* Binder: 跟外部消息中间件集成的组件,用来创建 Binding,各消息中间件都有自己的 Binder 实现。 + +比如 `Kafka` 的实现 `KafkaMessageChannelBinder`,`RabbitMQ` 的实现 `RabbitMessageChannelBinder` 以及 `RocketMQ` 的实现 `RocketMQMessageChannelBinder`。 + +* Binding: 包括 Input Binding 和 Output Binding。 + +Binding 在消息中间件与应用程序提供的 Provider 和 Consumer 之间提供了一个桥梁,实现了开发者只需使用应用程序的 Provider 或 Consumer 生产或消费数据即可,屏蔽了开发者与底层消息中间件的接触。 + +.Spring Cloud Stream +image::https://docs.spring.io/spring-cloud-stream/docs/current/reference/htmlsingle/images/SCSt-overview.png[] + +使用 Spring Cloud Stream 完成一段简单的消息发送和消息接收代码: + +```java +MessageChannel messageChannel = new DirectChannel(); + +// 消息订阅 +((SubscribableChannel) messageChannel).subscribe(new MessageHandler() { + @Override + public void handleMessage(Message message) throws MessagingException { + System.out.println("receive msg: " + message.getPayload()); + } +}); + +// 消息发送 +messageChannel.send(MessageBuilder.withPayload("simple msg").build()); +``` + +这段代码所有的消息类都是 `spring-messaging` 模块里提供的。屏蔽具体消息中间件的底层实现,如果想用更换消息中间件,在配置文件里配置相关消息中间件信息以及修改 binder 依赖即可。 + +**Spring Cloud Stream 底层基于这段代码去做了各种抽象。** + + +=== 如何使用 Spring Cloud Alibaba RocketMQ Binder ### + +如果要在您的项目中引入 RocketMQ Binder,需要引入如下 maven 依赖: + +```xml + + com.alibaba.cloud + spring-cloud-stream-binder-rocketmq + +``` + +或者可以使用 Spring Cloud Stream RocketMQ Starter: + +```xml + + com.alibaba.cloud + spring-cloud-starter-stream-rocketmq + +``` + +=== Spring Cloud Alibaba RocketMQ Binder 实现 + +这是 Spring Cloud Stream RocketMQ Binder 的实现架构: + +.SCS RocketMQ Binder +image::https://img.alicdn.com/tfs/TB1v8rcbUY1gK0jSZFCXXcwqXXa-1236-773.png[] + +RocketMQ Binder 的重构优化去除了对 https://github.com/apache/rocketmq-spring[RocketMQ-Spring]框架的依赖 。 +RocketMQ Binder 核心类 `RocketMQMessageChannelBinder` 实现了 Spring Cloud Stream 规范,内部会构建 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java[RocketMQInboundChannelAdapter] 和 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java[RocketMQProducerMessageHandler]。 + +`RocketMQProducerMessageHandler` 会基于 Binding 配置通过 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java[RocketMQProduceFactory]构造 RocketMQ Producer,其内部会把 `spring-messaging` 模块内 `org.springframework.messaging.Message` 消息类转换成 RocketMQ 的消息类 `org.apache.rocketmq.common.message.Message`,然后发送出去。 + +`RocketMQInboundChannelAdapter` 也会基于 Binding 配置通过 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java[RocketMQConsumerFactory]构造 DefaultMQPushConsumer,其内部会启动 RocketMQ Consumer 接收消息。 + +NOTE: 与 https://github.com/apache/rocketmq-spring[RocketMQ-Spring] 框架的兼容需要手动处理 + +目前 Binder 支持在 `Header` 中设置相关的 key 来进行 RocketMQ Message 消息的特性设置。 + +比如 `TAGS`、`KEYS`、`TRANSACTIONAL_ARGS` 等 RocketMQ 消息对应的标签,详情见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java[com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst] + +```java +MessageBuilder builder = MessageBuilder.withPayload(msg) + .setHeader(RocketMQHeaders.TAGS, "binder") + .setHeader(RocketMQHeaders.KEYS, "my-key"); +Message message = builder.build(); +output().send(message); +``` +NOTE: 更多使用请参考样例: https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java[com.alibaba.cloud.examples.SenderService] + +=== MessageSource 支持 + +SCS RocketMQ Binder 支持 `MessageSource`,可以进行消息的拉取,例子如下: + +```java +@SpringBootApplication +@EnableBinding(MQApplication.PolledProcessor.class) +public class MQApplication { + + private final Logger logger = + LoggerFactory.getLogger(MQApplication.class); + + public static void main(String[] args) { + SpringApplication.run(MQApplication.class, args); + } + + @Bean + public ApplicationRunner runner(PollableMessageSource source, + MessageChannel dest) { + return args -> { + while (true) { + boolean result = source.poll(m -> { + String payload = (String) m.getPayload(); + logger.info("Received: " + payload); + dest.send(MessageBuilder.withPayload(payload.toUpperCase()) + .copyHeaders(m.getHeaders()) + .build()); + }, new ParameterizedTypeReference() { }); + if (result) { + logger.info("Processed a message"); + } + else { + logger.info("Nothing to do"); + } + Thread.sleep(5_000); + } + }; + } + + public static interface PolledProcessor { + + @Input + PollableMessageSource source(); + + @Output + MessageChannel dest(); + + } + +} +``` + + + +=== 配置选项 + +==== RocketMQ Binder Properties + +spring.cloud.stream.rocketmq.binder.name-server:: +RocketMQ NameServer 地址(老版本使用 namesrv-addr 配置项)。 ++ +Default: `127.0.0.1:9876`. +spring.cloud.stream.rocketmq.binder.access-key:: +阿里云账号 AccessKey。 ++ +Default: null. +spring.cloud.stream.rocketmq.binder.secret-key:: +阿里云账号 SecretKey。 ++ +Default: null. +spring.cloud.stream.rocketmq.binder.enable-msg-trace:: +是否为 Producer 和 Consumer 开启消息轨迹功能 ++ +Default: `true`. +spring.cloud.stream.rocketmq.binder.customized-trace-topic:: +消息轨迹开启后存储的 topic 名称。 ++ +Default: `RMQ_SYS_TRACE_TOPIC`. + + +==== RocketMQ Consumer Properties + +下面的这些配置是以 `spring.cloud.stream.rocketmq.bindings..consumer.` 为前缀的 RocketMQ Consumer 相关的配置。 +更多见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties]。 + +enable:: +是否启用 Consumer。 ++ +默认值: `true`. +subscription:: +Consumer 基于 TAGS 订阅,多个 tag 以 `||` 分割。更多见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties.subscription` ++ +默认值: empty. +messageModel:: +Consumer 消费模式。如果想让每一个的订阅者都能接收到消息,可以使用广播模式。更多见 `org.apache.rocketmq.common.protocol.heartbeat.MessageModel` ++ +默认值: `CLUSTERING`. +consumeFromWhere:: +Consumer 从哪里开始消费。更多见 `org.apache.rocketmq.common.consumer.ConsumeFromWhere` ++ +默认值: `CONSUME_FROM_LAST_OFFSET`. + +#下面的这些配置是 Consumer Push 模式相关的配置。# + `spring.cloud.stream.rocketmq.bindings..consumer.push.` + +orderly:: +是否同步消费消息模式 ++ +默认值: `false`. +delayLevelWhenNextConsume:: +异步消费消息模式下消费失败重试策略: +* -1,不重复,直接放入死信队列 +* 0,broker 控制重试策略 +* >0,client 控制重试策略 ++ +默认值: `0`. +suspendCurrentQueueTimeMillis:: +同步消费消息模式下消费失败后再次消费的时间间隔。 ++ +默认值: `1000`. + +其他更多参数见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties.Push` + +#下面的这些配置是 Consumer Pull 模式相关的配置。# +`spring.cloud.stream.rocketmq.bindings..consumer.pull.` + +pullThreadNums:: +消费时拉取的线程数 ++ +默认值: `20`. +pollTimeoutMillis:: +拉取时的超时毫秒数 ++ +默认值: `1000 * 5`. + +其他更多参数见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties.Pull`. + +NOTE: 更多参数见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties] + +==== RocketMQ Provider Properties + +下面的这些配置是以 `spring.cloud.stream.rocketmq.bindings..producer.` 为前缀的 RocketMQ Producer 相关的配置。更多见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties] + +enable:: +是否启用 Producer。 ++ +默认值: `true`. +group:: +Producer group name。 ++ +默认值: empty. +maxMessageSize:: +消息发送的最大字节数。 ++ +默认值: `8249344`. +producerType:: +消息生产者类型,普通或者事务。更多见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties.ProducerType`. ++ +默认值: `Normal`. +transactionListener:: +事务消息监听器的beanName,在 `producerType=Trans` 时才有效;必须是实现 `org.apache.rocketmq.client.producer.TransactionListener` 接口的Spring Bean。 + +sendType:: +消息发送类型(同步、异步、单向)。更多见`com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties.SendType`. ++ +默认值: `Sync`. +sendCallBack:: +消息发送后回调函数的beanName,在 `sendType=Async` 时才有效;必须是实现 `org.apache.rocketmq.client.producer.SendCallback` 接口的Spring Bean。 +vipChannelEnabled:: +是否在 Vip Channel 上发送消息。 ++ +默认值: `true`. +sendMessageTimeout:: +发送消息的超时时间(毫秒)。 ++ +默认值: `3000`. +compressMessageBodyThreshold:: +消息体压缩阀值(当消息体超过 4k 的时候会被压缩)。 ++ +默认值: `4096`. +retryTimesWhenSendFailed:: +在同步发送消息的模式下,消息发送失败的重试次数。 ++ +默认值: `2`. +retryTimesWhenSendAsyncFailed:: +在异步发送消息的模式下,消息发送失败的重试次数。 ++ +默认值: `2`. +retryAnotherBroker:: +消息发送失败的情况下是否重试其它的 broker。 ++ +默认值: `false`. + +NOTE: 生产者其他更多参数请见: +https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties] + +=== 阿里云 MQ 服务 + +使用阿里云 MQ 服务需要配置 AccessKey、SecretKey 以及云上的 NameServer 地址。 + +NOTE: 0.1.2 & 0.2.2 & 0.9.0 才支持该功能 + +```properties +spring.cloud.stream.rocketmq.binder.access-key=YourAccessKey +spring.cloud.stream.rocketmq.binder.secret-key=YourSecretKey +spring.cloud.stream.rocketmq.binder.name-server=NameServerInMQ +``` + +NOTE: topic 和 group 请以 实例id% 为前缀进行配置。比如 topic 为 "test",需要配置成 "实例id%test" + +.NameServer 的获取(配置中请去掉 http:// 前缀) +image::https://spring-cloud-alibaba.oss-cn-beijing.aliyuncs.com/MQ.png[] diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java index f7db15b57..860c01467 100644 --- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java +++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java @@ -20,7 +20,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import com.alibaba.cloud.examples.RocketMQProduceApplication.MySource; -import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; +import com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst; import org.apache.rocketmq.common.message.MessageConst; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/constant/RocketMQConst.java similarity index 97% rename from spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java rename to spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/constant/RocketMQConst.java index 4f893642e..d0a3b88e0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/constant/RocketMQConst.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.cloud.stream.binder.rocketmq.contants; +package com.alibaba.cloud.stream.binder.rocketmq.constant; import org.apache.rocketmq.common.message.MessageConst; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java index 56c208759..11edb2bf1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java @@ -18,7 +18,7 @@ package com.alibaba.cloud.stream.binder.rocketmq.integration.outbound; import java.util.List; -import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; +import com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst; import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache; import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java index 0509805ea..3615cd4e8 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java @@ -20,8 +20,8 @@ import java.nio.charset.Charset; import java.util.Map; import java.util.Objects; -import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; -import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst.Headers; +import com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst; +import com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst.Headers; import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter; import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache; import org.apache.rocketmq.common.message.MessageConst; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java index 1aed546a0..55e5a5d15 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java @@ -16,7 +16,7 @@ package com.alibaba.cloud.stream.binder.rocketmq.utils; -import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst; +import com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQCommonProperties; import org.apache.rocketmq.acl.common.AclClientRPCHook; From 5d745f81c00ef7054c50696d931a95ba0f179598 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Wed, 18 Aug 2021 10:11:27 +0800 Subject: [PATCH 63/99] document --- .../src/main/asciidoc-zh/rocketmq-new.adoc | 378 ++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc new file mode 100644 index 000000000..a08d5f8ca --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc @@ -0,0 +1,378 @@ +== Spring Cloud Alibaba RocketMQ Binder + +=== RocketMQ 介绍 + +https://rocketmq.apache.org[RocketMQ] 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。 + +具有以下特点: + +* 能够保证严格的消息顺序 + +* 提供丰富的消息拉取模式 + +* 高效的订阅者水平扩展能力 + +* 实时的消息订阅机制 + +* 亿级消息堆积能力 + +=== RocketMQ 基本使用 + +* 下载 RocketMQ + +下载 https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip[RocketMQ最新的二进制文件],并解压 + +解压后的目录结构如下: + +``` +apache-rocketmq +├── LICENSE +├── NOTICE +├── README.md +├── benchmark +├── bin +├── conf +└── lib +``` + +* 启动 NameServer + +```bash +nohup sh bin/mqnamesrv & +tail -f ~/logs/rocketmqlogs/namesrv.log +``` + +* 启动 Broker + +```bash +nohup sh bin/mqbroker -n localhost:9876 & +tail -f ~/logs/rocketmqlogs/broker.log +``` + +* 发送、接收消息 + +发送消息: + +```bash +sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer +``` + +发送成功后显示:`SendResult [sendStatus=SEND_OK, msgId= ...` + +接收消息: + +```bash +sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer +``` + +接收成功后显示:`ConsumeMessageThread_%d Receive New Messages: [MessageExt...` + +* 关闭 Server + +```bash +sh bin/mqshutdown broker +sh bin/mqshutdown namesrv +``` + +=== Spring Cloud Stream 介绍 + +Spring Cloud Stream 是一个用于构建基于消息的微服务应用框架。它基于 SpringBoot 来创建具有生产级别的单机 Spring 应用,并且使用 `Spring Integration` 与 Broker 进行连接。 + +Spring Cloud Stream 提供了消息中间件配置的统一抽象,推出了 publish-subscribe、consumer groups、partition 这些统一的概念。 + +Spring Cloud Stream 内部有两个概念:Binder 和 Binding。 + +* Binder: 跟外部消息中间件集成的组件,用来创建 Binding,各消息中间件都有自己的 Binder 实现。 + +比如 `Kafka` 的实现 `KafkaMessageChannelBinder`,`RabbitMQ` 的实现 `RabbitMessageChannelBinder` 以及 `RocketMQ` 的实现 `RocketMQMessageChannelBinder`。 + +* Binding: 包括 Input Binding 和 Output Binding。 + +Binding 在消息中间件与应用程序提供的 Provider 和 Consumer 之间提供了一个桥梁,实现了开发者只需使用应用程序的 Provider 或 Consumer 生产或消费数据即可,屏蔽了开发者与底层消息中间件的接触。 + +.Spring Cloud Stream +image::https://docs.spring.io/spring-cloud-stream/docs/current/reference/htmlsingle/images/SCSt-overview.png[] + +使用 Spring Cloud Stream 完成一段简单的消息发送和消息接收代码: + +```java +MessageChannel messageChannel = new DirectChannel(); + +// 消息订阅 +((SubscribableChannel) messageChannel).subscribe(new MessageHandler() { + @Override + public void handleMessage(Message message) throws MessagingException { + System.out.println("receive msg: " + message.getPayload()); + } +}); + +// 消息发送 +messageChannel.send(MessageBuilder.withPayload("simple msg").build()); +``` + +这段代码所有的消息类都是 `spring-messaging` 模块里提供的。屏蔽具体消息中间件的底层实现,如果想用更换消息中间件,在配置文件里配置相关消息中间件信息以及修改 binder 依赖即可。 + +**Spring Cloud Stream 底层基于这段代码去做了各种抽象。** + + +=== 如何使用 Spring Cloud Alibaba RocketMQ Binder ### + +如果要在您的项目中引入 RocketMQ Binder,需要引入如下 maven 依赖: + +```xml + + com.alibaba.cloud + spring-cloud-stream-binder-rocketmq + +``` + +或者可以使用 Spring Cloud Stream RocketMQ Starter: + +```xml + + com.alibaba.cloud + spring-cloud-starter-stream-rocketmq + +``` + +=== Spring Cloud Alibaba RocketMQ Binder 实现 + +这是 Spring Cloud Stream RocketMQ Binder 的实现架构: + +.SCS RocketMQ Binder +image::https://img.alicdn.com/tfs/TB1v8rcbUY1gK0jSZFCXXcwqXXa-1236-773.png[] + +RocketMQ Binder 的重构优化去除了对 https://github.com/apache/rocketmq-spring[RocketMQ-Spring]框架的依赖 。 +RocketMQ Binder 核心类 `RocketMQMessageChannelBinder` 实现了 Spring Cloud Stream 规范,内部会构建 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java[RocketMQInboundChannelAdapter] 和 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java[RocketMQProducerMessageHandler]。 + +`RocketMQProducerMessageHandler` 会基于 Binding 配置通过 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java[RocketMQProduceFactory]构造 RocketMQ Producer,其内部会把 `spring-messaging` 模块内 `org.springframework.messaging.Message` 消息类转换成 RocketMQ 的消息类 `org.apache.rocketmq.common.message.Message`,然后发送出去。 + +`RocketMQInboundChannelAdapter` 也会基于 Binding 配置通过 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java[RocketMQConsumerFactory]构造 DefaultMQPushConsumer,其内部会启动 RocketMQ Consumer 接收消息。 + +NOTE: 与 https://github.com/apache/rocketmq-spring[RocketMQ-Spring] 框架的兼容需要手动处理 + +目前 Binder 支持在 `Header` 中设置相关的 key 来进行 RocketMQ Message 消息的特性设置。 + +比如 `TAGS`、`KEYS`、`TRANSACTIONAL_ARGS` 等 RocketMQ 消息对应的标签,详情见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java[com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst] + +```java +MessageBuilder builder = MessageBuilder.withPayload(msg) + .setHeader(RocketMQHeaders.TAGS, "binder") + .setHeader(RocketMQHeaders.KEYS, "my-key"); +Message message = builder.build(); +output().send(message); +``` +NOTE: 更多使用请参考样例: https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java[com.alibaba.cloud.examples.SenderService] + +=== MessageSource 支持 + +SCS RocketMQ Binder 支持 `MessageSource`,可以进行消息的拉取,例子如下: + +```java +@SpringBootApplication +@EnableBinding(MQApplication.PolledProcessor.class) +public class MQApplication { + + private final Logger logger = + LoggerFactory.getLogger(MQApplication.class); + + public static void main(String[] args) { + SpringApplication.run(MQApplication.class, args); + } + + @Bean + public ApplicationRunner runner(PollableMessageSource source, + MessageChannel dest) { + return args -> { + while (true) { + boolean result = source.poll(m -> { + String payload = (String) m.getPayload(); + logger.info("Received: " + payload); + dest.send(MessageBuilder.withPayload(payload.toUpperCase()) + .copyHeaders(m.getHeaders()) + .build()); + }, new ParameterizedTypeReference() { }); + if (result) { + logger.info("Processed a message"); + } + else { + logger.info("Nothing to do"); + } + Thread.sleep(5_000); + } + }; + } + + public static interface PolledProcessor { + + @Input + PollableMessageSource source(); + + @Output + MessageChannel dest(); + + } + +} +``` + + + +=== 配置选项 + +==== RocketMQ Binder Properties + +spring.cloud.stream.rocketmq.binder.name-server:: +RocketMQ NameServer 地址(老版本使用 namesrv-addr 配置项)。 ++ +Default: `127.0.0.1:9876`. +spring.cloud.stream.rocketmq.binder.access-key:: +阿里云账号 AccessKey。 ++ +Default: null. +spring.cloud.stream.rocketmq.binder.secret-key:: +阿里云账号 SecretKey。 ++ +Default: null. +spring.cloud.stream.rocketmq.binder.enable-msg-trace:: +是否为 Producer 和 Consumer 开启消息轨迹功能 ++ +Default: `true`. +spring.cloud.stream.rocketmq.binder.customized-trace-topic:: +消息轨迹开启后存储的 topic 名称。 ++ +Default: `RMQ_SYS_TRACE_TOPIC`. + + +==== RocketMQ Consumer Properties + +下面的这些配置是以 `spring.cloud.stream.rocketmq.bindings..consumer.` 为前缀的 RocketMQ Consumer 相关的配置。 +更多见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties]。 + +enable:: +是否启用 Consumer。 ++ +默认值: `true`. +subscription:: +Consumer 基于 TAGS 订阅,多个 tag 以 `||` 分割。更多见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties.subscription` ++ +默认值: empty. +messageModel:: +Consumer 消费模式。如果想让每一个的订阅者都能接收到消息,可以使用广播模式。更多见 `org.apache.rocketmq.common.protocol.heartbeat.MessageModel` ++ +默认值: `CLUSTERING`. +consumeFromWhere:: +Consumer 从哪里开始消费。更多见 `org.apache.rocketmq.common.consumer.ConsumeFromWhere` ++ +默认值: `CONSUME_FROM_LAST_OFFSET`. + +#下面的这些配置是 Consumer Push 模式相关的配置。# + `spring.cloud.stream.rocketmq.bindings..consumer.push.` + +orderly:: +是否同步消费消息模式 ++ +默认值: `false`. +delayLevelWhenNextConsume:: +异步消费消息模式下消费失败重试策略: +* -1,不重复,直接放入死信队列 +* 0,broker 控制重试策略 +* >0,client 控制重试策略 ++ +默认值: `0`. +suspendCurrentQueueTimeMillis:: +同步消费消息模式下消费失败后再次消费的时间间隔。 ++ +默认值: `1000`. + +其他更多参数见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties.Push` + +#下面的这些配置是 Consumer Pull 模式相关的配置。# +`spring.cloud.stream.rocketmq.bindings..consumer.pull.` + +pullThreadNums:: +消费时拉取的线程数 ++ +默认值: `20`. +pollTimeoutMillis:: +拉取时的超时毫秒数 ++ +默认值: `1000 * 5`. + +其他更多参数见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties.Pull`. + +NOTE: 更多参数见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties] + +==== RocketMQ Provider Properties + +下面的这些配置是以 `spring.cloud.stream.rocketmq.bindings..producer.` 为前缀的 RocketMQ Producer 相关的配置。更多见 https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties] + +enable:: +是否启用 Producer。 ++ +默认值: `true`. +group:: +Producer group name。 ++ +默认值: empty. +maxMessageSize:: +消息发送的最大字节数。 ++ +默认值: `8249344`. +producerType:: +消息生产者类型,普通或者事务。更多见 `com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties.ProducerType`. ++ +默认值: `Normal`. +transactionListener:: +事务消息监听器的beanName,在 `producerType=Trans` 时才有效;必须是实现 `org.apache.rocketmq.client.producer.TransactionListener` 接口的Spring Bean。 + +sendType:: +消息发送类型(同步、异步、单向)。更多见`com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties.SendType`. ++ +默认值: `Sync`. +sendCallBack:: +消息发送后回调函数的beanName,在 `sendType=Async` 时才有效;必须是实现 `org.apache.rocketmq.client.producer.SendCallback` 接口的Spring Bean。 +vipChannelEnabled:: +是否在 Vip Channel 上发送消息。 ++ +默认值: `true`. +sendMessageTimeout:: +发送消息的超时时间(毫秒)。 ++ +默认值: `3000`. +compressMessageBodyThreshold:: +消息体压缩阀值(当消息体超过 4k 的时候会被压缩)。 ++ +默认值: `4096`. +retryTimesWhenSendFailed:: +在同步发送消息的模式下,消息发送失败的重试次数。 ++ +默认值: `2`. +retryTimesWhenSendAsyncFailed:: +在异步发送消息的模式下,消息发送失败的重试次数。 ++ +默认值: `2`. +retryAnotherBroker:: +消息发送失败的情况下是否重试其它的 broker。 ++ +默认值: `false`. + +NOTE: 生产者其他更多参数请见: +https://github.com/alibaba/spring-cloud-alibaba/blob/rocketmq/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java[com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties] + +=== 阿里云 MQ 服务 + +使用阿里云 MQ 服务需要配置 AccessKey、SecretKey 以及云上的 NameServer 地址。 + +NOTE: 0.1.2 & 0.2.2 & 0.9.0 才支持该功能 + +```properties +spring.cloud.stream.rocketmq.binder.access-key=YourAccessKey +spring.cloud.stream.rocketmq.binder.secret-key=YourSecretKey +spring.cloud.stream.rocketmq.binder.name-server=NameServerInMQ +``` + +NOTE: topic 和 group 请以 实例id% 为前缀进行配置。比如 topic 为 "test",需要配置成 "实例id%test" + +.NameServer 的获取(配置中请去掉 http:// 前缀) +image::https://spring-cloud-alibaba.oss-cn-beijing.aliyuncs.com/MQ.png[] From c6147dc6180deb23a75859096c31cac73bdb2342 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Wed, 18 Aug 2021 10:27:44 +0800 Subject: [PATCH 64/99] document --- .../src/main/asciidoc-zh/rocketmq-new.adoc | 4 ++-- .../src/main/asciidoc-zh/spring-cloud-alibaba.adoc | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc index a08d5f8ca..80b6a280b 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/rocketmq-new.adoc @@ -1,4 +1,4 @@ -== Spring Cloud Alibaba RocketMQ Binder +== Spring Cloud Alibaba RocketMQ Binder (NEW) === RocketMQ 介绍 @@ -115,7 +115,7 @@ messageChannel.send(MessageBuilder.withPayload("simple msg").build()); **Spring Cloud Stream 底层基于这段代码去做了各种抽象。** -=== 如何使用 Spring Cloud Alibaba RocketMQ Binder ### +=== 如何使用 Spring Cloud Alibaba RocketMQ Binder 如果要在您的项目中引入 RocketMQ Binder,需要引入如下 maven 依赖: diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc index 13e0e76ee..80f858ea0 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/spring-cloud-alibaba.adoc @@ -19,6 +19,8 @@ include::sentinel.adoc[] include::dubbo.adoc[] +include::rocketmq-new.adoc[] + include::rocketmq.adoc[] include::ans.adoc[] From b35e7d78773526bc32dfc011924a1b65a10d8692 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 23 Aug 2021 11:41:11 +0800 Subject: [PATCH 65/99] fixed Instrumentation --- .../inbound/RocketMQInboundChannelAdapter.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java index 61c0eedd3..d27836b98 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java @@ -78,7 +78,6 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport || !extendedConsumerProperties.getExtension().getEnabled()) { return; } - Instrumentation instrumentation = new Instrumentation(topic, this); try { super.onInit(); if (this.retryTemplate != null) { @@ -130,18 +129,13 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport return ConsumeConcurrentlyStatus.RECONSUME_LATER; }, () -> ConsumeConcurrentlyStatus.CONSUME_SUCCESS)); } - instrumentation.markStartedSuccessfully(); } catch (Exception e) { - instrumentation.markStartFailed(e); log.error("DefaultMQPushConsumer init failed, Caused by " + e.getMessage()); throw new MessagingException(MessageBuilder.withPayload( "DefaultMQPushConsumer init failed, Caused by " + e.getMessage()) .build(), e); } - finally { - InstrumentationManager.addHealthInstrumentation(instrumentation); - } } /** @@ -188,16 +182,21 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport || !extendedConsumerProperties.getExtension().getEnabled()) { return; } + Instrumentation instrumentation = new Instrumentation(topic, this); try { pushConsumer.subscribe(topic, RocketMQUtils.getMessageSelector( extendedConsumerProperties.getExtension().getSubscription())); pushConsumer.start(); + instrumentation.markStartedSuccessfully(); } catch (Exception e) { + instrumentation.markStartFailed(e); log.error("DefaultMQPushConsumer init failed, Caused by " + e.getMessage()); throw new MessagingException(MessageBuilder.withPayload( "DefaultMQPushConsumer init failed, Caused by " + e.getMessage()) .build(), e); + }finally { + InstrumentationManager.addHealthInstrumentation(instrumentation); } } From 745d1738983d840e42f51fe1e5e696686b104760 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Thu, 26 Aug 2021 15:20:04 +0800 Subject: [PATCH 66/99] message converter --- .../ExtendedBindingHandlerMappingsProviderConfiguration.java | 3 +++ .../binder/rocketmq/convert/RocketMQMessageConverter.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java index ce48fccb0..df5d47b6b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java @@ -53,6 +53,9 @@ public class ExtendedBindingHandlerMappingsProviderConfiguration { } + /** + * if you want to customize a bean, please use this BeanName {@code RocketMQMessageConverter.DEFAULT_NAME}. + */ @Bean(RocketMQMessageConverter.DEFAULT_NAME) @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME }) public CompositeMessageConverter rocketMQMessageConverter() { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java index 98bd03263..f69290997 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java @@ -34,9 +34,9 @@ import org.springframework.util.ClassUtils; public class RocketMQMessageConverter { /** - * rocketMQMessageConverter. + * if you want to customize a bean, please use the BeanName. */ - public static final String DEFAULT_NAME = "rocketMQMessageConverter"; + public static final String DEFAULT_NAME = "com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter"; private static final boolean JACKSON_PRESENT; From 74462793e6ef6f4d38a50c990609d9fdc3393dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E9=BB=84=E5=BD=AC?= Date: Thu, 26 Aug 2021 16:39:37 +0800 Subject: [PATCH 67/99] Update nacos-config.adoc --- .../src/main/asciidoc-zh/nacos-config.adoc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc index 2bbfa7a63..96ef58716 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc @@ -348,13 +348,7 @@ Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置 * B: 通过 `spring.cloud.nacos.config.ext-config[n].data-id` 的方式支持多个扩展 Data Id 的配置 * C: 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置 -当三种方式共同使用时,他们的一个优先级关系是: - -->A为优先级最高的 - -->B的优先级低于A, - -->C的优先级是最低的 +当三种方式共同使用时,他们的一个优先级关系是: A < B < C === Nacos Config 对外暴露的 Endpoint From a7e3b39826bdf7882213bb6a4926bd083fcb9632 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Tue, 7 Sep 2021 11:32:08 +0800 Subject: [PATCH 68/99] upgrade Nacos client version to 2.0.3 --- pom.xml | 2 +- spring-cloud-alibaba-dependencies/pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 0208a34b4..70017da3f 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ - 2.2.6-SNAPSHOT + 2.2.7-SNAPSHOT Hoxton.SR9 diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 1adf679d2..e56436134 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -18,10 +18,10 @@ Spring Cloud Alibaba Dependencies - 2.2.6-SNAPSHOT + 2.2.7-SNAPSHOT 1.8.1 1.3.0 - 1.4.2 + 2.0.3 0.8.0 1.0.10 From 2fb1d064446ff05420b459645fab70459a1d2996 Mon Sep 17 00:00:00 2001 From: yuhuangbin Date: Tue, 7 Sep 2021 11:32:55 +0800 Subject: [PATCH 69/99] upgrade Nacos client version to 2.0.3 --- .../nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java index 3692414f4..af9110d33 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java @@ -40,7 +40,8 @@ import org.springframework.test.context.junit4.SpringRunner; */ @RunWith(SpringRunner.class) @SpringBootTest(classes = NacosRibbonClientPropertyOverrideTests.TestConfiguration.class, - properties = { "spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848", + properties = { "spring.cloud.nacos.server-addr=127.0.0.1:8848", + "spring.cloud.nacos.username=nacos", "spring.cloud.nacos.password=nacos", "spring.cloud.nacos.discovery.port=18080", "spring.cloud.nacos.discovery.service=remoteApp", "localApp.ribbon.NIWSServerListClassName=" From 23e9a52fc84e34c7bc151f57234e2811dbe73613 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 20:25:43 +0000 Subject: [PATCH 70/99] Bump dubbo from 2.7.8 to 2.7.13 Bumps [dubbo](https://github.com/apache/dubbo) from 2.7.8 to 2.7.13. - [Release notes](https://github.com/apache/dubbo/releases) - [Changelog](https://github.com/apache/dubbo/blob/3.0/CHANGES.md) - [Commits](https://github.com/apache/dubbo/compare/dubbo-2.7.8...dubbo-2.7.13) --- updated-dependencies: - dependency-name: org.apache.dubbo:dubbo dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 70017da3f..74bef2ee2 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ Hoxton.SR9 - 2.7.8 + 2.7.13 4.0.1 From 03e16756cde7146faf1f3d219b06c8ce339aa7be Mon Sep 17 00:00:00 2001 From: Alex Lu <459360594@qq.com> Date: Sun, 12 Sep 2021 09:54:19 +0800 Subject: [PATCH 71/99] Fixes #2253: ThreadPoolTaskScheduler instance in NacosWatch can't be shutdown. --- .../com/alibaba/cloud/nacos/discovery/NacosWatch.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 22a7f6766..181c6b455 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 @@ -35,6 +35,7 @@ import com.alibaba.nacos.api.naming.pojo.Instance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.context.ApplicationEventPublisher; @@ -45,8 +46,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; /** * @author xiaojing * @author yuhuangbin + * @author pengfei.lu */ -public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle { +public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle, DisposableBean { private static final Logger log = LoggerFactory.getLogger(NacosWatch.class); @@ -199,4 +201,8 @@ public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycl } + @Override + public void destroy() { + this.stop(); + } } From bbf4977e7e17fa64b2d7ee619d8714ac1f4e3c4d Mon Sep 17 00:00:00 2001 From: panzhi33 Date: Mon, 13 Sep 2021 18:34:59 +0800 Subject: [PATCH 72/99] [rocketmq]fix variable judgment bug --- .../config/RocketMQComponent4BinderAutoConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java index 5b1fb513a..f34aa6b44 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java @@ -74,7 +74,7 @@ public class RocketMQComponent4BinderAutoConfiguration { configNameServer = RocketMQBinderConstants.DEFAULT_NAME_SERVER; } producer.setNamesrvAddr(configNameServer); - if (!StringUtils.isEmpty(configNameServer)) { + if (!StringUtils.isEmpty(accessChannel)) { producer.setAccessChannel(AccessChannel.valueOf(accessChannel)); } return producer; From b34adc077bf8b67bbd732cb74f32773107f986ef Mon Sep 17 00:00:00 2001 From: Alex Lu <459360594@qq.com> Date: Sun, 12 Sep 2021 10:32:17 +0800 Subject: [PATCH 73/99] Optimize README format. --- README-zh.md | 26 +++++++++++++------------- README.md | 24 ++++++++++++------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README-zh.md b/README-zh.md index 373608c4b..b1b3243d0 100644 --- a/README-zh.md +++ b/README-zh.md @@ -15,7 +15,7 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 ## 主要功能 -* **服务限流降级**:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。 +* **服务限流降级**:默认支持 WebServlet、WebFlux、OpenFeign、RestTemplate、Spring Cloud Gateway、Zuul、Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。 * **服务注册与发现**:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。 * **分布式配置管理**:支持分布式系统中的外部化配置,配置更改时自动刷新。 * **消息驱动能力**:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。 @@ -56,7 +56,7 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone 到本地,然后执行以下命令: ```bash - ./mvnw install +./mvnw install ``` 执行完毕后,项目将被安装到本地 Maven 仓库。 @@ -66,17 +66,17 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone 如果需要使用已发布的版本,在 `dependencyManagement` 中添加如下配置。 ```xml - - - - com.alibaba.cloud - spring-cloud-alibaba-dependencies - 2.2.5.RELEASE - pom - import - - - + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + 2.2.6.RELEASE + pom + import + + + ``` 然后在 `dependencies` 中添加自己所需使用的依赖即可使用。 diff --git a/README.md b/README.md index 559683cfe..5a5710833 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ For more features please refer to [Roadmap](https://github.com/alibaba/spring-cl Spring Cloud uses Maven for most build-related activities, and you should be able to get off the ground quite quickly by cloning the project you are interested in and typing: ```bash - ./mvnw install +./mvnw install ``` ## How to Use @@ -68,17 +68,17 @@ Spring Cloud uses Maven for most build-related activities, and you should be abl These artifacts are available from Maven Central and Spring Release repository via BOM: ```xml - - - - com.alibaba.cloud - spring-cloud-alibaba-dependencies - 2.2.5.RELEASE - pom - import - - - + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + 2.2.6.RELEASE + pom + import + + + ``` add the module in `dependencies`. From 9cba216bfaad73453eac91c1269211e1a5a5814a Mon Sep 17 00:00:00 2001 From: zkzlx Date: Wed, 29 Sep 2021 16:57:13 +0800 Subject: [PATCH 74/99] Optimize the consumption of Pull --- .../inbound/RocketMQConsumerFactory.java | 7 +-- .../inbound/pull/RocketMQAckCallback.java | 23 +-------- .../inbound/pull/RocketMQMessageSource.java | 51 ++++++++----------- 3 files changed, 27 insertions(+), 54 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java index 2aeb1a19f..ead3cdfe1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java @@ -108,8 +108,7 @@ public final class RocketMQConsumerFactory { "Property 'nameServer' is required"); AllocateMessageQueueStrategy allocateMessageQueueStrategy = RocketMQBeanContainerCache .getBean(consumerProperties.getAllocateMessageQueueStrategy(), - AllocateMessageQueueStrategy.class, - new AllocateMessageQueueAveragely()); + AllocateMessageQueueStrategy.class); RPCHook rpcHook = null; if (!StringUtils.isEmpty(consumerProperties.getAccessKey()) @@ -126,7 +125,9 @@ public final class RocketMQConsumerFactory { null == rpcHook && consumerProperties.getVipChannelEnabled()); consumer.setInstanceName( RocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup())); - consumer.setAllocateMessageQueueStrategy(allocateMessageQueueStrategy); + if(null != allocateMessageQueueStrategy) { + consumer.setAllocateMessageQueueStrategy(allocateMessageQueueStrategy); + } consumer.setNamesrvAddr(consumerProperties.getNameServer()); consumer.setMessageModel(getMessageModel(consumerProperties.getMessageModel())); consumer.setUseTLS(consumerProperties.getUseTLS()); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java index 56e50ca4a..216bb05f0 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java @@ -18,11 +18,8 @@ package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull; import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.impl.consumer.AssignedMessageQueue; -import org.apache.rocketmq.client.impl.consumer.ProcessQueue; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageQueue; -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,18 +41,14 @@ public class RocketMQAckCallback implements AcknowledgmentCallback { private MessageExt messageExt; - private AssignedMessageQueue assignedMessageQueue; - private DefaultLitePullConsumer consumer; private final MessageQueue messageQueue; public RocketMQAckCallback(DefaultLitePullConsumer consumer, - AssignedMessageQueue assignedMessageQueue, MessageQueue messageQueue, - MessageExt messageExt) { + MessageQueue messageQueue,MessageExt messageExt) { this.messageExt = messageExt; this.consumer = consumer; - this.assignedMessageQueue = assignedMessageQueue; this.messageQueue = messageQueue; } @@ -86,19 +79,7 @@ public class RocketMQAckCallback implements AcknowledgmentCallback { switch (status) { case REJECT: case ACCEPT: - long consumerOffset = assignedMessageQueue - .getConsumerOffset(messageQueue); - if (consumerOffset != -1) { - ProcessQueue processQueue = assignedMessageQueue - .getProcessQueue(messageQueue); - if (processQueue != null && !processQueue.isDropped()) { - consumer.getOffsetStore().updateOffset(messageQueue, - consumerOffset, false); - } - } - if (consumer.getMessageModel() == MessageModel.BROADCASTING) { - consumer.getOffsetStore().persist(messageQueue); - } + consumer.committed(messageQueue); break; case REQUEUE: consumer.seek(messageQueue, offset); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java index a7d7e73da..7f348f79e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java @@ -16,9 +16,11 @@ package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull; -import java.lang.reflect.Field; +import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQConsumerFactory; import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; @@ -29,8 +31,6 @@ import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils; import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; import org.apache.rocketmq.client.consumer.MessageSelector; import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.impl.consumer.AssignedMessageQueue; -import org.apache.rocketmq.client.impl.consumer.DefaultLitePullConsumerImpl; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageQueue; import org.slf4j.Logger; @@ -44,7 +44,6 @@ import org.springframework.integration.endpoint.AbstractMessageSource; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.util.CollectionUtils; -import org.springframework.util.ReflectionUtils; /** * @author Jim @@ -57,7 +56,7 @@ public class RocketMQMessageSource extends AbstractMessageSource private DefaultLitePullConsumer consumer; - private AssignedMessageQueue assignedMessageQueue; + private final Map> messageQueuesForTopic = new ConcurrentHashMap<>(); private volatile boolean running; @@ -92,8 +91,11 @@ public class RocketMQMessageSource extends AbstractMessageSource // this.consumer.setPullBatchSize(1); this.consumer.subscribe(topic, messageSelector); this.consumer.setAutoCommit(false); - this.assignedMessageQueue = acquireAssignedMessageQueue(this.consumer); + //register TopicMessageQueueChangeListener for messageQueuesForTopic + consumer.registerTopicMessageQueueChangeListener(topic, messageQueuesForTopic::put); this.consumer.start(); + //Initialize messageQueuesForTopic immediately + messageQueuesForTopic.put(topic,consumer.fetchMessageQueues(topic)); instrumentation.markStartedSuccessfully(); } catch (MQClientException e) { @@ -106,21 +108,17 @@ public class RocketMQMessageSource extends AbstractMessageSource this.running = true; } - private AssignedMessageQueue acquireAssignedMessageQueue( - DefaultLitePullConsumer consumer) { - Field field = ReflectionUtils.findField(DefaultLitePullConsumer.class, - "defaultLitePullConsumerImpl"); - assert field != null; - field.setAccessible(true); - DefaultLitePullConsumerImpl defaultLitePullConsumerImpl = (DefaultLitePullConsumerImpl) ReflectionUtils - .getField(field, consumer); - - field = ReflectionUtils.findField(DefaultLitePullConsumerImpl.class, - "assignedMessageQueue"); - assert field != null; - field.setAccessible(true); - return (AssignedMessageQueue) ReflectionUtils.getField(field, - defaultLitePullConsumerImpl); + private MessageQueue acquireCurrentMessageQueue(String topic,int queueId) { + Collection messageQueueSet = messageQueuesForTopic.get(topic); + if(CollectionUtils.isEmpty(messageQueueSet)){ + return null; + } + for (MessageQueue messageQueue : messageQueueSet) { + if (messageQueue.getQueueId() == queueId) { + return messageQueue; + } + } + return null; } @Override @@ -153,13 +151,7 @@ public class RocketMQMessageSource extends AbstractMessageSource if (null == messageExt) { return null; } - MessageQueue messageQueue = null; - for (MessageQueue queue : assignedMessageQueue.getAssignedMessageQueues()) { - if (queue.getQueueId() == messageExt.getQueueId()) { - messageQueue = queue; - break; - } - } + MessageQueue messageQueue = this.acquireCurrentMessageQueue(messageExt.getTopic(),messageExt.getQueueId()); if (messageQueue == null) { throw new IllegalArgumentException( "The message queue is not in assigned list"); @@ -168,8 +160,7 @@ public class RocketMQMessageSource extends AbstractMessageSource .convertMessage2Spring(messageExt); return MessageBuilder.fromMessage(message) .setHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK, - new RocketMQAckCallback(this.consumer, assignedMessageQueue, - messageQueue, messageExt)) + new RocketMQAckCallback(this.consumer,messageQueue, messageExt)) .build(); } From 3e8380740c24740836ff44741978f2a71af3eef8 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Wed, 29 Sep 2021 17:53:10 +0800 Subject: [PATCH 75/99] Optimize the code of producer --- .../inbound/pull/RocketMQMessageSource.java | 2 +- .../outbound/RocketMQProducerMessageHandler.java | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java index 7f348f79e..6d5583518 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java @@ -139,7 +139,7 @@ public class RocketMQMessageSource extends AbstractMessageSource protected synchronized Object doReceive() { if (messageExtIterator == null) { List messageExtList = consumer.poll(); - if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) { + if (CollectionUtils.isEmpty(messageExtList)) { return null; } messageExtIterator = messageExtList.iterator(); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java index 11edb2bf1..df9bedebc 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java @@ -169,18 +169,23 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler } ((TransactionMQProducer) defaultMQProducer) .setTransactionListener(transactionListener); - log.info("send transaction message :" + mqMessage); + if(log.isDebugEnabled()){ + log.debug("send transaction message ->{}" , mqMessage); + } sendResult = defaultMQProducer.sendMessageInTransaction(mqMessage, message.getHeaders().get(RocketMQConst.USER_TRANSACTIONAL_ARGS)); } else { - log.info("send message :" + mqMessage); + if(log.isDebugEnabled()){ + log.debug("send message ->{}" , mqMessage); + } sendResult = this.send(mqMessage, this.messageQueueSelector, message.getHeaders(), message); } + log.info("the message has sent,message={},sendResult={}",mqMessage,sendResult); if (sendResult == null || !SendStatus.SEND_OK.equals(sendResult.getSendStatus())) { - log.error("message send fail.SendStatus is not OK "); + log.error("message send fail.SendStatus is not OK.the message={}",mqMessage); this.doFail(message, new MessagingException( "message send fail.SendStatus is not OK.")); } From 228013d6cb2f51656c9158fa0b014b9c8308c0d0 Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Sat, 16 Oct 2021 19:50:48 +0800 Subject: [PATCH 76/99] Polish README.md format --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5a5710833..6244ebb06 100644 --- a/README.md +++ b/README.md @@ -16,14 +16,14 @@ With Spring Cloud Alibaba, you only need to add some annotations and a small amo ## Features -* **Flow control and service degradation**:Flow control for HTTP services is supported by default. You can also customize flow control and service degradation rules using annotations. The rules can be changed dynamically. -* **Service registration and discovery**:Service can be registered and clients can discover the instances using Spring-managed beans, auto integration Ribbon. -* **Distributed configuration**:support for externalized configuration in a distributed system, auto refresh when configuration changes. -* **Event-driven**:support for building highly scalable event-driven microservices connected with shared messaging systems. -* **Distributed Transaction**:support for distributed transaction solution with high performance and ease of use. -* **Alibaba Cloud Object Storage**:massive, secure, low-cost, and highly reliable cloud storage services. Support for storing and accessing any type of data in any application, anytime, anywhere. -* **Alibaba Cloud SchedulerX**:accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds. -* **Alibaba Cloud SMS**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers. +* **Flow control and service degradation**: Flow control for HTTP services is supported by default. You can also customize flow control and service degradation rules using annotations. The rules can be changed dynamically. +* **Service registration and discovery**: Service can be registered and clients can discover the instances using Spring-managed beans, auto integration Ribbon. +* **Distributed configuration**: Support for externalized configuration in a distributed system, auto refresh when configuration changes. +* **Event-driven**: Support for building highly scalable event-driven microservices connected with shared messaging systems. +* **Distributed Transaction**: Support for distributed transaction solution with high performance and ease of use. +* **Alibaba Cloud Object Storage**: Massive, secure, low-cost, and highly reliable cloud storage services. Support for storing and accessing any type of data in any application, anytime, anywhere. +* **Alibaba Cloud SchedulerX**: Accurate, highly reliable, and highly available scheduled job scheduling services with response time within seconds. +* **Alibaba Cloud SMS**: A messaging service that covers the globe, Alibaba SMS provides convenient, efficient, and intelligent communication capabilities that help businesses quickly contact their customers. For more features, please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md). @@ -34,19 +34,19 @@ For more features, please refer to [Roadmap](https://github.com/alibaba/spring-c **[Nacos](https://github.com/alibaba/Nacos)**: An easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications. -**[RocketMQ](https://rocketmq.apache.org/)**:A distributed messaging and streaming platform with low latency, high performance and reliability, trillion-level capacity and flexible scalability. +**[RocketMQ](https://rocketmq.apache.org/)**: A distributed messaging and streaming platform with low latency, high performance and reliability, trillion-level capacity and flexible scalability. -**[Dubbo](https://github.com/apache/dubbo)**:A high-performance, Java based open source RPC framework. +**[Dubbo](https://github.com/apache/dubbo)**: A high-performance, Java based open source RPC framework. -**[Seata](https://github.com/seata/seata)**:A distributed transaction solution with high performance and ease of use for microservices architecture. +**[Seata](https://github.com/seata/seata)**: A distributed transaction solution with high performance and ease of use for microservices architecture. -**[Alibaba Cloud ACM](https://www.aliyun.com/product/acm)**:An application configuration center that enables you to centralize the management of application configurations, and accomplish real-time configuration push in a distributed environment. +**[Alibaba Cloud ACM](https://www.aliyun.com/product/acm)**: An application configuration center that enables you to centralize the management of application configurations, and accomplish real-time configuration push in a distributed environment. **[Alibaba Cloud OSS](https://www.aliyun.com/product/oss)**: An encrypted and secure cloud storage service which stores, processes and accesses massive amounts of data from anywhere in the world. **[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/aliware/schedulerx?spm=5176.10695662.784137.1.4b07363dej23L3)**: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). @@ -137,7 +137,7 @@ Add yourself as an @author to the .java files that you modify substantially (mor Add some Javadocs and, if you change the namespace, some XSD doc elements. -A few unit tests would help a lot as well — someone has to do it. +A few unit tests would help a lot as well —— someone has to do it. If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project). @@ -146,4 +146,4 @@ When writing a commit message please follow these conventions, if you are fixing ## Contact Us Mailing list is recommended for discussing almost anything related to spring-cloud-alibaba. -spring-cloud-alibaba@googlegroups.com:You can ask questions here if you encounter any problem when using or developing spring-cloud-alibaba. +spring-cloud-alibaba@googlegroups.com: You can ask questions here if you encounter any problem when using or developing spring-cloud-alibaba. From d57e28a1235e3b82a2b250c3406b3411f61f7c5f Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Tue, 19 Oct 2021 19:08:43 +0800 Subject: [PATCH 77/99] Add dingtalk group numbers --- README-zh.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README-zh.md b/README-zh.md index b1b3243d0..8d15ccb56 100644 --- a/README-zh.md +++ b/README-zh.md @@ -122,9 +122,11 @@ spring-cloud-alibaba@googlegroups.com,欢迎通过此邮件列表讨论与 spr ### 钉钉群 -![DingQR](https://img.alicdn.com/tfs/TB1jXikzAL0gK0jSZFtXXXQCXXa-1002-323.png) - -如图片有问题,访问 https://img.alicdn.com/tfs/TB1jXikzAL0gK0jSZFtXXXQCXXa-1002-323.png +* Spring Cloud Alibaba 开源交流群(1群):21914947 +* Spring Cloud Alibaba 开源交流群(2群,已满):21992595 +* Spring Cloud Alibaba 开源交流群(3群):35153903 +* Spring Cloud Alibaba 开源交流群(4群,已满):30301472 +* Spring Cloud Alibaba 开源交流群(5群):34930571 ## 社区相关开源 From 3f6e86eba76cab7d4524504dfc9e6403e9552951 Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Tue, 19 Oct 2021 20:39:32 +0800 Subject: [PATCH 78/99] Add README.md content --- README-zh.md | 2 ++ README.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/README-zh.md b/README-zh.md index 8d15ccb56..ee2b8b827 100644 --- a/README-zh.md +++ b/README-zh.md @@ -27,6 +27,8 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 更多功能请参考 [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap-zh.md)。 +除了上述所具有的功能外,针对企业级用户特殊微服务治理场景述求,Spring Cloud Alibaba 配套的企业版微服务治理方案 [微服务引擎MSE](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) 还提供了如全链路灰度、服务预热、无损上下线和离群实例摘除等更多更强大的治理能力。 + ## 组件 **[Sentinel](https://github.com/alibaba/Sentinel)**:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 diff --git a/README.md b/README.md index 6244ebb06..e9a004334 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ With Spring Cloud Alibaba, you only need to add some annotations and a small amo For more features, please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md). +In addition to the above-mentioned features, For the needs of enterprise users' special microservices governance scenarios, [Microservices Engine (MSE)](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) of Spring Cloud Alibaba's enterprise version provides more powerful governance capabilities such as Grayscale Release, Service Warm-up, Lossless Online and Offline and Outlier Ejection. + ## Components From 74f62dd701ab85996c2f8d527ceaa8c31a9ac453 Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Wed, 20 Oct 2021 09:31:22 +0800 Subject: [PATCH 79/99] Modified README.md content --- README-zh.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README-zh.md b/README-zh.md index ee2b8b827..12fd01347 100644 --- a/README-zh.md +++ b/README-zh.md @@ -27,7 +27,7 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 更多功能请参考 [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap-zh.md)。 -除了上述所具有的功能外,针对企业级用户特殊微服务治理场景述求,Spring Cloud Alibaba 配套的企业版微服务治理方案 [微服务引擎MSE](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) 还提供了如全链路灰度、服务预热、无损上下线和离群实例摘除等更多更强大的治理能力。 +除了上述所具有的功能外,针对企业级用户的场景,Spring Cloud Alibaba 配套的企业版微服务治理方案 [微服务引擎MSE](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) 还提供了企业级微服务治理中心,包括全链路灰度、服务预热、无损上下线和离群实例摘除等更多更强大的治理能力,同时还提供了企业级 Nacos 注册配置中心,企业级云原生网关等多种产品及解决方案。 ## 组件 diff --git a/README.md b/README.md index e9a004334..58e7e5a7e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ With Spring Cloud Alibaba, you only need to add some annotations and a small amo For more features, please refer to [Roadmap](https://github.com/alibaba/spring-cloud-alibaba/blob/master/Roadmap.md). -In addition to the above-mentioned features, For the needs of enterprise users' special microservices governance scenarios, [Microservices Engine (MSE)](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) of Spring Cloud Alibaba's enterprise version provides more powerful governance capabilities such as Grayscale Release, Service Warm-up, Lossless Online and Offline and Outlier Ejection. +In addition to the above-mentioned features, for the needs of enterprise users' scenarios, [Microservices Engine (MSE)](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar) of Spring Cloud Alibaba's enterprise version provides an enterprise-level microservices governance center, which includes more powerful governance capabilities such as Grayscale Release, Service Warm-up, Lossless Online and Offline and Outlier Ejection. At the same time, it also provides a variety of products and solutions such as enterprise-level Nacos registration / configuration center, enterprise-level cloud native gateway. ## Components From d886924ff347cfb1a710ebe00af47e02922c2553 Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Wed, 27 Oct 2021 18:11:06 +0800 Subject: [PATCH 80/99] Add README-zh.md content --- README-zh.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README-zh.md b/README-zh.md index 12fd01347..cb9b0737e 100644 --- a/README-zh.md +++ b/README-zh.md @@ -9,6 +9,8 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。 +此外,阿里云同时还提供了 Spring Cloud Alibaba 企业版 [微服务解决方案](https://www.aliyun.com/product/aliware/mse?spm=github.spring.com.topbar),包括无侵入服务治理(全链路灰度,无损上下线,离群实例摘除等),企业级 Nacos 注册配置中心和企业级云原生网关等众多产品。 + 参考文档 请查看 [WIKI](https://github.com/alibaba/spring-cloud-alibaba/wiki) 。 为 Spring Cloud Alibaba 贡献代码请参考 [如何贡献](https://github.com/alibaba/spring-cloud-alibaba/wiki/%E5%A6%82%E4%BD%95%E8%B4%A1%E7%8C%AE%E4%BB%A3%E7%A0%81) 。 From 1a146c726efcc7eccce508cb7251a88bc2fe1ce4 Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Mon, 1 Nov 2021 10:09:41 +0800 Subject: [PATCH 81/99] Fixed the errors in nacos-config-demo --- .../nacos-config-example/readme-zh.md | 10 +++++----- .../nacos-example/nacos-config-example/readme.md | 14 +++++++------- .../src/main/resources/bootstrap.properties | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md index c58f67833..76167ca4b 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md @@ -61,9 +61,9 @@ 内容如下 - user.id=1 - user.name=james - user.age=17 + user.id=1 + user.name=james + user.age=17 ### 应用启动 @@ -117,7 +117,7 @@ Nacos Client 从 Nacos Server 端获取数据时,调用的是此接口 `Config * `spring.profiles.active` 即为当前环境对应的 profile,详情可以参考 [Spring Boot文档](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-profiles) - **注意,当 activeprofile 为空时,对应的连接符 `-` 也将不存在,dataId 的拼接格式变成 `${prefix}`.`${file-extension}`** + **注意,当 active profile 为空时,对应的连接符 `-` 也将不存在,dataId 的拼接格式变成 `${prefix}`.`${file-extension}`** * `file-extension` 为配置内容的数据格式,可以通过配置项 `spring.cloud.nacos.config.file-extension`来配置。 目前只支持 `properties` 类型。 @@ -153,7 +153,7 @@ Spring Boot 应用支持通过 Endpoint 来暴露相关信息,Nacos Config Sta Spring Boot 1.x 可以通过访问 http://127.0.0.1:18084/nacos_config 来查看 Nacos Endpoint 的信息。 -Spring Boot 2.x 可以通过访问 http://127.0.0.1:18084/actuator/nacos-config 来访问。 +Spring Boot 2.x 可以通过访问 http://127.0.0.1:18084/actuator/nacosconfig 来访问。 ![actuator](https://cdn.nlark.com/lark/0/2018/png/54319/1536986344822-279e1edc-ebca-4201-8362-0ddeff240b85.png) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md index 797c09cc1..f8dee9f33 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme.md @@ -62,9 +62,9 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl content is - user.id=1 - user.name=james - user.age=17 + user.id=1 + user.name=james + user.age=17 ### Start Application @@ -119,7 +119,7 @@ In Nacos Config Starter, the splicing format of dataId is as follows * `spring.profiles.active` is the profile corresponding to the current environment. For details, please refer to [Spring Boot Doc](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-profiles) - **Note: when the activeprofile is empty, the corresponding connector `-` will also not exist, and the splicing format of the dataId becomes `${prefix}`.`${file-extension}`** + **Note: when the active profile is empty, the corresponding connector `-` will also not exist, and the splicing format of the dataId becomes `${prefix}`.`${file-extension}`** * `file-extension` is the data format of the configuration content, which can be configured by the configuration item `spring.cloud.nacos.config.file-extension`. Currently only the `properties` type is supported. @@ -139,7 +139,7 @@ By default, Nacos Config Starter adds a listening function to all Nacos configur If you need to dynamically refresh a bean, please refer to the Spring and Spring Cloud specifications. It is recommended to add `@RefreshScope` or `@ConfigurationProperties ` annotations to the class. -Please refer to[ContextRefresher Java Doc](http://static.javadoc.io/org.springframework.cloud/spring-cloud-context/2.0.0.RELEASE/org/springframework/cloud/context/refresh/ContextRefresher.html) for more details. +Please refer to [ContextRefresher Java Doc](http://static.javadoc.io/org.springframework.cloud/spring-cloud-context/2.0.0.RELEASE/org/springframework/cloud/context/refresh/ContextRefresher.html) for more details. @@ -156,8 +156,8 @@ Spring Boot 1.x: Add configuration management.security.enabled=false Spring Boot 2.x: Add configuration management.endpoints.web.exposure.include=* To view the endpoint information, visit the following URLS: -Spring Boot1.x: Nacos Config Endpoint URL is http://127.0.0.1:18083/nacos_config. -Spring Boot2.x: Nacos Config Endpoint URL is http://127.0.0.1:18083/actuator/nacos-config. +Spring Boot 1.x: Nacos Config Endpoint URL is http://127.0.0.1:18084/nacos_config. +Spring Boot 2.x: Nacos Config Endpoint URL is http://127.0.0.1:18084/actuator/nacosconfig. ![actuator](https://cdn.nlark.com/lark/0/2018/png/54319/1536986344822-279e1edc-ebca-4201-8362-0ddeff240b85.png) diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties index c9c1c9f64..691cba2d1 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/src/main/resources/bootstrap.properties @@ -34,5 +34,5 @@ spring.cloud.nacos.config.extension-configs[1].refresh=true -#spring.cloud.nacos.config.refresh-enabled=true +spring.cloud.nacos.config.refresh-enabled=true From ab1d3ef48854de71a9c9b909b8cd81b9d5de472e Mon Sep 17 00:00:00 2001 From: "x_vivi@yeah.net" Date: Mon, 8 Nov 2021 11:27:51 +0800 Subject: [PATCH 82/99] Upgrade Spring Cloud & Spring Boot version to Hoxton.SR12, 2.3.12.RELEASE --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a97a8f5d8..055095e2f 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-build - 2.3.1.RELEASE + 2.3.5.RELEASE @@ -83,7 +83,7 @@ 2.2.7-SNAPSHOT - Hoxton.SR9 + Hoxton.SR12 2.7.13 From 000e141404fc2ccc1812cb44e721e03aa4c13ccb Mon Sep 17 00:00:00 2001 From: "x_vivi@yeah.net" Date: Fri, 5 Nov 2021 19:42:19 +0800 Subject: [PATCH 83/99] Change NacosServiceManager injection mode to constructor injection --- .../cloud/nacos/registry/NacosServiceRegistry.java | 8 ++++---- .../registry/NacosServiceRegistryAutoConfiguration.java | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java index 9b91ce48e..3c3546e18 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistry.java @@ -27,7 +27,6 @@ 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; @@ -49,11 +48,12 @@ public class NacosServiceRegistry implements ServiceRegistry { private final NacosDiscoveryProperties nacosDiscoveryProperties; - @Autowired - private NacosServiceManager nacosServiceManager; + private final NacosServiceManager nacosServiceManager; - public NacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) { + public NacosServiceRegistry(NacosServiceManager nacosServiceManager, + NacosDiscoveryProperties nacosDiscoveryProperties) { this.nacosDiscoveryProperties = nacosDiscoveryProperties; + this.nacosServiceManager = nacosServiceManager; } @Override diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java index c51c085ed..2f7273592 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.java @@ -20,6 +20,7 @@ import java.util.List; import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; +import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration; import org.springframework.beans.factory.ObjectProvider; @@ -50,8 +51,9 @@ public class NacosServiceRegistryAutoConfiguration { @Bean public NacosServiceRegistry nacosServiceRegistry( + NacosServiceManager nacosServiceManager, NacosDiscoveryProperties nacosDiscoveryProperties) { - return new NacosServiceRegistry(nacosDiscoveryProperties); + return new NacosServiceRegistry(nacosServiceManager, nacosDiscoveryProperties); } @Bean From 3d715c268731daa4e99904ca447ac1bba0505477 Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Thu, 2 Dec 2021 16:00:09 +0800 Subject: [PATCH 84/99] Updated release info --- pom.xml | 2 +- spring-cloud-alibaba-dependencies/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0a75ad5b2..fd5d66f58 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ - 2.2.7-SNAPSHOT + 2.2.8-SNAPSHOT Hoxton.SR12 diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index e56436134..715f622ac 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.7-SNAPSHOT + 2.2.8-SNAPSHOT 1.8.1 1.3.0 2.0.3 From 48c0be2277dd0cbe9f3f2db0f21a7aef254bd264 Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Thu, 2 Dec 2021 21:04:54 +0800 Subject: [PATCH 85/99] Updated README info --- README-zh.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README-zh.md b/README-zh.md index cb9b0737e..4db92ef3b 100644 --- a/README-zh.md +++ b/README-zh.md @@ -75,7 +75,7 @@ Spring Cloud 使用 Maven 来构建,最快的使用方式是将本项目 clone com.alibaba.cloud spring-cloud-alibaba-dependencies - 2.2.6.RELEASE + 2.2.7.RELEASE pom import diff --git a/README.md b/README.md index 58e7e5a7e..3f8ec48a5 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ These artifacts are available from Maven Central and Spring Release repository v com.alibaba.cloud spring-cloud-alibaba-dependencies - 2.2.6.RELEASE + 2.2.7.RELEASE pom import From 374757274f1429dcf69de0e021af04b0782ad4fd Mon Sep 17 00:00:00 2001 From: "chengpu.rzh" Date: Fri, 3 Dec 2021 22:17:43 +0800 Subject: [PATCH 86/99] Fixed Dubbo 2.7.13 fail to start --- spring-cloud-alibaba-dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml index 715f622ac..9ed2c1c2a 100644 --- a/spring-cloud-alibaba-dependencies/pom.xml +++ b/spring-cloud-alibaba-dependencies/pom.xml @@ -23,7 +23,7 @@ 1.3.0 2.0.3 0.8.0 - 1.0.10 + 1.0.11 2.2.1 From 162941e8807da1b3d473993d00229ca53d06df7c Mon Sep 17 00:00:00 2001 From: wuchao Date: Tue, 21 Dec 2021 17:52:13 +0800 Subject: [PATCH 87/99] fix issue#2323 --- .../SentinelWebAutoConfiguration.java | 25 +++----- .../sentinel/SentinelWebMvcConfigurer.java | 57 +++++++++++++++++++ 2 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebMvcConfigurer.java diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java index b899320cf..ff37a0a03 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebAutoConfiguration.java @@ -36,7 +36,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** @@ -65,23 +64,6 @@ public class SentinelWebAutoConfiguration implements WebMvcConfigurer { @Autowired private Optional requestOriginParserOptional; - @Autowired - private Optional sentinelWebInterceptorOptional; - - @Override - public void addInterceptors(InterceptorRegistry registry) { - if (!sentinelWebInterceptorOptional.isPresent()) { - return; - } - SentinelProperties.Filter filterConfig = properties.getFilter(); - registry.addInterceptor(sentinelWebInterceptorOptional.get()) - .order(filterConfig.getOrder()) - .addPathPatterns(filterConfig.getUrlPatterns()); - log.info( - "[Sentinel Starter] register SentinelWebInterceptor with urlPatterns: {}.", - filterConfig.getUrlPatterns()); - } - @Bean @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", matchIfMissing = true) @@ -118,4 +100,11 @@ public class SentinelWebAutoConfiguration implements WebMvcConfigurer { return sentinelWebMvcConfig; } + @Bean + @ConditionalOnProperty(name = "spring.cloud.sentinel.filter.enabled", + matchIfMissing = true) + public SentinelWebMvcConfigurer sentinelWebMvcConfigurer() { + return new SentinelWebMvcConfigurer(); + } + } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebMvcConfigurer.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebMvcConfigurer.java new file mode 100644 index 000000000..c9c518b7a --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/SentinelWebMvcConfigurer.java @@ -0,0 +1,57 @@ +/* + * 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 java.util.Optional; + +import com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author: chao.wu + */ +public class SentinelWebMvcConfigurer implements WebMvcConfigurer { + + private static final Logger log = LoggerFactory + .getLogger(SentinelWebMvcConfigurer.class); + + @Autowired + private SentinelProperties sentinelProperties; + + @Autowired + private Optional sentinelWebInterceptorOptional; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + if (!sentinelWebInterceptorOptional.isPresent()) { + return; + } + SentinelProperties.Filter filterConfig = sentinelProperties.getFilter(); + registry.addInterceptor(sentinelWebInterceptorOptional.get()) + .order(filterConfig.getOrder()) + .addPathPatterns(filterConfig.getUrlPatterns()); + log.info( + "[Sentinel Starter] register SentinelWebInterceptor with urlPatterns: {}.", + filterConfig.getUrlPatterns()); + } + +} From 6d58917fa6dadf4e8b38da6303e00e14e4a0f770 Mon Sep 17 00:00:00 2001 From: HuGuirong Date: Thu, 23 Dec 2021 12:29:18 +0800 Subject: [PATCH 88/99] NacosDataSourceProperties support for contextPath configuration items Closes gh-2327 --- .../config/NacosDataSourceProperties.java | 10 ++++++++++ .../factorybean/NacosDataSourceFactoryBean.java | 13 +++++++++++++ .../datasource/NacosDataSourceFactoryBeanTests.java | 4 ++++ .../datasource/NacosDataSourcePropertiesTests.java | 2 ++ 4 files changed, 29 insertions(+) diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java index 08790ac4b..d52c9c3b2 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java @@ -32,6 +32,8 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { private String serverAddr; + private String contextPath; + private String username; private String password; @@ -71,6 +73,14 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { this.serverAddr = serverAddr; } + public String getContextPath() { + return contextPath; + } + + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } + public String getUsername() { return username; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java index e8bf42e4c..d04dd1f95 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/factorybean/NacosDataSourceFactoryBean.java @@ -35,6 +35,8 @@ public class NacosDataSourceFactoryBean implements FactoryBean private String serverAddr; + private String contextPath; + private String username; private String password; @@ -63,6 +65,9 @@ public class NacosDataSourceFactoryBean implements FactoryBean properties.setProperty(PropertyKeyConst.ENDPOINT, this.endpoint); } + if (!StringUtils.isEmpty(this.contextPath)) { + properties.setProperty(PropertyKeyConst.CONTEXT_PATH, this.contextPath); + } if (!StringUtils.isEmpty(this.accessKey)) { properties.setProperty(PropertyKeyConst.ACCESS_KEY, this.accessKey); } @@ -94,6 +99,14 @@ public class NacosDataSourceFactoryBean implements FactoryBean this.serverAddr = serverAddr; } + public String getContextPath() { + return contextPath; + } + + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } + public String getUsername() { return username; } diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java index ca364f30e..cb4b826e3 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java @@ -39,6 +39,8 @@ public class NacosDataSourceFactoryBeanTests { private String serverAddr = "localhost:8848"; + private String contextPath = "/my-nacos"; + private String accessKey = "ak"; private String secretKey = "sk"; @@ -56,6 +58,7 @@ public class NacosDataSourceFactoryBeanTests { factoryBean.setDataId(dataId); factoryBean.setGroupId(groupId); factoryBean.setServerAddr(serverAddr); + factoryBean.setContextPath(contextPath); factoryBean.setConverter(converter); NacosDataSource nacosDataSource = mock(NacosDataSource.class); @@ -69,6 +72,7 @@ public class NacosDataSourceFactoryBeanTests { assertThat(factoryBean.getDataId()).isEqualTo(dataId); assertThat(factoryBean.getGroupId()).isEqualTo(groupId); assertThat(factoryBean.getServerAddr()).isEqualTo(serverAddr); + assertThat(factoryBean.getContextPath()).isEqualTo(contextPath); } @Test diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourcePropertiesTests.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourcePropertiesTests.java index f897d6ed8..cde739d06 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourcePropertiesTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourcePropertiesTests.java @@ -31,11 +31,13 @@ public class NacosDataSourcePropertiesTests { public void testNacosWithAddr() { NacosDataSourceProperties nacosDataSourceProperties = new NacosDataSourceProperties(); nacosDataSourceProperties.setServerAddr("127.0.0.1:8848"); + nacosDataSourceProperties.setContextPath("/my-nacos"); nacosDataSourceProperties.setRuleType(RuleType.FLOW); nacosDataSourceProperties.setDataId("sentinel"); nacosDataSourceProperties.setGroupId("custom-group"); nacosDataSourceProperties.setDataType("xml"); + assertThat(nacosDataSourceProperties.getContextPath()).isEqualTo("/my-nacos"); assertThat(nacosDataSourceProperties.getGroupId()).isEqualTo("custom-group"); assertThat(nacosDataSourceProperties.getDataId()).isEqualTo("sentinel"); assertThat(nacosDataSourceProperties.getDataType()).isEqualTo("xml"); From 941bdad484be6dbff0595ae281adffc13897b411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E5=A8=81?= <214508914@qq.com> Date: Mon, 27 Dec 2021 18:10:33 +0800 Subject: [PATCH 89/99] fix the checkstyle plugin error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ```shell [INFO] --- maven-checkstyle-plugin:3.0.0:check (checkstyle-validation) @ spring-cloud-starter-stream-rocketmq --- [INFO] 开始检查…… [ERROR] /Users/lizhiwei/Git/github/spring-cloud-alibaba/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java:59: 需要一个 Javadoc注释 @return 。 [JavadocMethod] 检查完成。 [INFO] ------------------------------------------------------------------------ ``` --- .../ExtendedBindingHandlerMappingsProviderConfiguration.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java index df5d47b6b..4d5700db6 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java @@ -55,6 +55,7 @@ public class ExtendedBindingHandlerMappingsProviderConfiguration { /** * if you want to customize a bean, please use this BeanName {@code RocketMQMessageConverter.DEFAULT_NAME}. + * @return */ @Bean(RocketMQMessageConverter.DEFAULT_NAME) @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME }) From 796d18a9418dd5f129f50e0af2e605528f9629ec Mon Sep 17 00:00:00 2001 From: HuGuirong Date: Fri, 7 Jan 2022 23:02:19 +0800 Subject: [PATCH 90/99] Update documentation and code comment links --- .../src/main/asciidoc-zh/nacos-config.adoc | 2 +- spring-cloud-alibaba-docs/src/main/asciidoc/nacos-config.adoc | 2 +- .../metadata/repository/DubboServiceMetadataRepository.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc index 96ef58716..0c4c6305b 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc @@ -281,7 +281,7 @@ NOTE: 该配置必须放在 bootstrap.properties 文件中。并且在添加配 === 支持自定义扩展的 Data Id 配置 -Nacos Config 从 0.2.1 版本后,可支持自定义 Data Id 的配置。关于这部分详细的设计可参考 https://github.com/spring-cloud-incubator/spring-cloud-alibaba/issues/141[这里]。 +Nacos Config 从 0.2.1 版本后,可支持自定义 Data Id 的配置。关于这部分详细的设计可参考 https://github.com/alibaba/spring-cloud-alibaba/issues/141[这里]。 一个完整的配置案例如下所示: [source,properties] diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-config.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-config.adoc index 5aa199c11..c9f97b464 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-config.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/nacos-config.adoc @@ -280,7 +280,7 @@ NOTE: This configuration must be in the bootstrap.properties file, and the value === Support Custom Data Id -As of Spring Cloud Alibaba Nacos Config, data id can be self-defined. For detailed design of this part, refer to https://github.com/spring-cloud-incubator/spring-cloud-alibaba/issues/141[Github issue]. +As of Spring Cloud Alibaba Nacos Config, data id can be self-defined. For detailed design of this part, refer to https://github.com/alibaba/spring-cloud-alibaba/issues/141[Github issue]. The following is a complete sample: [source,properties] diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java index 2579b12ab..776513f35 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -378,7 +378,7 @@ public class DubboServiceMetadataRepository String ipAddress = hostInfo.getIpAddress(); // To use InetUtils to set IP if they are different // issue : - // https://github.com/spring-cloud-incubator/spring-cloud-alibaba/issues/589 + // https://github.com/alibaba/spring-cloud-alibaba/issues/589 if (!Objects.equals(url.getHost(), ipAddress)) { actualURL = url.setHost(ipAddress); } @@ -388,7 +388,7 @@ public class DubboServiceMetadataRepository public void unexportURL(URL url) { String key = url.getServiceKey(); // NPE issue : - // https://github.com/spring-cloud-incubator/spring-cloud-alibaba/issues/591 + // https://github.com/alibaba/spring-cloud-alibaba/issues/591 List urls = allExportedURLs.get(key); if (!isEmpty(urls)) { urls.remove(url); From fcfa78c15c63f511022811eb92b633bdad8bc652 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Sat, 8 Jan 2022 16:49:27 +0800 Subject: [PATCH 91/99] Update README-zh.md Fixed unreachable url --- README-zh.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-zh.md b/README-zh.md index 4db92ef3b..f80e21238 100644 --- a/README-zh.md +++ b/README-zh.md @@ -45,7 +45,7 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。 **[Alibaba Cloud OSS](https://www.aliyun.com/product/oss)**: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。 -**[Alibaba Cloud SchedulerX](https://help.aliyun.com/document_detail/43136.html)**: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。 +**[Alibaba Cloud SchedulerX](https://cn.aliyun.com/aliware/schedulerx)**: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。 **[Alibaba Cloud SMS](https://www.aliyun.com/product/sms)**: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。 From f2fc814404f9e459533b1f6a439c16c67989f23f Mon Sep 17 00:00:00 2001 From: Chenwp Date: Sun, 9 Jan 2022 22:54:33 +0800 Subject: [PATCH 92/99] nacos configuration file support "---" --- .../nacos/client/NacosPropertySource.java | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java index 2abdc3499..683940c40 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java @@ -16,17 +16,18 @@ package com.alibaba.cloud.nacos.client; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; - import com.alibaba.cloud.nacos.NacosConfigProperties; - +import com.alibaba.nacos.shaded.com.google.common.collect.Lists; +import com.alibaba.nacos.shaded.com.google.common.collect.Maps; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.util.CollectionUtils; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + /** * @author xiaojing * @author pbting @@ -63,7 +64,7 @@ public class NacosPropertySource extends MapPropertySource { } NacosPropertySource(List> propertySources, String group, - String dataId, Date timestamp, boolean isRefreshable) { + String dataId, Date timestamp, boolean isRefreshable) { this(group, dataId, getSourceMap(group, dataId, propertySources), timestamp, isRefreshable); } @@ -80,12 +81,32 @@ public class NacosPropertySource extends MapPropertySource { return (Map) propertySource.getSource(); } } - // If it is multiple, it will be returned as it is, and the internal elements - // cannot be directly retrieved, so the user needs to implement the retrieval - // logic by himself - return Collections.singletonMap( - String.join(NacosConfigProperties.COMMAS, dataId, group), - propertySources); + + Map sourceMap = Maps.newHashMap(); + List> otherTypePropertySources = Lists.newArrayList(); + for (PropertySource propertySource : propertySources) { + if (propertySource == null) { + continue; + } + if (propertySource instanceof MapPropertySource) { + // If the Nacos configuration file uses "---" to separate property name, + // propertySources will be multiple documents, and every document is a map. + // see org.springframework.boot.env.YamlPropertySourceLoader#load + MapPropertySource mapPropertySource = (MapPropertySource) propertySource; + Map source = mapPropertySource.getSource(); + sourceMap.putAll(source); + } else { + otherTypePropertySources.add(propertySource); + } + } + + // Other property sources which is not instanceof MapPropertySource will be put as it is, + // and the internal elements cannot be directly retrieved, + // so the user needs to implement the retrieval logic by himself + if (!otherTypePropertySources.isEmpty()) { + sourceMap.put(String.join(NacosConfigProperties.COMMAS, dataId, group), otherTypePropertySources); + } + return sourceMap; } public String getGroup() { From aeb1dfb2e714d09c8f252b968c71e3cff555aba6 Mon Sep 17 00:00:00 2001 From: Chenwp Date: Mon, 10 Jan 2022 21:14:37 +0800 Subject: [PATCH 93/99] yaml powerMock --- .../cloud/nacos/client/NacosPropertySource.java | 11 ++++++----- .../alibaba/cloud/nacos/NacosFileExtensionTest.java | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java index 683940c40..60139ecf7 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java @@ -16,18 +16,19 @@ package com.alibaba.cloud.nacos.client; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + import com.alibaba.cloud.nacos.NacosConfigProperties; import com.alibaba.nacos.shaded.com.google.common.collect.Lists; import com.alibaba.nacos.shaded.com.google.common.collect.Maps; + import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.util.CollectionUtils; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; - /** * @author xiaojing * @author pbting diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java index 229610514..6e2e36504 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosFileExtensionTest.java @@ -67,7 +67,7 @@ public class NacosFileExtensionTest { throws Throwable { if ("test-name.yaml".equals(args[0]) && "DEFAULT_GROUP".equals(args[1])) { - return "user:\n name: hello\n age: 12"; + return "user:\n name: hello\n age: 12\n---\nuser:\n gender: male"; } return ""; } @@ -88,6 +88,7 @@ public class NacosFileExtensionTest { Assert.assertEquals(environment.getProperty("user.name"), "hello"); Assert.assertEquals(environment.getProperty("user.age"), "12"); + Assert.assertEquals(environment.getProperty("user.gender"), "male"); } @Configuration From 72180ff0b180b4c6f32ad32a0facc79b01f32f1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jan 2022 23:04:14 +0000 Subject: [PATCH 94/99] Bump dubbo from 2.7.13 to 2.7.15 Bumps [dubbo](https://github.com/apache/dubbo) from 2.7.13 to 2.7.15. - [Release notes](https://github.com/apache/dubbo/releases) - [Changelog](https://github.com/apache/dubbo/blob/3.0/CHANGES.md) - [Commits](https://github.com/apache/dubbo/compare/dubbo-2.7.13...dubbo-2.7.15) --- updated-dependencies: - dependency-name: org.apache.dubbo:dubbo dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fd5d66f58..a56944432 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ Hoxton.SR12 - 2.7.13 + 2.7.15 4.0.1 From 67b98c3a7afae4dd2fda13567dd80c31515c35c7 Mon Sep 17 00:00:00 2001 From: Chenwp Date: Thu, 13 Jan 2022 18:58:23 +0800 Subject: [PATCH 95/99] use LinkedHashMap to ensure the order of configuration. --- .../alibaba/cloud/nacos/client/NacosPropertySource.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java index 60139ecf7..0f1158a82 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java @@ -16,14 +16,14 @@ package com.alibaba.cloud.nacos.client; +import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.alibaba.cloud.nacos.NacosConfigProperties; -import com.alibaba.nacos.shaded.com.google.common.collect.Lists; -import com.alibaba.nacos.shaded.com.google.common.collect.Maps; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; @@ -83,8 +83,8 @@ public class NacosPropertySource extends MapPropertySource { } } - Map sourceMap = Maps.newHashMap(); - List> otherTypePropertySources = Lists.newArrayList(); + Map sourceMap = new LinkedHashMap<>(); + List> otherTypePropertySources = new ArrayList<>(); for (PropertySource propertySource : propertySources) { if (propertySource == null) { continue; From ebb130091eaa9417334fd05e4758ad8cac91f7f5 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Sat, 12 Feb 2022 21:27:37 +0800 Subject: [PATCH 96/99] Update sidecar.adoc --- spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc index 2a8832f52..611ad0929 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc @@ -3,7 +3,7 @@ `Spring Cloud Alibaba Sidecar` 是一个用来快速**完美整合** Spring Cloud 与 *异构微服务* 的框架,灵感来自 https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-sidecar[Spring -Cloud Netflix Sidecar] 。目前支持的服务发现组件: +Cloud Netflix Sidecar],目前支持的服务发现组件: * Nacos * Consul @@ -14,7 +14,7 @@ Cloud Netflix Sidecar] 。目前支持的服务发现组件: 非Spring Cloud应用,统称异构微服务。比如你的遗留项目,或者非JVM应用。 -==== ``完美整合''的三层含义 +==== "完美整合"的三层含义 * 享受服务发现的优势 * 有负载均衡 From 8af1ed84b749c9d0df4a18d137f8b158ad1cc61c Mon Sep 17 00:00:00 2001 From: iaiti Date: Fri, 18 Feb 2022 10:52:56 +0800 Subject: [PATCH 97/99] Update readme-zh.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit github网站处于https链接,资源为http被禁止跳转下载,更改为https资源下载 --- .../sentinel-example/sentinel-core-example/readme-zh.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md index c5a8111f9..6313ac6f8 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md @@ -65,7 +65,7 @@ 1. 首先需要获取 Sentinel 控制台,支持直接下载和源码构建两种方式。 - 1. 直接下载:[下载 Sentinel 控制台](http://edas-public.oss-cn-hangzhou.aliyuncs.com/install_package/demo/sentinel-dashboard.jar) + 1. 直接下载:[下载 Sentinel 控制台](https://edas-public.oss-cn-hangzhou.aliyuncs.com/install_package/demo/sentinel-dashboard.jar) 2. 源码构建:进入 Sentinel [Github 项目页面](https://github.com/alibaba/Sentinel),将代码 git clone 到本地自行编译打包,[参考此文档](https://github.com/alibaba/Sentinel/tree/master/sentinel-dashboard)。 2. 启动控制台,执行 Java 命令 `java -jar sentinel-dashboard.jar`完成 Sentinel 控制台的启动。 From 3451906c2b4ce7e2265e720d5522bc27b45d7ea2 Mon Sep 17 00:00:00 2001 From: Freeman Lau Date: Sat, 19 Feb 2022 01:29:15 +0800 Subject: [PATCH 98/99] Merge 2.2.x to 2022. --- pom.xml | 6 - .../src/main/asciidoc-zh/sentinel.adoc | 2 +- .../src/main/asciidoc-zh/sidecar.adoc | 2 +- .../src/main/asciidoc/sentinel.adoc | 2 +- .../nacos-config-2.4.x-example/pom.xml | 6 - .../nacos-config-2.4.x-example/readme-zh.md | 2 +- .../src/main/resources/application.yml | 5 +- .../cloud/examples/ProviderApplication.java | 5 +- .../src/main/resources/application.properties | 23 +- .../src/main/resources/bootstrap.yml | 2 +- .../src/main/resources/application.yml | 2 +- .../src/main/resources/application.properties | 2 +- .../src/main/resources/application.properties | 2 +- .../src/main/resources/application.properties | 2 +- .../src/main/resources/application.properties | 2 +- .../src/main/resources/bootstrap.yml | 2 +- .../sentinel-core-example/readme-zh.md | 2 +- .../sentinel-core-example/readme.md | 2 +- .../config/NacosDataSourceProperties.java | 2 +- .../NacosDataSourceFactoryBeanTests.java | 2 +- ...SentinelCircuitBreakerIntegrationTest.java | 8 +- .../cloud/nacos/NacosConfigProperties.java | 36 +-- .../nacos/client/NacosPropertySource.java | 54 ++-- ...itional-spring-configuration-metadata.json | 2 +- .../NacosConfigAutoConfigurationTest.java | 2 +- ...PropertiesServerAddressBothLevelTests.java | 9 +- .../cloud/nacos/NacosDiscoveryProperties.java | 7 +- ...itional-spring-configuration-metadata.json | 2 +- ...PropertiesServerAddressBothLevelTests.java | 11 +- ...yPropertiesServerAddressTopLevelTests.java | 10 +- ...acosRibbonClientPropertyOverrideTests.java | 82 ----- .../cloud/sentinel/feign/SentinelFeign.java | 70 ++-- .../feign/SentinelFeignAutoConfiguration.java | 7 - .../feign/SentinelTargeterAspect.java | 51 --- ...oServiceRegistrationAutoConfiguration.java | 18 +- .../GenearalServiceSubscribeHandler.java | 1 - ...gHandlerMappingsProviderConfiguration.java | 1 - .../integration/RocketMQMessageHandler.java | 302 ------------------ .../inbound/RocketMQConsumerFactory.java | 2 +- .../RocketMQInboundChannelAdapter.java | 7 +- .../inbound/pull/RocketMQAckCallback.java | 2 +- .../inbound/pull/RocketMQMessageSource.java | 20 +- .../RocketMQProducerMessageHandler.java | 20 +- 43 files changed, 174 insertions(+), 625 deletions(-) delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java diff --git a/pom.xml b/pom.xml index 922dfe8d3..d47f54403 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,6 @@ 4.0.1 - 2.0.4 4.6.1 @@ -180,11 +179,6 @@ - - - - - org.apache.rocketmq rocketmq-client diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc index 6dd603354..2a45f6d13 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc @@ -222,7 +222,7 @@ spring.cloud.sentinel.datasource.ds1.file.rule-type=flow #spring.cloud.sentinel.datasource.ds1.file.converter-class=org.springframework.cloud.alibaba.cloud.examples.JsonFlowRuleListConverter #spring.cloud.sentinel.datasource.ds1.file.rule-type=flow -spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848 +spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848 spring.cloud.sentinel.datasource.ds2.nacos.data-id=sentinel spring.cloud.sentinel.datasource.ds2.nacos.group-id=DEFAULT_GROUP spring.cloud.sentinel.datasource.ds2.nacos.data-type=json diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc index 611ad0929..07f448cff 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc @@ -89,7 +89,7 @@ spring: cloud: nacos: discovery: - server-addr: localhost:8848 + server-addr: 127.0.0.1:8848 gateway: discovery: locator: diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc index da132203e..0dfac8014 100644 --- a/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/sentinel.adoc @@ -225,7 +225,7 @@ spring.cloud.sentinel.datasource.ds1.file.rule-type=flow #spring.cloud.sentinel.datasource.ds1.file.converter-class=JsonFlowRuleListConverter #spring.cloud.sentinel.datasource.ds1.file.rule-type=flow -spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848 +spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848 spring.cloud.sentinel.datasource.ds2.nacos.data-id=sentinel spring.cloud.sentinel.datasource.ds2.nacos.group-id=DEFAULT_GROUP spring.cloud.sentinel.datasource.ds2.nacos.data-type=json diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/pom.xml b/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/pom.xml index 09b031af6..891376567 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/pom.xml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/pom.xml @@ -24,12 +24,6 @@ com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config - - - org.springframework.cloud - spring-cloud-starter-bootstrap - - diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/readme-zh.md b/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/readme-zh.md index 363a4cb50..1b26a025b 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/readme-zh.md @@ -46,7 +46,7 @@ spring: # 2.4.0 新增配置 spring.config.import config: import: - - optional:nacos:localhost:8848 + - optional:nacos:127.0.0.1:8848 ``` 3. 在 nacos 创建 test.yml diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/src/main/resources/application.yml b/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/src/main/resources/application.yml index 6047c5ab3..cdc55e868 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/src/main/resources/application.yml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-config-2.4.x-example/src/main/resources/application.yml @@ -7,9 +7,12 @@ spring: nacos: config: group: DEFAULT_GROUP - server-addr: localhost:8848 + server-addr: 127.0.0.1:8848 config: import: - optional:nacos:test.yml - optional:nacos:test01.yml?group=group_02 - optional:nacos:test02.yml?group=group_03&refreshEnabled=false +logging: + level: + com.alibaba.nacos: debug diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java index 723165507..038fe452f 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/java/com/alibaba/cloud/examples/ProviderApplication.java @@ -77,9 +77,10 @@ public class ProviderApplication { @GetMapping("/divide") public String divide(@RequestParam Integer a, @RequestParam Integer b) { - if(b == 0) { + if (b == 0) { return String.valueOf(0); - } else { + } + else { return String.valueOf(a / b); } } diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties index e967cd12f..228372852 100755 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-provider-example/src/main/resources/application.properties @@ -1,11 +1,12 @@ -server.port=18082 -spring.application.name=service-provider -spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 -spring.cloud.nacos.discovery.enabled=true -#spring.cloud.nacos.discovery.instance-enabled=true - -spring.cloud.nacos.username=nacos -spring.cloud.nacos.password=nacos - -management.endpoints.web.exposure.include=* -management.endpoint.health.show-details=always +server.port=18082 +spring.application.name=service-provider +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 +spring.cloud.nacos.discovery.enabled=true +#spring.cloud.nacos.discovery.instance-enabled=true + +spring.cloud.nacos.username=nacos +spring.cloud.nacos.password=nacos + +management.endpoints.web.exposure.include=* +management.endpoint.health.show-details=always + diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/src/main/resources/bootstrap.yml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/src/main/resources/bootstrap.yml index 9abeb329b..a53218009 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/src/main/resources/bootstrap.yml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-client-example/src/main/resources/bootstrap.yml @@ -6,7 +6,7 @@ spring: username: nacos password: nacos discovery: - server-addr: localhost:8848 + server-addr: 127.0.0.1:8848 config: discovery: enabled: true diff --git a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-server-example/src/main/resources/application.yml b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-server-example/src/main/resources/application.yml index cca1b4465..8fc3f8bf9 100644 --- a/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-server-example/src/main/resources/application.yml +++ b/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/nacos-discovery-spring-cloud-config-server-example/src/main/resources/application.yml @@ -9,7 +9,7 @@ spring: username: nacos password: nacos discovery: - server-addr: localhost:8848 + server-addr: 127.0.0.1:8848 config: server: git: diff --git a/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties index d5f73adfe..d67018432 100644 --- a/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.application.name=account-service server.port=18084 -spring.cloud.nacos.discovery.server-addr=localhost:8848 +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.datasource.name="accountDataSource" spring.datasource.type=com.alibaba.druid.pool.DruidDataSource diff --git a/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties index bc40bece3..a0f6550ab 100644 --- a/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties @@ -1,6 +1,6 @@ server.port=18081 spring.application.name=business-service -spring.cloud.nacos.discovery.server-addr=localhost:8848 +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 # The following configuration can be omitted. #feign.hystrix.enabled=true diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties index fb4a4b7c0..4fef9e1b4 100644 --- a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.application.name=order-service server.port=18083 -spring.cloud.nacos.discovery.server-addr=localhost:8848 +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.datasource.name="orderDataSource" spring.datasource.type=com.alibaba.druid.pool.DruidDataSource diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties index a2bd463a0..c9671852f 100644 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.application.name=storage-service server.port=18082 -spring.cloud.nacos.discovery.server-addr=localhost:8848 +spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.datasource.name="storageDataSource" spring.datasource.type=com.alibaba.druid.pool.DruidDataSource diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/resources/bootstrap.yml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/resources/bootstrap.yml index 7e7d1440a..6d1b2332f 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/resources/bootstrap.yml +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-circuitbreaker-example/src/main/resources/bootstrap.yml @@ -6,6 +6,6 @@ spring: cloud: nacos: config: - server-addr: localhost:8848 + server-addr: 127.0.0.1:8848 name: sentinel-circuitbreaker-rules.yml file-extension: yml diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md index c5a8111f9..e1a583421 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md @@ -206,7 +206,7 @@ Sentinel starter 整合了目前存在的几类 ReadableDataSource。只需要 spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json spring.cloud.sentinel.datasource.ds1.file.data-type=json -spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848 +spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848 spring.cloud.sentinel.datasource.ds2.nacos.dataId=sentinel spring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP spring.cloud.sentinel.datasource.ds2.nacos.data-type=json diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md index 1856a4a05..c1c946338 100644 --- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md +++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme.md @@ -181,7 +181,7 @@ If you want to define `FileRefreshableDataSource` and `NacosDataSource`, see the spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json spring.cloud.sentinel.datasource.ds1.file.data-type=json -spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848 +spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848 spring.cloud.sentinel.datasource.ds2.nacos.dataId=sentinel spring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP spring.cloud.sentinel.datasource.ds2.nacos.data-type=json diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java index d52c9c3b2..349c8db5e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/config/NacosDataSourceProperties.java @@ -61,7 +61,7 @@ public class NacosDataSourceProperties extends AbstractDataSourceProperties { if (StringUtils.isEmpty(serverAddr)) { serverAddr = this.getEnv().getProperty( "spring.cloud.sentinel.datasource.nacos.server-addr", - "localhost:8848"); + "127.0.0.1:8848"); } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java index cb4b826e3..8de459f97 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/test/java/com/alibaba/cloud/sentinel/datasource/NacosDataSourceFactoryBeanTests.java @@ -37,7 +37,7 @@ public class NacosDataSourceFactoryBeanTests { private String groupId = "DEFAULT_GROUP"; - private String serverAddr = "localhost:8848"; + private String serverAddr = "127.0.0.1:8848"; private String contextPath = "/my-nacos"; diff --git a/spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java b/spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java index 247b7efbf..0856b4772 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/ReactiveSentinelCircuitBreakerIntegrationTest.java @@ -44,15 +44,15 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; +import static com.alibaba.cloud.circuitbreaker.sentinel.ReactiveSentinelCircuitBreakerIntegrationTest.Application; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** * @author Ryan Baxter */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT, - classes = ReactiveSentinelCircuitBreakerIntegrationTest.Application.class, - properties = { "spring.cloud.discovery.client.health-indicator.enabled=false" }) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = Application.class, properties = { + "spring.cloud.discovery.client.health-indicator.enabled=false" }) @DirtiesContext public class ReactiveSentinelCircuitBreakerIntegrationTest { @@ -60,7 +60,7 @@ public class ReactiveSentinelCircuitBreakerIntegrationTest { private int port = 0; @Autowired - private ReactiveSentinelCircuitBreakerIntegrationTest.Application.DemoControllerService service; + private Application.DemoControllerService service; @Before public void setup() { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java index db3024adf..07fa74783 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/NacosConfigProperties.java @@ -107,7 +107,7 @@ public class NacosConfigProperties { .resolvePlaceholders("${spring.cloud.nacos.config.server-addr:}"); if (StringUtils.isEmpty(serverAddr)) { serverAddr = environment.resolvePlaceholders( - "${spring.cloud.nacos.server-addr:localhost:8848}"); + "${spring.cloud.nacos.server-addr:127.0.0.1:8848}"); } this.setServerAddr(serverAddr); } @@ -442,19 +442,19 @@ public class NacosConfigProperties { * @return string */ @Deprecated - @DeprecatedConfigurationProperty( - reason = "replaced to NacosConfigProperties#sharedConfigs and not use it at the same time.", - replacement = PREFIX + ".shared-configs[x]") + @DeprecatedConfigurationProperty(reason = "replaced to NacosConfigProperties#sharedConfigs and not use it at the same time.", replacement = PREFIX + + ".shared-configs[x]") public String getSharedDataids() { - return null == getSharedConfigs() ? null : getSharedConfigs().stream() - .map(Config::getDataId).collect(Collectors.joining(COMMAS)); + return null == getSharedConfigs() ? null + : getSharedConfigs().stream().map(Config::getDataId) + .collect(Collectors.joining(COMMAS)); } /** * recommend to use {@link NacosConfigProperties#sharedConfigs} and not use it at the * same time . * @param sharedDataids the dataids for configurable multiple shared configurations , - * multiple separated by commas . + * multiple separated by commas . */ @Deprecated public void setSharedDataids(String sharedDataids) { @@ -472,9 +472,8 @@ public class NacosConfigProperties { * @return string */ @Deprecated - @DeprecatedConfigurationProperty( - reason = "replaced to NacosConfigProperties#sharedConfigs and not use it at the same time.", - replacement = PREFIX + ".shared-configs[x].refresh") + @DeprecatedConfigurationProperty(reason = "replaced to NacosConfigProperties#sharedConfigs and not use it at the same time.", replacement = PREFIX + + ".shared-configs[x].refresh") public String getRefreshableDataids() { return null == getSharedConfigs() ? null : getSharedConfigs().stream().filter(Config::isRefresh) @@ -520,9 +519,8 @@ public class NacosConfigProperties { * @return extensionConfigs */ @Deprecated - @DeprecatedConfigurationProperty( - reason = "replaced to NacosConfigProperties#extensionConfigs and not use it at the same time .", - replacement = PREFIX + ".extension-configs[x]") + @DeprecatedConfigurationProperty(reason = "replaced to NacosConfigProperties#extensionConfigs and not use it at the same time .", replacement = PREFIX + + ".extension-configs[x]") public List getExtConfig() { return this.getExtensionConfigs(); } @@ -578,7 +576,8 @@ public class NacosConfigProperties { int index = endpoint.indexOf(":"); properties.put(ENDPOINT, endpoint.substring(0, index)); properties.put(ENDPOINT_PORT, endpoint.substring(index + 1)); - } else { + } + else { properties.put(ENDPOINT, endpoint); } @@ -617,11 +616,10 @@ public class NacosConfigProperties { + ", enableRemoteSyncConfig=" + enableRemoteSyncConfig + ", endpoint='" + endpoint + '\'' + ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\'' + ", secretKey='" + secretKey + '\'' - + ", ramRoleName='" + ramRoleName + '\'' - + ", contextPath='" + contextPath + '\'' + ", clusterName='" + clusterName - + '\'' + ", name='" + name + '\'' + '\'' + ", shares=" + sharedConfigs - + ", extensions=" + extensionConfigs + ", refreshEnabled=" - + refreshEnabled + '}'; + + ", ramRoleName='" + ramRoleName + '\'' + ", contextPath='" + contextPath + + '\'' + ", clusterName='" + clusterName + '\'' + ", name='" + name + '\'' + + '\'' + ", shares=" + sharedConfigs + ", extensions=" + extensionConfigs + + ", refreshEnabled=" + refreshEnabled + '}'; } public static class Config { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java index 6220f6930..4b4d07356 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySource.java @@ -83,31 +83,35 @@ public class NacosPropertySource extends MapPropertySource { } } - Map sourceMap = new LinkedHashMap<>(); - List> otherTypePropertySources = new ArrayList<>(); - for (PropertySource propertySource : propertySources) { - if (propertySource == null) { - continue; - } - if (propertySource instanceof MapPropertySource) { - // If the Nacos configuration file uses "---" to separate property name, - // propertySources will be multiple documents, and every document is a map. - // see org.springframework.boot.env.YamlPropertySourceLoader#load - MapPropertySource mapPropertySource = (MapPropertySource) propertySource; - Map source = mapPropertySource.getSource(); - sourceMap.putAll(source); - } else { - otherTypePropertySources.add(propertySource); - } - } - - // Other property sources which is not instanceof MapPropertySource will be put as it is, - // and the internal elements cannot be directly retrieved, - // so the user needs to implement the retrieval logic by himself - if (!otherTypePropertySources.isEmpty()) { - sourceMap.put(String.join(NacosConfigProperties.COMMAS, dataId, group), otherTypePropertySources); - } - return sourceMap; + Map sourceMap = new LinkedHashMap<>(); + List> otherTypePropertySources = new ArrayList<>(); + for (PropertySource propertySource : propertySources) { + if (propertySource == null) { + continue; + } + if (propertySource instanceof MapPropertySource) { + // If the Nacos configuration file uses "---" to separate property name, + // propertySources will be multiple documents, and every document is a + // map. + // see org.springframework.boot.env.YamlPropertySourceLoader#load + MapPropertySource mapPropertySource = (MapPropertySource) propertySource; + Map source = mapPropertySource.getSource(); + sourceMap.putAll(source); + } + else { + otherTypePropertySources.add(propertySource); + } + } + + // Other property sources which is not instanceof MapPropertySource will be put as + // it is, + // and the internal elements cannot be directly retrieved, + // so the user needs to implement the retrieval logic by himself + if (!otherTypePropertySources.isEmpty()) { + sourceMap.put(String.join(NacosConfigProperties.COMMAS, dataId, group), + otherTypePropertySources); + } + return sourceMap; } public String getGroup() { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json index f6f3fe414..603c6cf43 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -3,7 +3,7 @@ { "name": "spring.cloud.nacos.server-addr", "type": "java.lang.String", - "defaultValue": "localhost:8848", + "defaultValue": "127.0.0.1:8848", "description": "nacos server address." }, { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigAutoConfigurationTest.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigAutoConfigurationTest.java index 59309e3d5..3a25e8f29 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigAutoConfigurationTest.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigAutoConfigurationTest.java @@ -38,7 +38,7 @@ public class NacosConfigAutoConfigurationTest { assertThat(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, NacosConfigProperties.class).length).isEqualTo(1); assertThat(context.getBean(NacosConfigProperties.class).getServerAddr()) - .isEqualTo("localhost:8848"); + .isEqualTo("127.0.0.1:8848"); context.close(); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java index d0e134892..32224ea6a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config/src/test/java/com/alibaba/cloud/nacos/NacosConfigPropertiesServerAddressBothLevelTests.java @@ -28,7 +28,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** * @author lyuzb @@ -36,9 +35,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @RunWith(SpringRunner.class) @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) + properties = { "spring.cloud.nacos.config.server-addr=321.321.321.321:8848", + "spring.cloud.nacos.server-addr=123.123.123.123:8848" } +) public class NacosConfigPropertiesServerAddressBothLevelTests { @Autowired @@ -46,7 +45,7 @@ public class NacosConfigPropertiesServerAddressBothLevelTests { @Test public void testGetServerAddr() { - assertThat(properties.getServerAddr()).isEqualTo("321,321,321,321:8848"); + assertThat(properties.getServerAddr()).isEqualTo("321.321.321.321:8848"); } @Configuration diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java index 8515277ba..5b5ae9421 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java @@ -555,7 +555,8 @@ public class NacosDiscoveryProperties { watchDelay, logName, service, weight, clusterName, group, namingLoadCacheAtStart, metadata, registerEnabled, ip, networkInterface, port, secure, accessKey, secretKey, heartBeatInterval, heartBeatTimeout, - ipDeleteTimeout, instanceEnabled, ephemeral, failureToleranceEnabled, failFast); + ipDeleteTimeout, instanceEnabled, ephemeral, failureToleranceEnabled, + failFast); } @Override @@ -574,7 +575,7 @@ public class NacosDiscoveryProperties { + heartBeatInterval + ", heartBeatTimeout=" + heartBeatTimeout + ", ipDeleteTimeout=" + ipDeleteTimeout + ", instanceEnabled=" + instanceEnabled + ", ephemeral=" + ephemeral - + ", failureToleranceEnabled=" + failureToleranceEnabled + '}'; + + ", failureToleranceEnabled=" + failureToleranceEnabled + '}' + ", ipDeleteTimeout=" + ipDeleteTimeout + ", failFast=" + failFast + '}'; } @@ -585,7 +586,7 @@ public class NacosDiscoveryProperties { .resolvePlaceholders("${spring.cloud.nacos.discovery.server-addr:}"); if (StringUtils.isEmpty(serverAddr)) { serverAddr = env.resolvePlaceholders( - "${spring.cloud.nacos.server-addr:localhost:8848}"); + "${spring.cloud.nacos.server-addr:127.0.0.1:8848}"); } this.setServerAddr(serverAddr); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 12a9c531c..2e06a71ac 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -2,7 +2,7 @@ { "name": "spring.cloud.nacos.server-addr", "type": "java.lang.String", - "defaultValue": "localhost:8848", + "defaultValue": "127.0.0.1:8848", "description": "nacos server address." }, { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressBothLevelTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressBothLevelTests.java index 9e1ce8ae3..9a54b2ae1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressBothLevelTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressBothLevelTests.java @@ -29,18 +29,17 @@ import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationC import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; +import static com.alibaba.cloud.nacos.NacosDiscoveryPropertiesServerAddressBothLevelTests.TestConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** * @author lyuzb */ @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 = TestConfig.class, properties = { + "spring.application.name=app", + "spring.cloud.nacos.discovery.server-addr=321.321.321.321:8848", + "spring.cloud.nacos.server-addr=123.123.123.123:8848" }) public class NacosDiscoveryPropertiesServerAddressBothLevelTests { @Autowired diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java index db90b57a7..fb24e6e80 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/NacosDiscoveryPropertiesServerAddressTopLevelTests.java @@ -29,19 +29,17 @@ import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationC import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; +import static com.alibaba.cloud.nacos.NacosDiscoveryPropertiesServerAddressTopLevelTests.TestConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** * @author lyuzb * */ @RunWith(SpringRunner.class) -@SpringBootTest( - classes = NacosDiscoveryPropertiesServerAddressTopLevelTests.TestConfig.class, - properties = { "spring.cloud.nacos.server-addr=123.123.123.123:8848" }, - webEnvironment = RANDOM_PORT) - +@SpringBootTest(classes = TestConfig.class, properties = { + "spring.application.name=app", + "spring.cloud.nacos.server-addr=123.123.123.123:8848" }) public class NacosDiscoveryPropertiesServerAddressTopLevelTests { @Autowired diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java deleted file mode 100644 index af9110d33..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/test/java/com/alibaba/cloud/nacos/ribbon/NacosRibbonClientPropertyOverrideTests.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2013-2017 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.ribbon; - -import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration; -import com.netflix.loadbalancer.ConfigurationBasedServerList; -import com.netflix.loadbalancer.Server; -import com.netflix.loadbalancer.ZoneAwareLoadBalancer; -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.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.commons.util.UtilAutoConfiguration; -import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration; -import org.springframework.cloud.netflix.ribbon.RibbonClients; -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.context.junit4.SpringRunner; - -/** - * @author liujunjie - */ -@RunWith(SpringRunner.class) -@SpringBootTest(classes = NacosRibbonClientPropertyOverrideTests.TestConfiguration.class, - properties = { "spring.cloud.nacos.server-addr=127.0.0.1:8848", - "spring.cloud.nacos.username=nacos", "spring.cloud.nacos.password=nacos", - "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 - private SpringClientFactory factory; - - @Test - public void serverListOverridesToTest() { - ConfigurationBasedServerList.class - .cast(getLoadBalancer("localApp").getServerListImpl()); - } - - @Test - public void serverListRemoteTest() { - NacosServerList.class.cast(getLoadBalancer("remoteApp").getServerListImpl()); - } - - @SuppressWarnings("unchecked") - private ZoneAwareLoadBalancer getLoadBalancer(String name) { - return (ZoneAwareLoadBalancer) this.factory.getLoadBalancer(name); - } - - @Configuration - @RibbonClients - @EnableAutoConfiguration - @ImportAutoConfiguration({ UtilAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class, - RibbonNacosAutoConfiguration.class, NacosDiscoveryClientConfiguration.class }) - protected static class TestConfiguration { - - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java index 7c5a35f54..b80227614 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java @@ -25,8 +25,6 @@ import feign.Contract; import feign.Feign; import feign.InvocationHandlerFactory; import feign.Target; -import feign.hystrix.FallbackFactory; -import feign.hystrix.HystrixFeign; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; @@ -81,41 +79,41 @@ public final class SentinelFeign { @Override public InvocationHandler create(Target target, Map dispatch) { - // using reflect get fallback and fallbackFactory properties from - // FeignClientFactoryBean because FeignClientFactoryBean is a package - // level class, we can not use it in our package - Object feignClientFactoryBean = SentinelTargeterAspect - .getFeignClientFactoryBean(); - - if (feignClientFactoryBean != null) { - Class fallback = (Class) getFieldValue(feignClientFactoryBean, - "fallback"); - Class fallbackFactory = (Class) getFieldValue( - feignClientFactoryBean, "fallbackFactory"); - String beanName = (String) getFieldValue(feignClientFactoryBean, - "contextId"); - if (!StringUtils.hasText(beanName)) { - beanName = (String) getFieldValue(feignClientFactoryBean, - "name"); - } - - Object fallbackInstance; - FallbackFactory fallbackFactoryInstance; - // check fallback and fallbackFactory properties - if (void.class != fallback) { - fallbackInstance = getFromContext(beanName, "fallback", - fallback, target.type()); - return new SentinelInvocationHandler(target, dispatch, - new FallbackFactory.Default(fallbackInstance)); - } - if (void.class != fallbackFactory) { - fallbackFactoryInstance = (FallbackFactory) getFromContext( - beanName, "fallbackFactory", fallbackFactory, - FallbackFactory.class); - return new SentinelInvocationHandler(target, dispatch, - fallbackFactoryInstance); - } + GenericApplicationContext gctx = (GenericApplicationContext) Builder.this.applicationContext; + BeanDefinition def = gctx.getBeanDefinition(target.type().getName()); + + /* + * Due to the change of the initialization sequence, + * BeanFactory.getBean will cause a circular dependency. So + * FeignClientFactoryBean can only be obtained from BeanDefinition + */ + FeignClientFactoryBean feignClientFactoryBean = (FeignClientFactoryBean) def + .getAttribute("feignClientsRegistrarFactoryBean"); + + Class fallback = feignClientFactoryBean.getFallback(); + Class fallbackFactory = feignClientFactoryBean.getFallbackFactory(); + String beanName = feignClientFactoryBean.getContextId(); + if (!StringUtils.hasText(beanName)) { + beanName = (String) getFieldValue(feignClientFactoryBean, "name"); } + + Object fallbackInstance; + FallbackFactory fallbackFactoryInstance; + // check fallback and fallbackFactory properties + if (void.class != fallback) { + fallbackInstance = getFromContext(beanName, "fallback", fallback, + target.type()); + return new SentinelInvocationHandler(target, dispatch, + new FallbackFactory.Default(fallbackInstance)); + } + if (void.class != fallbackFactory) { + fallbackFactoryInstance = (FallbackFactory) getFromContext( + beanName, "fallbackFactory", fallbackFactory, + FallbackFactory.class); + return new SentinelInvocationHandler(target, dispatch, + fallbackFactoryInstance); + } + return new SentinelInvocationHandler(target, dispatch); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java index d78dd0b2e..5a7ba59c4 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeignAutoConfiguration.java @@ -41,11 +41,4 @@ public class SentinelFeignAutoConfiguration { return SentinelFeign.builder(); } - @Bean - @ConditionalOnProperty(name = "feign.sentinel.enabled") - @ConditionalOnClass(name = "org.springframework.cloud.openfeign.Targeter") - public SentinelTargeterAspect sentinelTargeterAspect() { - return new SentinelTargeterAspect(); - } - } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java deleted file mode 100644 index 69873b52c..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelTargeterAspect.java +++ /dev/null @@ -1,51 +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.feign; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; - -/** - * Record FeignClientFactoryBean to threadlocal, so that SentinelFeign can get it when - * creating SentinelInvocationHandler. - * - * @see com.alibaba.cloud.sentinel.feign.SentinelFeign.Builder - * @author theonefx - */ -@Aspect -public class SentinelTargeterAspect { - - private static final ThreadLocal FEIGN_CLIENT_FACTORY_BEAN = new ThreadLocal<>(); - - public static Object getFeignClientFactoryBean() { - return FEIGN_CLIENT_FACTORY_BEAN.get(); - } - - @Around("execution(* org.springframework.cloud.openfeign.Targeter.target(..))") - public Object process(ProceedingJoinPoint pjp) throws Throwable { - Object factory = pjp.getArgs()[0]; - try { - FEIGN_CLIENT_FACTORY_BEAN.set(factory); - return pjp.proceed(); - } - finally { - FEIGN_CLIENT_FACTORY_BEAN.remove(); - } - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java index 8d8d8df12..8edb3c589 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java @@ -80,12 +80,11 @@ import static org.springframework.util.ObjectUtils.isEmpty; @Configuration(proxyBeanMethods = false) @Import({ DubboServiceRegistrationEventPublishingAspect.class, DubboBootstrapStartCommandLineRunner.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 { /** @@ -304,13 +303,10 @@ public class DubboServiceRegistrationAutoConfiguration { return; } NewService newService = consulRegistration.getService(); - if (consulDiscoveryProperties.isTagsAsMetadata()) { - for (Map.Entry entry : serviceMetadata.entrySet()) { - attAsTag(newService.getTags(), entry.getKey(), entry.getValue()); - } - } - else { - newService.getMeta().putAll(serviceMetadata); + // properties `tagsAsMetadata` in tagsAsMetadata is deprecated, and default + // value is true. + for (Map.Entry entry : serviceMetadata.entrySet()) { + attAsTag(newService.getTags(), entry.getKey(), entry.getValue()); } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java index b92e8c4e5..9641c5ce1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-dubbo/src/main/java/com/alibaba/cloud/dubbo/registry/GenearalServiceSubscribeHandler.java @@ -167,7 +167,6 @@ public class GenearalServiceSubscribeHandler extends AbstractServiceSubscribeHan * Clone the subscribed URLs based on the template URLs. * @param serviceInstances the list of * {@link org.springframework.cloud.client.ServiceInstance service instances} - * @return */ List cloneExportedURLs(List serviceInstances) { diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java index 4d5700db6..df5d47b6b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java @@ -55,7 +55,6 @@ public class ExtendedBindingHandlerMappingsProviderConfiguration { /** * if you want to customize a bean, please use this BeanName {@code RocketMQMessageConverter.DEFAULT_NAME}. - * @return */ @Bean(RocketMQMessageConverter.DEFAULT_NAME) @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME }) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java deleted file mode 100644 index 6f89ff717..000000000 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java +++ /dev/null @@ -1,302 +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.stream.binder.rocketmq.integration; - -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation; -import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager; -import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties; -import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.producer.SendCallback; -import org.apache.rocketmq.client.producer.SendResult; -import org.apache.rocketmq.client.producer.SendStatus; -import org.apache.rocketmq.common.message.MessageConst; -import org.apache.rocketmq.common.message.MessageQueue; -import org.apache.rocketmq.spring.core.RocketMQTemplate; -import org.apache.rocketmq.spring.support.RocketMQHeaders; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.cloud.stream.binder.BinderHeaders; -import org.springframework.cloud.stream.binder.ExtendedProducerProperties; -import org.springframework.cloud.stream.binding.MessageConverterConfigurer; -import org.springframework.context.Lifecycle; -import org.springframework.integration.handler.AbstractMessageHandler; -import org.springframework.integration.support.DefaultErrorMessageStrategy; -import org.springframework.integration.support.ErrorMessageStrategy; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.support.ErrorMessage; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * @author Jim - */ -public class RocketMQMessageHandler extends AbstractMessageHandler implements Lifecycle { - - private final static Logger log = LoggerFactory - .getLogger(RocketMQMessageHandler.class); - - private ErrorMessageStrategy errorMessageStrategy = new DefaultErrorMessageStrategy(); - - private MessageChannel sendFailureChannel; - - private final RocketMQTemplate rocketMQTemplate; - - private RocketMQHeaderMapper headerMapper; - - private final Boolean transactional; - - private final String destination; - - private final String groupName; - - private final InstrumentationManager instrumentationManager; - - private boolean sync = false; - - private volatile boolean running = false; - - private ExtendedProducerProperties producerProperties; - - private MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor; - - public RocketMQMessageHandler(RocketMQTemplate rocketMQTemplate, String destination, - String groupName, Boolean transactional, - InstrumentationManager instrumentationManager, - ExtendedProducerProperties producerProperties, - MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor) { - this.rocketMQTemplate = rocketMQTemplate; - this.destination = destination; - this.groupName = groupName; - this.transactional = transactional; - this.instrumentationManager = instrumentationManager; - this.producerProperties = producerProperties; - this.partitioningInterceptor = partitioningInterceptor; - } - - @Override - public void start() { - if (!transactional) { - instrumentationManager - .addHealthInstrumentation(new Instrumentation(destination)); - try { - rocketMQTemplate.afterPropertiesSet(); - instrumentationManager.getHealthInstrumentation(destination) - .markStartedSuccessfully(); - } - catch (Exception e) { - instrumentationManager.getHealthInstrumentation(destination) - .markStartFailed(e); - log.error("RocketMQTemplate startup failed, Caused by " + e.getMessage()); - throw new MessagingException(MessageBuilder.withPayload( - "RocketMQTemplate startup failed, Caused by " + e.getMessage()) - .build(), e); - } - } - if (producerProperties.isPartitioned()) { - try { - List messageQueues = rocketMQTemplate.getProducer() - .fetchPublishMessageQueues(destination); - if (producerProperties.getPartitionCount() != messageQueues.size()) { - logger.info(String.format( - "The partition count of topic '%s' will change from '%s' to '%s'", - destination, producerProperties.getPartitionCount(), - messageQueues.size())); - producerProperties.setPartitionCount(messageQueues.size()); - partitioningInterceptor - .setPartitionCount(producerProperties.getPartitionCount()); - } - } - catch (MQClientException e) { - logger.error(e, "fetch publish message queues fail"); - } - } - running = true; - } - - @Override - public void stop() { - if (!transactional) { - rocketMQTemplate.destroy(); - } - running = false; - } - - @Override - public boolean isRunning() { - return running; - } - - @Override - protected void handleMessageInternal( - org.springframework.messaging.Message message) { - try { - // issue 737 fix - Map jsonHeaders = headerMapper - .fromHeaders(message.getHeaders()); - message = org.springframework.messaging.support.MessageBuilder - .fromMessage(message).copyHeaders(jsonHeaders).build(); - - final StringBuilder topicWithTags = new StringBuilder(destination); - String tags = Optional - .ofNullable(message.getHeaders().get(RocketMQHeaders.TAGS)).orElse("") - .toString(); - if (!StringUtils.isEmpty(tags)) { - topicWithTags.append(":").append(tags); - } - - SendResult sendRes = null; - if (transactional) { - sendRes = rocketMQTemplate.sendMessageInTransaction(groupName, - topicWithTags.toString(), message, message.getHeaders() - .get(RocketMQBinderConstants.ROCKET_TRANSACTIONAL_ARG)); - log.debug("transactional send to topic " + topicWithTags + " " + sendRes); - } - else { - int delayLevel = 0; - try { - Object delayLevelObj = message.getHeaders() - .getOrDefault(MessageConst.PROPERTY_DELAY_TIME_LEVEL, 0); - if (delayLevelObj instanceof Number) { - delayLevel = ((Number) delayLevelObj).intValue(); - } - else if (delayLevelObj instanceof String) { - delayLevel = Integer.parseInt((String) delayLevelObj); - } - } - catch (Exception e) { - // ignore - } - boolean needSelectQueue = message.getHeaders() - .containsKey(BinderHeaders.PARTITION_HEADER); - if (sync) { - if (needSelectQueue) { - sendRes = rocketMQTemplate.syncSendOrderly( - topicWithTags.toString(), message, "", - rocketMQTemplate.getProducer().getSendMsgTimeout()); - } - else { - sendRes = rocketMQTemplate.syncSend(topicWithTags.toString(), - message, - rocketMQTemplate.getProducer().getSendMsgTimeout(), - delayLevel); - } - log.debug("sync send to topic " + topicWithTags + " " + sendRes); - } - else { - Message finalMessage = message; - SendCallback sendCallback = new SendCallback() { - @Override - public void onSuccess(SendResult sendResult) { - log.debug("async send to topic " + topicWithTags + " " - + sendResult); - } - - @Override - public void onException(Throwable e) { - log.error("RocketMQ Message hasn't been sent. Caused by " - + e.getMessage()); - if (getSendFailureChannel() != null) { - getSendFailureChannel().send( - RocketMQMessageHandler.this.errorMessageStrategy - .buildErrorMessage(new MessagingException( - finalMessage, e), null)); - } - } - }; - if (needSelectQueue) { - rocketMQTemplate.asyncSendOrderly(topicWithTags.toString(), - message, "", sendCallback, - rocketMQTemplate.getProducer().getSendMsgTimeout()); - } - else { - rocketMQTemplate.asyncSend(topicWithTags.toString(), message, - sendCallback); - } - } - } - if (sendRes != null && !sendRes.getSendStatus().equals(SendStatus.SEND_OK)) { - if (getSendFailureChannel() != null) { - this.getSendFailureChannel().send(message); - } - else { - throw new MessagingException(message, - new MQClientException("message hasn't been sent", null)); - } - } - } - catch (Exception e) { - log.error("RocketMQ Message hasn't been sent. Caused by " + e.getMessage()); - if (getSendFailureChannel() != null) { - getSendFailureChannel().send(this.errorMessageStrategy - .buildErrorMessage(new MessagingException(message, e), null)); - } - else { - throw new MessagingException(message, e); - } - } - - } - - /** - * Set the failure channel. After a send failure, an {@link ErrorMessage} will be sent - * to this channel with a payload of a {@link MessagingException} with the failed - * message and cause. - * @param sendFailureChannel the failure channel. - * @since 0.2.2 - */ - public void setSendFailureChannel(MessageChannel sendFailureChannel) { - this.sendFailureChannel = sendFailureChannel; - } - - /** - * Set the error message strategy implementation to use when sending error messages - * after send failures. Cannot be null. - * @param errorMessageStrategy the implementation. - * @since 0.2.2 - */ - public void setErrorMessageStrategy(ErrorMessageStrategy errorMessageStrategy) { - Assert.notNull(errorMessageStrategy, "'errorMessageStrategy' cannot be null"); - this.errorMessageStrategy = errorMessageStrategy; - } - - public MessageChannel getSendFailureChannel() { - return sendFailureChannel; - } - - public void setSync(boolean sync) { - this.sync = sync; - } - - public RocketMQHeaderMapper getHeaderMapper() { - return headerMapper; - } - - public void setHeaderMapper(RocketMQHeaderMapper headerMapper) { - this.headerMapper = headerMapper; - } - -} diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java index ead3cdfe1..13c2cd415 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java @@ -125,7 +125,7 @@ public final class RocketMQConsumerFactory { null == rpcHook && consumerProperties.getVipChannelEnabled()); consumer.setInstanceName( RocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup())); - if(null != allocateMessageQueueStrategy) { + if (null != allocateMessageQueueStrategy) { consumer.setAllocateMessageQueueStrategy(allocateMessageQueueStrategy); } consumer.setNamesrvAddr(consumerProperties.getNameServer()); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java index d27836b98..1941e8cdd 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java @@ -142,9 +142,9 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport * The actual execution of a user-defined input consumption service method. * @param messageExtList rocket mq message list * @param failSupplier {@link ConsumeConcurrentlyStatus} or - * {@link ConsumeOrderlyStatus} + * {@link ConsumeOrderlyStatus} * @param sucSupplier {@link ConsumeConcurrentlyStatus} or - * {@link ConsumeOrderlyStatus} + * {@link ConsumeOrderlyStatus} * @param object * @return R */ @@ -195,7 +195,8 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport throw new MessagingException(MessageBuilder.withPayload( "DefaultMQPushConsumer init failed, Caused by " + e.getMessage()) .build(), e); - }finally { + } + finally { InstrumentationManager.addHealthInstrumentation(instrumentation); } } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java index 216bb05f0..12540af59 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java @@ -46,7 +46,7 @@ public class RocketMQAckCallback implements AcknowledgmentCallback { private final MessageQueue messageQueue; public RocketMQAckCallback(DefaultLitePullConsumer consumer, - MessageQueue messageQueue,MessageExt messageExt) { + MessageQueue messageQueue, MessageExt messageExt) { this.messageExt = messageExt; this.consumer = consumer; this.messageQueue = messageQueue; diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java index 6d5583518..d0f6c6234 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java @@ -91,11 +91,12 @@ public class RocketMQMessageSource extends AbstractMessageSource // this.consumer.setPullBatchSize(1); this.consumer.subscribe(topic, messageSelector); this.consumer.setAutoCommit(false); - //register TopicMessageQueueChangeListener for messageQueuesForTopic - consumer.registerTopicMessageQueueChangeListener(topic, messageQueuesForTopic::put); + // register TopicMessageQueueChangeListener for messageQueuesForTopic + consumer.registerTopicMessageQueueChangeListener(topic, + messageQueuesForTopic::put); this.consumer.start(); - //Initialize messageQueuesForTopic immediately - messageQueuesForTopic.put(topic,consumer.fetchMessageQueues(topic)); + // Initialize messageQueuesForTopic immediately + messageQueuesForTopic.put(topic, consumer.fetchMessageQueues(topic)); instrumentation.markStartedSuccessfully(); } catch (MQClientException e) { @@ -108,9 +109,9 @@ public class RocketMQMessageSource extends AbstractMessageSource this.running = true; } - private MessageQueue acquireCurrentMessageQueue(String topic,int queueId) { - Collection messageQueueSet = messageQueuesForTopic.get(topic); - if(CollectionUtils.isEmpty(messageQueueSet)){ + private MessageQueue acquireCurrentMessageQueue(String topic, int queueId) { + Collection messageQueueSet = messageQueuesForTopic.get(topic); + if (CollectionUtils.isEmpty(messageQueueSet)) { return null; } for (MessageQueue messageQueue : messageQueueSet) { @@ -151,7 +152,8 @@ public class RocketMQMessageSource extends AbstractMessageSource if (null == messageExt) { return null; } - MessageQueue messageQueue = this.acquireCurrentMessageQueue(messageExt.getTopic(),messageExt.getQueueId()); + MessageQueue messageQueue = this.acquireCurrentMessageQueue(messageExt.getTopic(), + messageExt.getQueueId()); if (messageQueue == null) { throw new IllegalArgumentException( "The message queue is not in assigned list"); @@ -160,7 +162,7 @@ public class RocketMQMessageSource extends AbstractMessageSource .convertMessage2Spring(messageExt); return MessageBuilder.fromMessage(message) .setHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK, - new RocketMQAckCallback(this.consumer,messageQueue, messageExt)) + new RocketMQAckCallback(this.consumer, messageQueue, messageExt)) .build(); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java index df9bedebc..35450cb1c 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java @@ -100,8 +100,10 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler // Use the default if the partition is on and no customization is available. this.messageQueueSelector = RocketMQBeanContainerCache.getBean( mqProducerProperties.getMessageQueueSelector(), - MessageQueueSelector.class, extendedProducerProperties.isPartitioned() - ? new PartitionMessageQueueSelector() : null); + MessageQueueSelector.class, + extendedProducerProperties.isPartitioned() + ? new PartitionMessageQueueSelector() + : null); } @Override @@ -169,23 +171,25 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler } ((TransactionMQProducer) defaultMQProducer) .setTransactionListener(transactionListener); - if(log.isDebugEnabled()){ - log.debug("send transaction message ->{}" , mqMessage); + if (log.isDebugEnabled()) { + log.debug("send transaction message ->{}", mqMessage); } sendResult = defaultMQProducer.sendMessageInTransaction(mqMessage, message.getHeaders().get(RocketMQConst.USER_TRANSACTIONAL_ARGS)); } else { - if(log.isDebugEnabled()){ - log.debug("send message ->{}" , mqMessage); + if (log.isDebugEnabled()) { + log.debug("send message ->{}", mqMessage); } sendResult = this.send(mqMessage, this.messageQueueSelector, message.getHeaders(), message); } - log.info("the message has sent,message={},sendResult={}",mqMessage,sendResult); + log.info("the message has sent,message={},sendResult={}", mqMessage, + sendResult); if (sendResult == null || !SendStatus.SEND_OK.equals(sendResult.getSendStatus())) { - log.error("message send fail.SendStatus is not OK.the message={}",mqMessage); + log.error("message send fail.SendStatus is not OK.the message={}", + mqMessage); this.doFail(message, new MessagingException( "message send fail.SendStatus is not OK.")); } From 1a7f900a9c92b82353daca8a177d562bef0d5baa Mon Sep 17 00:00:00 2001 From: Freeman Lau Date: Sat, 19 Feb 2022 21:50:29 +0800 Subject: [PATCH 99/99] Merge 2.2.x to 2022. fix conflict and checkstyle --- .../binder/rocketmq/RocketMQMessageChannelBinder.java | 4 +--- .../rocketmq/custom/RocketMQBeanContainerCache.java | 2 +- .../integration/inbound/RocketMQConsumerFactory.java | 8 ++++---- .../integration/outbound/RocketMQProduceFactory.java | 4 ++-- .../rocketmq/support/RocketMQMessageConverterSupport.java | 4 ++-- .../cloud/stream/binder/rocketmq/utils/RocketMQUtils.java | 4 ++-- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java index ed0be4eb9..7e1cea97e 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java @@ -39,7 +39,6 @@ import org.springframework.cloud.stream.provisioning.ConsumerDestination; import org.springframework.cloud.stream.provisioning.ProducerDestination; import org.springframework.integration.StaticMessageHeaderAccessor; import org.springframework.integration.acks.AcknowledgmentCallback; -import org.springframework.integration.acks.AcknowledgmentCallback.Status; import org.springframework.integration.channel.AbstractMessageChannel; import org.springframework.integration.core.MessageProducer; import org.springframework.integration.support.DefaultErrorMessageStrategy; @@ -47,7 +46,6 @@ import org.springframework.integration.support.ErrorMessageStrategy; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; -import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** @@ -116,7 +114,7 @@ public class RocketMQMessageChannelBinder extends ExtendedConsumerProperties extendedConsumerProperties) throws Exception { // todo support anymous consumer - if (StringUtils.isEmpty(group)) { + if (!StringUtils.hasLength(group)) { throw new RuntimeException( "'group must be configured for channel " + destination.getName()); } diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java index 21c62aede..a90e1f21a 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java @@ -62,7 +62,7 @@ public final class RocketMQBeanContainerCache { } public static T getBean(String beanName, Class clazz, T defaultObj) { - if (StringUtils.isEmpty(beanName)) { + if (!StringUtils.hasLength(beanName)) { return defaultObj; } Object obj = BEANS_CACHE.get(beanName); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java index 13c2cd415..b4e5b1529 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java @@ -60,8 +60,8 @@ public final class RocketMQConsumerFactory { AllocateMessageQueueStrategy.class, new AllocateMessageQueueAveragely()); RPCHook rpcHook = null; - if (!StringUtils.isEmpty(consumerProperties.getAccessKey()) - && !StringUtils.isEmpty(consumerProperties.getSecretKey())) { + if (StringUtils.hasLength(consumerProperties.getAccessKey()) + && StringUtils.hasLength(consumerProperties.getSecretKey())) { rpcHook = new AclClientRPCHook( new SessionCredentials(consumerProperties.getAccessKey(), consumerProperties.getSecretKey())); @@ -111,8 +111,8 @@ public final class RocketMQConsumerFactory { AllocateMessageQueueStrategy.class); RPCHook rpcHook = null; - if (!StringUtils.isEmpty(consumerProperties.getAccessKey()) - && !StringUtils.isEmpty(consumerProperties.getSecretKey())) { + if (StringUtils.hasLength(consumerProperties.getAccessKey()) + && StringUtils.hasLength(consumerProperties.getSecretKey())) { rpcHook = new AclClientRPCHook( new SessionCredentials(consumerProperties.getAccessKey(), consumerProperties.getSecretKey())); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java index 509aae652..d50ddf52d 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java @@ -65,8 +65,8 @@ public final class RocketMQProduceFactory { "Property 'nameServer' is required"); RPCHook rpcHook = null; - if (!StringUtils.isEmpty(producerProperties.getAccessKey()) - && !StringUtils.isEmpty(producerProperties.getSecretKey())) { + if (StringUtils.hasLength(producerProperties.getAccessKey()) + && StringUtils.hasLength(producerProperties.getSecretKey())) { rpcHook = new AclClientRPCHook( new SessionCredentials(producerProperties.getAccessKey(), producerProperties.getSecretKey())); diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java index 3615cd4e8..c6e0a29b1 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java @@ -138,13 +138,13 @@ public final class RocketMQMessageConverterSupport { if (Objects.nonNull(headers) && !headers.isEmpty()) { Object tag = headers.getOrDefault(Headers.TAGS, headers.get(toRocketHeaderKey(Headers.TAGS))); - if (!StringUtils.isEmpty(tag)) { + if (StringUtils.hasLength(tag.toString())) { rocketMsg.setTags(String.valueOf(tag)); } Object keys = headers.getOrDefault(Headers.KEYS, headers.get(toRocketHeaderKey(Headers.KEYS))); - if (!StringUtils.isEmpty(keys)) { + if (StringUtils.hasLength(keys.toString())) { rocketMsg.setKeys(keys.toString()); } Object flagObj = headers.getOrDefault(Headers.FLAG, diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java index b431db74f..4ab1411da 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java +++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java @@ -19,13 +19,13 @@ package com.alibaba.cloud.stream.binder.rocketmq.utils; import com.alibaba.cloud.stream.binder.rocketmq.constant.RocketMQConst; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties; import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQCommonProperties; +import org.apache.commons.lang3.StringUtils; import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.consumer.MessageSelector; import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.remoting.RPCHook; -import org.springframework.util.StringUtils; /** * @author Jim @@ -94,7 +94,7 @@ public final class RocketMQUtils { private static final String SQL = "sql:"; public static MessageSelector getMessageSelector(String expression) { - if (StringUtils.hasText(expression) && expression.startsWith(SQL)) { + if (StringUtils.isNotBlank(expression) && expression.startsWith(SQL)) { return MessageSelector.bySql(expression.replaceFirst(SQL, "")); } return MessageSelector.byTag(expression);