From e37de52366f88c642d8fd392f4a5e41b4a55c766 Mon Sep 17 00:00:00 2001 From: lepdou Date: Tue, 8 Nov 2022 15:28:58 +0800 Subject: [PATCH] merge 1.8.2-Hoxton.SR12 (#708) --- README-zh.md | 2 +- README.md | 2 +- changes/changes-1.8.2.md | 6 ++ .../PolarisLoadBalancerCompositeRule.java | 39 ++++++---- .../router/SimpleLoadBalancerTest.java | 72 ------------------- ...isCachingSpringLoadBalanceFactoryTest.java | 1 - .../feign/PolarisFeignLoadBalancerTest.java | 1 - .../router/feign}/SimpleLoadBalancer.java | 3 +- .../src/main/resources/bootstrap.yml | 6 ++ .../loadbalancer/PolarisLoadBalancer.java | 14 ++++ .../loadbalancer/PolarisWeightedRule.java | 18 ++++- .../loadbalancer/PolarisLoadBalancerTest.java | 2 + 12 files changed, 73 insertions(+), 93 deletions(-) create mode 100644 changes/changes-1.8.2.md delete mode 100644 spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/SimpleLoadBalancerTest.java rename spring-cloud-starter-tencent-polaris-router/src/{main/java/com/tencent/cloud/polaris/router => test/java/com/tencent/cloud/polaris/router/feign}/SimpleLoadBalancer.java (97%) diff --git a/README-zh.md b/README-zh.md index c39aa3fa..9637b4ab 100644 --- a/README-zh.md +++ b/README-zh.md @@ -70,7 +70,7 @@ Spring Cloud Tencent 所有组件都已上传到 Maven 中央仓库,只需要 com.tencent.cloud spring-cloud-tencent-dependencies - 1.8.1-Hoxton.SR12 + 1.8.2-Hoxton.SR12 pom import diff --git a/README.md b/README.md index 466a35f4..a46d6e0d 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ For example: com.tencent.cloud spring-cloud-tencent-dependencies - 1.8.1-Hoxton.SR12 + 1.8.2-Hoxton.SR12 pom import diff --git a/changes/changes-1.8.2.md b/changes/changes-1.8.2.md new file mode 100644 index 00000000..1ff48cf6 --- /dev/null +++ b/changes/changes-1.8.2.md @@ -0,0 +1,6 @@ +# Change Log +--- + +- [fix router concurrent bug&fix spring-retry circuit breaker not work bug](https://github.com/Tencent/spring-cloud-tencent/pull/679) +- [fix router unit test](https://github.com/Tencent/spring-cloud-tencent/pull/684) +- [fix weight load balancer bug](https://github.com/Tencent/spring-cloud-tencent/pull/704) diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java index 7581ca46..f06a8f32 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java @@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.router; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; @@ -37,6 +38,7 @@ import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.pojo.PolarisServer; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.polaris.loadbalancer.LoadBalancerUtils; +import com.tencent.cloud.polaris.loadbalancer.PolarisLoadBalancer; import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule; import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; @@ -84,6 +86,8 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule { private final AbstractLoadBalancerRule delegateRule; + private final AtomicBoolean initializedLoadBalancerToDelegateRule = new AtomicBoolean(false); + public PolarisLoadBalancerCompositeRule(RouterAPI routerAPI, PolarisLoadBalancerProperties polarisLoadBalancerProperties, IClientConfig iClientConfig, @@ -111,22 +115,31 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule { @Override public Server choose(Object key) { - // 1. get all servers - List allServers = getLoadBalancer().getReachableServers(); + ILoadBalancer loadBalancer = getLoadBalancer(); + + if (!(loadBalancer instanceof PolarisLoadBalancer)) { + return loadBalancer.chooseServer(key); + } + + // set load balancer to delegate rule + if (initializedLoadBalancerToDelegateRule.compareAndSet(false, true)) { + delegateRule.setLoadBalancer(loadBalancer); + } + + PolarisLoadBalancer polarisLoadBalancer = (PolarisLoadBalancer) loadBalancer; + + // 1. get all servers from polaris client + List allServers = polarisLoadBalancer.getReachableServersWithoutCache(); if (CollectionUtils.isEmpty(allServers)) { return null; } - ILoadBalancer loadBalancer = new SimpleLoadBalancer(); // 2. filter by router + List serversAfterRouter; if (key instanceof PolarisRouterContext) { // router implement for Feign and scg PolarisRouterContext routerContext = (PolarisRouterContext) key; - List serversAfterRouter = doRouter(allServers, routerContext); - // 3. filter by load balance. - // A LoadBalancer needs to be regenerated for each request, - // because the list of servers may be different after filtered by router - loadBalancer.addServers(serversAfterRouter); + serversAfterRouter = doRouter(allServers, routerContext); } else if (key instanceof HttpRequest) { // router implement for rest template @@ -135,20 +148,20 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule { String routerContextStr = request.getHeaders().getFirst(RouterConstant.HEADER_ROUTER_CONTEXT); if (StringUtils.isEmpty(routerContextStr)) { - loadBalancer.addServers(allServers); + serversAfterRouter = allServers; } else { PolarisRouterContext routerContext = JacksonUtils.deserialize(UriEncoder.decode(routerContextStr), PolarisRouterContext.class); - List serversAfterRouter = doRouter(allServers, routerContext); - loadBalancer.addServers(serversAfterRouter); + serversAfterRouter = doRouter(allServers, routerContext); } } else { - loadBalancer.addServers(allServers); + serversAfterRouter = allServers; } - delegateRule.setLoadBalancer(loadBalancer); + // 3. put filtered servers to thread local, so delegate rule choose servers from filtered servers. + polarisLoadBalancer.addServers(serversAfterRouter); return delegateRule.choose(key); } diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/SimpleLoadBalancerTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/SimpleLoadBalancerTest.java deleted file mode 100644 index 31653909..00000000 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/SimpleLoadBalancerTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. - * - * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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.tencent.cloud.polaris.router; - -import java.util.LinkedList; -import java.util.List; - -import com.netflix.loadbalancer.Server; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -/** - * test for {@link SimpleLoadBalancer}. - * - * @author lepdou 2022-05-26 - */ -public class SimpleLoadBalancerTest { - - @Test - public void testSetterGetter() { - List servers = new LinkedList<>(); - servers.add(Mockito.mock(Server.class)); - servers.add(Mockito.mock(Server.class)); - servers.add(Mockito.mock(Server.class)); - servers.add(Mockito.mock(Server.class)); - servers.add(Mockito.mock(Server.class)); - - SimpleLoadBalancer simpleLoadBalancer = new SimpleLoadBalancer(); - - simpleLoadBalancer.addServers(servers); - - List allServers = simpleLoadBalancer.getAllServers(); - List reachableServers = simpleLoadBalancer.getReachableServers(); - List availableServers = simpleLoadBalancer.getServerList(true); - - Assert.assertEquals(servers.size(), allServers.size()); - Assert.assertEquals(servers.size(), reachableServers.size()); - Assert.assertEquals(servers.size(), availableServers.size()); - } - - @Test - public void testSetNull() { - SimpleLoadBalancer simpleLoadBalancer = new SimpleLoadBalancer(); - - simpleLoadBalancer.addServers(null); - - List allServers = simpleLoadBalancer.getAllServers(); - List reachableServers = simpleLoadBalancer.getReachableServers(); - List availableServers = simpleLoadBalancer.getServerList(true); - - Assert.assertEquals(0, allServers.size()); - Assert.assertEquals(0, reachableServers.size()); - Assert.assertEquals(0, availableServers.size()); - } -} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactoryTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactoryTest.java index f84dec3e..e1cd267a 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactoryTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisCachingSpringLoadBalanceFactoryTest.java @@ -20,7 +20,6 @@ package com.tencent.cloud.polaris.router.feign; import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.loadbalancer.ILoadBalancer; -import com.tencent.cloud.polaris.router.SimpleLoadBalancer; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancerTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancerTest.java index ed7ea3d0..6c7dfb71 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancerTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/PolarisFeignLoadBalancerTest.java @@ -32,7 +32,6 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.polaris.router.PolarisRouterContext; -import com.tencent.cloud.polaris.router.SimpleLoadBalancer; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/SimpleLoadBalancer.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/SimpleLoadBalancer.java similarity index 97% rename from spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/SimpleLoadBalancer.java rename to spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/SimpleLoadBalancer.java index 3ccaf01a..54dab79e 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/SimpleLoadBalancer.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/feign/SimpleLoadBalancer.java @@ -13,10 +13,9 @@ * 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.tencent.cloud.polaris.router; +package com.tencent.cloud.polaris.router.feign; import java.util.Collections; import java.util.List; diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml index 7a53c2f0..47d4b1d1 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-router-example/router-caller-service/src/main/resources/bootstrap.yml @@ -14,6 +14,12 @@ spring: enabled: true loadbalancer: enabled: true + loadbalancer: + retry: + retry-on-all-operations: true + max-retries-on-same-service-instance: 0 + max-retries-on-next-service-instance: 3 +# strategy: polarisWeighted management: endpoints: web: diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java index d1c4e3ae..c3b28f18 100644 --- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java +++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancer.java @@ -52,6 +52,7 @@ import org.springframework.util.CollectionUtils; * @author Haotian Zhang */ public class PolarisLoadBalancer extends DynamicServerListLoadBalancer { + private static final ThreadLocal> THREAD_CACHE_SERVERS = new ThreadLocal<>(); private final ConsumerAPI consumerAPI; @@ -64,8 +65,21 @@ public class PolarisLoadBalancer extends DynamicServerListLoadBalancer { this.polarisLoadBalancerProperties = properties; } + @Override + public void addServers(List servers) { + THREAD_CACHE_SERVERS.set(servers); + } + @Override public List getReachableServers() { + // Get servers first from the thread context + if (!CollectionUtils.isEmpty(THREAD_CACHE_SERVERS.get())) { + return THREAD_CACHE_SERVERS.get(); + } + return getReachableServersWithoutCache(); + } + + public List getReachableServersWithoutCache() { ServiceInstances serviceInstances; if (polarisLoadBalancerProperties.getDiscoveryType().equals(ContextConstant.POLARIS)) { serviceInstances = getPolarisDiscoveryServiceInstances(); diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisWeightedRule.java b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisWeightedRule.java index 31278f55..8c38d3a5 100644 --- a/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisWeightedRule.java +++ b/spring-cloud-tencent-polaris-loadbalancer/src/main/java/com/tencent/cloud/polaris/loadbalancer/PolarisWeightedRule.java @@ -21,7 +21,10 @@ package com.tencent.cloud.polaris.loadbalancer; import java.util.List; import com.netflix.client.config.IClientConfig; -import com.netflix.loadbalancer.AbstractLoadBalancerRule; +import com.netflix.loadbalancer.AbstractServerPredicate; +import com.netflix.loadbalancer.AvailabilityPredicate; +import com.netflix.loadbalancer.CompositePredicate; +import com.netflix.loadbalancer.PredicateBasedRule; import com.netflix.loadbalancer.Server; import com.tencent.cloud.common.pojo.PolarisServer; import com.tencent.polaris.api.config.consumer.LoadBalanceConfig; @@ -38,9 +41,10 @@ import org.springframework.util.CollectionUtils; * * @author lepdou 2022-05-17 */ -public class PolarisWeightedRule extends AbstractLoadBalancerRule { +public class PolarisWeightedRule extends PredicateBasedRule { private final RouterAPI routerAPI; + private CompositePredicate compositePredicate; public PolarisWeightedRule(RouterAPI routerAPI) { this.routerAPI = routerAPI; @@ -48,6 +52,13 @@ public class PolarisWeightedRule extends AbstractLoadBalancerRule { @Override public void initWithNiwsConfig(IClientConfig clientConfig) { + AvailabilityPredicate availabilityPredicate = new AvailabilityPredicate(this, clientConfig); + compositePredicate = CompositePredicate.withPredicates(availabilityPredicate).build(); + } + + @Override + public AbstractServerPredicate getPredicate() { + return compositePredicate; } @Override @@ -57,6 +68,9 @@ public class PolarisWeightedRule extends AbstractLoadBalancerRule { return null; } + // filter circuit breaker servers by ribbon + servers = compositePredicate.getEligibleServers(servers); + ServiceInstances serviceInstances = LoadBalancerUtils.transferServersToServiceInstances(servers); ProcessLoadBalanceRequest request = new ProcessLoadBalanceRequest(); diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java b/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java index 6241318f..6e5514c5 100644 --- a/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java +++ b/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java @@ -80,6 +80,7 @@ public class PolarisLoadBalancerTest { //mock routerAPI for rule when(routerAPI.processLoadBalance(any())).thenReturn(assembleProcessLoadBalanceResp()); PolarisWeightedRule rule = new PolarisWeightedRule(routerAPI); + rule.initWithNiwsConfig(new DefaultClientConfigImpl()); // clientConfig IClientConfig config = new DefaultClientConfigImpl(); @@ -111,6 +112,7 @@ public class PolarisLoadBalancerTest { //mock routerAPI for rule when(routerAPI.processLoadBalance(any())).thenReturn(assembleProcessLoadBalanceResp()); PolarisWeightedRule rule = new PolarisWeightedRule(routerAPI); + rule.initWithNiwsConfig(new DefaultClientConfigImpl()); // clientConfig IClientConfig config = new DefaultClientConfigImpl();