Skip to content

Commit fcf6867

Browse files
authored
fix: server switch not work when only 1 server in cluster (#264)
1 parent fb3d773 commit fcf6867

File tree

4 files changed

+161
-33
lines changed

4 files changed

+161
-33
lines changed

polaris-plugins/polaris-plugins-connector/connector-polaris-grpc/pom.xml

+12
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,17 @@
4343
<version>${slf4j.version}</version>
4444
<scope>provided</scope>
4545
</dependency>
46+
<dependency>
47+
<groupId>com.tencent.polaris</groupId>
48+
<artifactId>polaris-test-mock-discovery</artifactId>
49+
<version>${project.version}</version>
50+
<scope>test</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>com.tencent.polaris</groupId>
54+
<artifactId>polaris-test-common</artifactId>
55+
<version>${project.version}</version>
56+
<scope>test</scope>
57+
</dependency>
4658
</dependencies>
4759
</project>

polaris-plugins/polaris-plugins-connector/connector-polaris-grpc/src/main/java/com/tencent/polaris/plugins/connector/grpc/ConnectionManager.java

+42-32
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.tencent.polaris.api.config.Configuration;
2121
import com.tencent.polaris.api.config.global.ClusterType;
2222
import com.tencent.polaris.api.config.global.ServerConnectorConfig;
23+
import com.tencent.polaris.api.config.verify.DefaultValues;
2324
import com.tencent.polaris.api.control.Destroyable;
2425
import com.tencent.polaris.api.exception.ErrorCode;
2526
import com.tencent.polaris.api.exception.PolarisException;
@@ -50,6 +51,7 @@
5051
import java.util.concurrent.TimeUnit;
5152
import java.util.concurrent.atomic.AtomicBoolean;
5253
import java.util.concurrent.atomic.AtomicReference;
54+
import java.util.function.Consumer;
5355
import org.slf4j.Logger;
5456

5557
/**
@@ -74,6 +76,7 @@ public class ConnectionManager extends Destroyable {
7476
private final String clientId;
7577
private Extensions extensions;
7678
private final ChannelTlsCertificates tlsCertificates;
79+
private Consumer<ConnID> callbackOnSwitched;
7780

7881
/**
7982
* 构造器
@@ -159,6 +162,15 @@ public boolean checkReady(ClusterType clusterType) {
159162
return serverAddressList.ready.get();
160163
}
161164

165+
public Consumer<ConnID> getCallbackOnSwitched() {
166+
return callbackOnSwitched;
167+
}
168+
169+
public void setCallbackOnSwitched(
170+
Consumer<ConnID> callbackOnSwitched) {
171+
this.callbackOnSwitched = callbackOnSwitched;
172+
}
173+
162174
/**
163175
* 设置准备状态
164176
*
@@ -257,9 +269,6 @@ private class SwitchServerTask implements Runnable {
257269
public void run() {
258270
for (Map.Entry<ClusterType, ServerAddressList> entry : serverAddresses.entrySet()) {
259271
ClusterType clusterType = entry.getKey();
260-
if (clusterType == ClusterType.BUILTIN_CLUSTER) {
261-
continue;
262-
}
263272
try {
264273
ServerAddressList serverAddressList = entry.getValue();
265274
serverAddressList.switchClient();
@@ -399,21 +408,35 @@ public void switchClientOnFail(ConnID lastConn) throws PolarisException {
399408
//已经完成切换,不处理
400409
return;
401410
}
402-
Node servAddress = getServerAddress();
403-
if (null == servAddress) {
404-
return;
405-
}
406-
if (null != curConnection) {
407-
if (servAddress.getHost().equals(curConnection.getConnID().getHost())
408-
&& servAddress.getPort() == curConnection.getConnID().getPort()) {
409-
return;
410-
}
411-
curConnection.lazyClose();
412-
}
413-
ConnID connID = new ConnID(serverServiceInfo.getServiceKey(), clusterType, servAddress.getHost(),
414-
servAddress.getPort(), protocol);
415-
Connection connection = connectTarget(connID);
416-
curConnectionValue.set(connection);
411+
doSwitchClient(curConnection);
412+
}
413+
}
414+
415+
private void doSwitchClient(Connection curConnection) throws PolarisException {
416+
Node servAddress = getServerAddress();
417+
if (null == servAddress) {
418+
return;
419+
}
420+
String preAddress = null;
421+
if (null != curConnection) {
422+
curConnection.lazyClose();
423+
preAddress = String.format(
424+
"%s:%d", curConnection.getConnID().getHost(), curConnection.getConnID().getPort());
425+
}
426+
String namespace = DefaultValues.DEFAULT_SYSTEM_NAMESPACE;
427+
String serviceName = DefaultValues.DEFAULT_BUILTIN_DISCOVER;
428+
if (null != serverServiceInfo) {
429+
namespace = serverServiceInfo.getServiceKey().getNamespace();
430+
serviceName = serverServiceInfo.getServiceKey().getService();
431+
}
432+
ConnID connID = new ConnID(new ServiceKey(namespace, serviceName), clusterType, servAddress.getHost(),
433+
servAddress.getPort(), protocol);
434+
Connection connection = connectTarget(connID);
435+
curConnectionValue.set(connection);
436+
LOG.info("server {} connection switched from {} to {}:{}",
437+
serviceName, preAddress, servAddress.getHost(), servAddress.getPort());
438+
if (null != callbackOnSwitched) {
439+
callbackOnSwitched.accept(connection.getConnID());
417440
}
418441
}
419442

@@ -423,25 +446,12 @@ public void switchClient() throws PolarisException {
423446
if (!Connection.isAvailableConnection(curConnection)) {
424447
return;
425448
}
426-
LOG.info("start switch for {}", serverServiceInfo.getServiceKey());
427449
synchronized (lock) {
428450
curConnection = curConnectionValue.get();
429451
if (!Connection.isAvailableConnection(curConnection)) {
430452
return;
431453
}
432-
Node servAddress = getServerAddress();
433-
if (null == servAddress) {
434-
return;
435-
}
436-
if (servAddress.getHost().equals(curConnection.getConnID().getHost())
437-
&& servAddress.getPort() == curConnection.getConnID().getPort()) {
438-
return;
439-
}
440-
ConnID connID = new ConnID(serverServiceInfo.getServiceKey(), clusterType, servAddress.getHost(),
441-
servAddress.getPort(), protocol);
442-
Connection connection = connectTarget(connID);
443-
curConnection.lazyClose();
444-
curConnectionValue.set(connection);
454+
doSwitchClient(curConnection);
445455
}
446456
}
447457

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Tencent is pleased to support the open source community by making Polaris available.
3+
*
4+
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
5+
*
6+
* Licensed under the BSD 3-Clause License (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* https://opensource.org/licenses/BSD-3-Clause
11+
*
12+
* Unless required by applicable law or agreed to in writing, software distributed
13+
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations under the License.
16+
*/
17+
18+
package com.tencent.polaris.plugins.connector.grpc;
19+
20+
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
21+
import static com.tencent.polaris.test.common.Consts.SERVICE_CIRCUIT_BREAKER;
22+
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
23+
24+
import com.tencent.polaris.api.config.Configuration;
25+
import com.tencent.polaris.api.config.global.ClusterType;
26+
import com.tencent.polaris.api.config.verify.DefaultValues;
27+
import com.tencent.polaris.api.plugin.common.PluginTypes;
28+
import com.tencent.polaris.api.plugin.compose.Extensions;
29+
import com.tencent.polaris.api.plugin.server.ServerConnector;
30+
import com.tencent.polaris.api.pojo.ServiceKey;
31+
import com.tencent.polaris.client.api.BaseEngine;
32+
import com.tencent.polaris.client.api.SDKContext;
33+
import com.tencent.polaris.factory.config.ConfigurationImpl;
34+
import com.tencent.polaris.plugins.connector.grpc.Connection.ConnID;
35+
import com.tencent.polaris.test.common.TestUtils;
36+
import com.tencent.polaris.test.mock.discovery.NamingServer;
37+
import com.tencent.polaris.test.mock.discovery.NamingService.InstanceParameter;
38+
import java.io.IOException;
39+
import java.util.concurrent.atomic.AtomicBoolean;
40+
import java.util.function.Consumer;
41+
import org.junit.After;
42+
import org.junit.Assert;
43+
import org.junit.Before;
44+
import org.junit.Test;
45+
46+
public class ConnectionManagerTest {
47+
48+
private NamingServer namingServer;
49+
50+
@Before
51+
public void before() {
52+
try {
53+
namingServer = NamingServer.startNamingServer(-1);
54+
System.setProperty(TestUtils.SERVER_ADDRESS_ENV, String.format("127.0.0.1:%d", namingServer.getPort()));
55+
} catch (IOException e) {
56+
Assert.fail(e.getMessage());
57+
}
58+
ServiceKey serviceKey = new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER);
59+
InstanceParameter parameter = new InstanceParameter();
60+
parameter.setHealthy(true);
61+
parameter.setIsolated(false);
62+
parameter.setWeight(100);
63+
namingServer.getNamingService().batchAddInstances(serviceKey, 10012, 1, parameter);
64+
}
65+
66+
@After
67+
public void after() {
68+
if (null != namingServer) {
69+
namingServer.terminate();
70+
}
71+
}
72+
73+
@Test
74+
public void testSwitchClient() {
75+
Configuration configuration = TestUtils.configWithEnvAddress();
76+
((ConfigurationImpl)configuration).getGlobal().getServerConnector().setServerSwitchInterval(1000L);
77+
AtomicBoolean switched = new AtomicBoolean(false);
78+
try (SDKContext sdkContext = SDKContext.initContextByConfig(configuration)) {
79+
ServerConnector serverConnector = (ServerConnector) sdkContext.getPlugins().getPlugin(
80+
PluginTypes.SERVER_CONNECTOR.getBaseType(), DefaultValues.DEFAULT_DISCOVER_PROTOCOL);
81+
GrpcConnector grpcConnector = (GrpcConnector) serverConnector;
82+
ConnectionManager connectionManager = grpcConnector.getConnectionManager();
83+
Extensions extensions = new Extensions();
84+
connectionManager.setExtensions(extensions);
85+
connectionManager.setCallbackOnSwitched(new Consumer<ConnID>() {
86+
@Override
87+
public void accept(ConnID connID) {
88+
if (switched.compareAndSet(false, true)) {
89+
System.out.println("server switched to " + connID);
90+
}
91+
}
92+
});
93+
Connection testConn = connectionManager.getConnection("test", ClusterType.BUILTIN_CLUSTER);
94+
Assert.assertNotNull(testConn);
95+
try {
96+
Thread.sleep(5000);
97+
} catch (InterruptedException e) {
98+
e.printStackTrace();
99+
}
100+
} catch (Throwable e) {
101+
e.printStackTrace();
102+
}
103+
Assert.assertTrue(switched.get());
104+
}
105+
106+
}

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464

6565
<properties>
6666
<!-- Project revision -->
67-
<revision>1.9.2</revision>
67+
<revision>1.9.3</revision>
6868

6969
<timestamp>${maven.build.timestamp}</timestamp>
7070
<skip.maven.deploy>false</skip.maven.deploy>

0 commit comments

Comments
 (0)