Skip to content

Commit

Permalink
feat: support lossless online/offline (#1377)
Browse files Browse the repository at this point in the history
Co-authored-by: Haotian Zhang <skyebefreeman@qq.com>
Co-authored-by: andrew shan <45474304+andrewshan@users.noreply.github.com>
  • Loading branch information
3 people committed Aug 13, 2024
1 parent 54d04d8 commit f5bb38c
Show file tree
Hide file tree
Showing 43 changed files with 1,727 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
- [fix:fix ApplicationContextAwareUtils NPE bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1296)
- [feat:upgrade jacoco version.](https://github.com/Tencent/spring-cloud-tencent/pull/1307)
- [fix: fix RouterLabelRestTemplateInterceptor add response headers exception with httpclient5.](https://github.com/Tencent/spring-cloud-tencent/pull/1376)
- [feat: support lossless online and offline](https://github.com/Tencent/spring-cloud-tencent/pull/1377)
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
import java.util.concurrent.ScheduledExecutorService;

import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.util.OkHttpUtil;
import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.util.OkHttpUtil;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
import com.tencent.polaris.api.config.global.StatReporterConfig;
import com.tencent.polaris.api.core.ProviderAPI;
Expand Down Expand Up @@ -176,7 +176,7 @@ public void register(PolarisRegistration registration) {
public void deregister(PolarisRegistration registration) {
LOGGER.info("De-registering from Polaris Server now...");

if (StringUtils.isEmpty(registration.getServiceId())) {
if (StringUtils.isEmpty(registration.getServiceId()) || !PolarisSDKContextManager.isRegistered) {
LOGGER.warn("No dom to de-register for polaris client...");
return;
}
Expand All @@ -191,6 +191,8 @@ public void deregister(PolarisRegistration registration) {
try {
ProviderAPI providerClient = polarisSDKContextManager.getProviderAPI();
providerClient.deRegister(deRegisterRequest);
PolarisSDKContextManager.isRegistered = false;
LOGGER.info("De-registration finished.");
}
catch (Exception e) {
LOGGER.error("ERR_POLARIS_DEREGISTER, de-register failed...{},", registration, e);
Expand All @@ -199,8 +201,6 @@ public void deregister(PolarisRegistration registration) {
if (null != heartbeatExecutor) {
heartbeatExecutor.shutdown();
}
LOGGER.info("De-registration finished.");
PolarisSDKContextManager.isRegistered = false;
}
}

Expand Down Expand Up @@ -238,21 +238,14 @@ public Object getStatus(PolarisRegistration registration) {
public void heartbeat(InstanceHeartbeatRequest heartbeatRequest) {
heartbeatExecutor.scheduleWithFixedDelay(() -> {
try {
String healthCheckEndpoint = polarisDiscoveryProperties.getHealthCheckUrl();
// If the health check passes, the heartbeat will be reported.
// If it does not pass, the heartbeat will not be reported.
if (!healthCheckEndpoint.startsWith("/")) {
healthCheckEndpoint = "/" + healthCheckEndpoint;
}

String healthCheckUrl = String.format("http://%s:%s%s", heartbeatRequest.getHost(),
heartbeatRequest.getPort(), healthCheckEndpoint);

Map<String, String> headers = new HashMap<>(1);
headers.put(HttpHeaders.USER_AGENT, "polaris");
if (!OkHttpUtil.get(healthCheckUrl, headers)) {
if (!OkHttpUtil.checkUrl(heartbeatRequest.getHost(), heartbeatRequest.getPort(),
polarisDiscoveryProperties.getHealthCheckUrl(), headers)) {
LOGGER.error("backend service health check failed. health check endpoint = {}",
healthCheckEndpoint);
polarisDiscoveryProperties.getHealthCheckUrl());
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ public static final class Modifier {
*/
public static Integer STAT_REPORTER_ORDER = 1;

/**
* Order of lossless configuration modifier.
*/
public static Integer LOSSLESS_ORDER = 2;

/**
* Order of service contract configuration modifier.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/

package com.tencent.cloud.polaris.util;
package com.tencent.cloud.common.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
Expand Down Expand Up @@ -87,4 +87,12 @@ public static boolean get(String path, Map<String, String> headers) {
}
return false;
}

public static boolean checkUrl(String host, Integer port, String endpoint, Map<String, String> headers) {
if (!endpoint.startsWith("/")) {
endpoint = "/" + endpoint;
}
String checkUrl = String.format("http://%s:%s%s", host, port, endpoint);
return get(checkUrl, headers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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.common.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.util.StringUtils;

import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;

/**
* Utils for URLDecoder/URLEncoder.
*
* @author Shedfree Wu
*/
public final class UrlUtils {

private static final Logger LOG = LoggerFactory.getLogger(UrlUtils.class);

private UrlUtils() {
}

public static String decode(String s) {
return decode(s, UTF_8);
}

public static String decode(String s, String enc) {
if (!StringUtils.hasText(s)) {
return s;
}
try {
return URLDecoder.decode(s, enc);
}
catch (UnsupportedEncodingException e) {
LOG.warn("Runtime system does not support {} coding. s:{}, msg:{}", enc, s, e.getMessage());
// return original string
return s;
}
}

public static String encode(String s) {
return encode(s, UTF_8);
}

public static String encode(String s, String enc) {
if (!StringUtils.hasText(s)) {
return s;
}
try {
return URLEncoder.encode(s, enc);
}
catch (UnsupportedEncodingException e) {
LOG.warn("Runtime system does not support {} coding. s:{}, msg:{}", enc, s, e.getMessage());
// return original string
return s;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/

package com.tencent.cloud.polaris.util;
package com.tencent.cloud.common.util;

import org.assertj.core.util.Maps;
import org.junit.jupiter.api.Test;
Expand All @@ -37,7 +37,13 @@
* @author Haotian Zhang
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = OkHttpUtilTest.TestApplication.class, properties = {"spring.application.name=test", "spring.cloud.polaris.discovery.register=false"})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = OkHttpUtilTest.TestApplication.class,
properties = {
"spring.application.name=test",
"spring.cloud.polaris.discovery.register=false",
"spring.cloud.gateway.enabled=false"
})
public class OkHttpUtilTest {

@LocalServerPort
Expand All @@ -46,6 +52,8 @@ public class OkHttpUtilTest {
@Test
public void testGet() {
assertThat(OkHttpUtil.get("http://localhost:" + port + "/test", Maps.newHashMap("key", "value"))).isTrue();
assertThat(OkHttpUtil.checkUrl("localhost", port, "/test", Maps.newHashMap("key", "value"))).isTrue();
assertThat(OkHttpUtil.checkUrl("localhost", port, "test", Maps.newHashMap("key", "value"))).isTrue();
assertThat(OkHttpUtil.get("http://localhost:" + port + "/error", Maps.newHashMap("key", "value"))).isFalse();
assertThat(OkHttpUtil.get("http://localhost:55555/error", Maps.newHashMap("key", "value"))).isFalse();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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.common.util;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Utils for {@link UrlUtils}.
*
* @author Shedfree Wu
*/
public class UrlUtilsTest {

@Test
public void testEncodeDecode1() {
String expectEncodeValue = "a%2Fb";
String origin = "a/b";
String encode1 = UrlUtils.encode(origin);
assertThat(expectEncodeValue).isEqualTo(encode1);
// encode twice is different
String encode2 = UrlUtils.encode(encode1);
assertThat(encode1).isNotEqualTo(encode2);
// test decode
assertThat(origin).isEqualTo(UrlUtils.decode(encode1));
}

@Test
public void testEncodeDecode2() {

String origin = null;
String encode1 = UrlUtils.encode(origin);
assertThat(encode1).isNull();

origin = "";
encode1 = UrlUtils.encode(origin);
assertThat(encode1).isEqualTo(origin);
}

@Test
public void testError() {
String origin = "a/b";
String encode = UrlUtils.encode(origin, "error-enc");
assertThat(encode).isEqualTo(origin);

encode = "a%2Fb";
String decode = UrlUtils.decode(encode, "error-enc");
assertThat(decode).isEqualTo(encode);
}

}
5 changes: 5 additions & 0 deletions spring-cloud-tencent-coverage/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-gateway-plugin</artifactId>
</dependency>

<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-lossless-plugin</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
6 changes: 6 additions & 0 deletions spring-cloud-tencent-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@
<version>${revision}</version>
</dependency>

<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-lossless-plugin</artifactId>
<version>${revision}</version>
</dependency>

<!-- third part framework dependencies -->
<dependency>
<groupId>com.google.guava</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>lossless-example</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>lossless-callee-service</artifactId>
<name>Spring Cloud Starter Tencent Lossless Callee Service Example</name>

<dependencies>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-all</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-lossless-plugin</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading

0 comments on commit f5bb38c

Please sign in to comment.