Commit 0542339d authored by 王亮's avatar 王亮

commit gray init code.

parent ef43eb4d
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- <maven.test.skip>true</maven.test.skip>--> <!-- <maven.test.skip>true</maven.test.skip>-->
<maven.javadoc.skip>true</maven.javadoc.skip> <maven.javadoc.skip>true</maven.javadoc.skip>
<revision>2.6.3.7</revision> <revision>2.6.3.8</revision>
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<maven-source-plugin.version>3.2.1</maven-source-plugin.version> <maven-source-plugin.version>3.2.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.3.1</maven-javadoc-plugin.version> <maven-javadoc-plugin.version>3.3.1</maven-javadoc-plugin.version>
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
<module>qg-apollo-starter</module> <module>qg-apollo-starter</module>
<module>qg-web-starter</module> <module>qg-web-starter</module>
<module>qg-micrometer-register-kafka-starter</module> <module>qg-micrometer-register-kafka-starter</module>
<module>qg-discovery-starter</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<packaging>pom</packaging> <packaging>pom</packaging>
<properties> <properties>
<revision>2.6.3.7</revision> <revision>2.6.3.8</revision>
<spring-boot.version>2.6.3</spring-boot.version> <spring-boot.version>2.6.3</spring-boot.version>
<spring-cloud.version>2021.0.1</spring-cloud.version> <spring-cloud.version>2021.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version> <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
......
<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">
<parent>
<artifactId>qg-boot-parent</artifactId>
<groupId>cn.quantgroup.boot</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qg-discovery-starter</artifactId>
<packaging>jar</packaging>
<version>2.6.3.7</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package cn.quantgroup.boot;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
import feign.Feign;
import feign.RequestInterceptor;
import org.slf4j.MDC;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
@Configuration
@DependsOn({"nacosServiceDiscovery"})
@EnableDiscoveryClient
public class DisCoveryAutoConfiguration {
final NacosAutoServiceRegistration nacosAutoServiceRegistration;
public DisCoveryAutoConfiguration(NacosAutoServiceRegistration nacosAutoServiceRegistration) {
this.nacosAutoServiceRegistration = nacosAutoServiceRegistration;
}
@LoadBalancerClients({
@LoadBalancerClient(value = "price-tracker", configuration = CustomLoadBalancerConfiguration.class),
@LoadBalancerClient(value = "sc-task", configuration = CustomLoadBalancerConfiguration.class),
@LoadBalancerClient(value = "sc-auth", configuration = CustomLoadBalancerConfiguration.class)}
)
public class FeignConfig {
@LoadBalanced
@Bean
public Feign.Builder feignBuilder() {
return Feign.builder();
}
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate -> requestTemplate.header("x-b3-version", MDC.get("x-b3-version"));
}
}
@Bean
public RequestLoggingFilter requestLoggingFilter() {
return new RequestLoggingFilter();
}
@Bean
public CommonsRequestLoggingFilter logFilter(RequestLoggingFilter requestLoggingFilter) {
requestLoggingFilter.setIncludeQueryString(true);
requestLoggingFilter.setIncludePayload(true);
requestLoggingFilter.setMaxPayloadLength(10000);
requestLoggingFilter.setIncludeHeaders(false);
requestLoggingFilter.setAfterMessagePrefix("REQUEST DATA : ");
return requestLoggingFilter;
}
public static class CustomLoadBalancerConfiguration {
@Bean
ReactorLoadBalancer<ServiceInstance> versionGrayLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory,
NacosDiscoveryProperties nacosDiscoveryProperties) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new VersionGrayLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name,
nacosDiscoveryProperties);
}
}
}
package cn.quantgroup.boot;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
@Slf4j
public class RequestLoggingFilter extends CommonsRequestLoggingFilter {
@Override
protected boolean shouldLog(HttpServletRequest request) {
return logger.isInfoEnabled();
}
/**
* Writes a log message before the request is processed.
*/
@Override
protected void beforeRequest(HttpServletRequest request, String message) {
Map<String,String> traces = MDC.getCopyOfContextMap();
String version = request.getHeader("x-b3-version");
if(StringUtils.isNoneBlank(version)){
traces.put("x-b3-version",version);
}
MDC.setContextMap(traces);
if(StringUtils.containsIgnoreCase(message,"/health/check")){
return;
}
Instant start = Instant.now();
request.setAttribute("metric-start", start);
}
/**
* Writes a log message after the request is processed.
*/
@Override
protected void afterRequest(HttpServletRequest request, String message) {
String contentType = request.getContentType();
if (StringUtils.containsAnyIgnoreCase(message,"/health/check","/actuator/health")
||StringUtils.containsAnyIgnoreCase(contentType,"multipart/form-data")) {
return;
}
Instant start = (Instant) request.getAttribute("metric-start");
Instant finished = Instant.now();
long time = Duration.between(start, finished).toMillis();
log.info("message:{},time:{}", message, time);
}
}
\ No newline at end of file
package cn.quantgroup.boot;
import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;
import org.springframework.context.annotation.Configuration;
@Configuration
@WebEndpoint(id = "serviceDeployEndpoint")
public class ServiceDeployEndpoint {
final NacosAutoServiceRegistration nacosAutoServiceRegistration;
public ServiceDeployEndpoint(NacosAutoServiceRegistration nacosAutoServiceRegistration) {
this.nacosAutoServiceRegistration = nacosAutoServiceRegistration;
}
@ReadOperation
public void offLine() {
nacosAutoServiceRegistration.stop();
}
}
\ No newline at end of file
package cn.quantgroup.boot;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.balancer.NacosBalancer;
import com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer;
import com.alibaba.nacos.common.utils.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;
public class VersionGrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private static final Logger log = LoggerFactory.getLogger(NacosLoadBalancer.class);
private final String serviceId;
ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
private final NacosDiscoveryProperties nacosDiscoveryProperties;
public VersionGrayLoadBalancer(
ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
String serviceId, NacosDiscoveryProperties nacosDiscoveryProperties) {
this.serviceId = serviceId;
this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
}
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
.getIfAvailable(NoopServiceInstanceListSupplier::new);
return supplier.get().next()
.mapNotNull(this::getInstanceResponse);
}
private Response<ServiceInstance> getInstanceResponse(
List<ServiceInstance> serviceInstances) {
if (serviceInstances.isEmpty()) {
log.warn("No servers available for service: " + this.serviceId);
return new EmptyResponse();
}
try {
String clusterName = this.nacosDiscoveryProperties.getClusterName();
List<ServiceInstance> instancesToChoose = serviceInstances;
if (StringUtils.isNotBlank(clusterName)) {
List<ServiceInstance> sameClusterInstances = serviceInstances.stream()
.filter(serviceInstance -> {
String cluster = serviceInstance.getMetadata()
.get("nacos.cluster");
return StringUtils.equals(cluster, clusterName);
}).collect(Collectors.toList());
String version = MDC.get("x-b3-version");
if (StringUtils.isEmpty(version)) {
sameClusterInstances = sameClusterInstances.stream()
.filter(i -> StringUtils.isEmpty(i.getMetadata().get("version"))).collect(
Collectors.toList());
} else {
List<ServiceInstance> grayInstances = sameClusterInstances.stream()
.filter(i -> version.equals(i.getMetadata().get("version"))).collect(
Collectors.toList());
if (CollectionUtils.isNotEmpty(grayInstances)) {
sameClusterInstances = grayInstances;
}
}
instancesToChoose = sameClusterInstances;
} else {
log.warn(
"A cross-cluster call occurs,name = {}, clusterName = {}, instance = {}",
serviceId, clusterName, serviceInstances);
}
ServiceInstance instance = NacosBalancer
.getHostByRandomWeight3(instancesToChoose);
return new DefaultResponse(instance);
} catch (Exception e) {
log.warn("NacosLoadBalancer error", e);
return null;
}
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.quantgroup.boot.DisCoveryAutoConfiguration,\
cn.quantgroup.boot.ServiceDeployEndpoint
\ No newline at end of file
...@@ -39,6 +39,10 @@ ...@@ -39,6 +39,10 @@
<groupId>org.apache.kafka</groupId> <groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId> <artifactId>kafka-clients</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment