Commit 9ed5d3a5 by Nepxion

增加对埋点功能的可扩展性,可以支持第三方埋点(例如:CAT)

parent 895fc6e7
......@@ -455,9 +455,9 @@ XML示例(Json示例见discovery-springcloud-example-service下的rule.json)
<!-- service-name,表示服务名 -->
<!-- version-value,表示可供访问的版本,如果多个用“;”分隔,不允许出现空格 -->
<version>
<!-- 表示网关z的1.0,允许访问提供端服务a的1.0版本 -->
<!-- 表示网关g的1.0,允许访问提供端服务a的1.0版本 -->
<service consumer-service-name="discovery-springcloud-example-gateway" provider-service-name="discovery-springcloud-example-a" consumer-version-value="1.0" provider-version-value="1.0"/>
<!-- 表示网关z的1.1,允许访问提供端服务a的1.1版本 -->
<!-- 表示网关g的1.1,允许访问提供端服务a的1.1版本 -->
<service consumer-service-name="discovery-springcloud-example-gateway" provider-service-name="discovery-springcloud-example-a" consumer-version-value="1.1" provider-version-value="1.1"/>
<!-- 表示网关z的1.0,允许访问提供端服务a的1.0版本 -->
<service consumer-service-name="discovery-springcloud-example-zuul" provider-service-name="discovery-springcloud-example-a" consumer-version-value="1.0" provider-version-value="1.0"/>
......@@ -691,13 +691,17 @@ management.server.port=5100
# spring.application.strategy.control.enabled=true
# 开启和关闭Ribbon默认的ZoneAvoidanceRule负载均衡策略。一旦关闭,则使用RoundRobin简单轮询负载均衡策略。缺失则默认为true
# spring.application.strategy.zone.avoidance.rule.enabled=true
# 用户自定义和编程灰度路由策略的时候,对RPC方法调用拦截的时候,需要指定对业务Controller类的扫描路径,以便传递上下文对象。该项配置只对服务有效,对网关无效。缺失则默认关闭该功能
# 启动和关闭用户自定义和编程灰度路由策略的时候,对RPC方式的调用拦截。缺失则默认为false
spring.application.strategy.rpc.intercept.enabled=true
# 用户自定义和编程灰度路由策略的时候,对RPC方式调用拦截的时候,需要指定对业务Controller类的扫描路径,以便传递上下文对象。该项配置只对服务有效,对网关无效
spring.application.strategy.scan.packages=com.nepxion.discovery.plugin.example.service.feign
# 用户自定义和编程灰度路由策略的时候,对REST调用拦截的时候(支持Feign或者RestTemplate调用),需要把来自外部的指定Header参数传递到服务里,如果多个用“;”分隔,不允许出现空格。该项配置只对服务有效,对网关无效。缺失则默认关闭该功能
# 启动和关闭用户自定义和编程灰度路由策略的时候,对REST方式的调用拦截。缺失则默认为false
spring.application.strategy.rest.intercept.enabled=true
# 用户自定义和编程灰度路由策略的时候,对REST方式调用拦截的时候(支持Feign或者RestTemplate调用),需要把来自外部的指定Header参数传递到服务里,如果多个用“;”分隔,不允许出现空格。该项配置只对服务有效,对网关无效
spring.application.strategy.request.headers=version;region;token
# spring.application.strategy.zone.avoidance.rule.enabled=true
# 开启Zuul网关上实现Hystrix线程隔离模式做服务隔离时,必须把spring.application.strategy.hystrix.threadlocal.supported设置为true,同时要引入discovery-plugin-strategy-starter-hystrix包,否则线程切换时会发生ThreadLocal上下文对象丢失
# zuul.ribbon-isolation-strategy=thread
# 启动和关闭用户自定义和编程灰度路由策略的时候日志打印,注意每调用一次都会打印一次,会对性能有所影响,建议压测环境和生产环境关闭。缺失则默认为false
spring.application.strategy.intercept.log.print=true
# 开启服务端实现Hystrix线程隔离模式做服务隔离时,必须把spring.application.strategy.hystrix.threadlocal.supported设置为true,同时要引入discovery-plugin-strategy-starter-hystrix包,否则线程切换时会发生ThreadLocal上下文对象丢失
# spring.application.strategy.hystrix.threadlocal.supported=true
```
......
......@@ -16,11 +16,14 @@ import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.nepxion.discovery.plugin.strategy.service.constant.ServiceStrategyConstant;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContextHolder;
public class FeignStrategyInterceptor implements RequestInterceptor {
......@@ -29,18 +32,26 @@ public class FeignStrategyInterceptor implements RequestInterceptor {
private String requestHeaders;
@Autowired
private ConfigurableEnvironment environment;
@Autowired
private ServiceStrategyContextHolder serviceStrategyContextHolder;
public FeignStrategyInterceptor(String requestHeaders) {
this.requestHeaders = requestHeaders.toLowerCase();
LOG.info("------------- Feign Proxy Information -----------");
LOG.info("Feign interceptor headers are '{}'", requestHeaders);
LOG.info("------------- Feign Intercept Information -----------");
if (StringUtils.isNotEmpty(requestHeaders)) {
this.requestHeaders = requestHeaders.toLowerCase();
}
LOG.info("Feign intercepted headers are {}", StringUtils.isNotEmpty(requestHeaders) ? requestHeaders : "empty");
LOG.info("-------------------------------------------------");
}
@Override
public void apply(RequestTemplate requestTemplate) {
if (StringUtils.isEmpty(requestHeaders)) {
return;
}
ServletRequestAttributes attributes = serviceStrategyContextHolder.getRestAttributes();
if (attributes == null) {
return;
......@@ -52,13 +63,23 @@ public class FeignStrategyInterceptor implements RequestInterceptor {
return;
}
Boolean interceptLogPrint = environment.getProperty(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_INTERCEPT_LOG_PRINT, Boolean.class, Boolean.FALSE);
if (interceptLogPrint) {
LOG.info("------------- Feign Route Information -----------");
}
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String header = previousRequest.getHeader(headerName);
if (requestHeaders.contains(headerName.toLowerCase())) {
if (interceptLogPrint) {
LOG.info("{}={}", headerName, header);
}
requestTemplate.header(headerName, header);
}
}
if (interceptLogPrint) {
LOG.info("-------------------------------------------------");
}
}
}
\ No newline at end of file
......@@ -14,9 +14,11 @@ import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
......@@ -24,6 +26,7 @@ import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.nepxion.discovery.plugin.strategy.service.constant.ServiceStrategyConstant;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContextHolder;
public class RestTemplateStrategyInterceptor implements ClientHttpRequestInterceptor {
......@@ -32,18 +35,26 @@ public class RestTemplateStrategyInterceptor implements ClientHttpRequestInterce
private String requestHeaders;
@Autowired
private ConfigurableEnvironment environment;
@Autowired
private ServiceStrategyContextHolder serviceStrategyContextHolder;
public RestTemplateStrategyInterceptor(String requestHeaders) {
this.requestHeaders = requestHeaders.toLowerCase();
LOG.info("------------- RestTemplate Proxy Information -----------");
LOG.info("RestTemplate interceptor headers are '{}'", requestHeaders);
LOG.info("------------- RestTemplate Intercept Information -----------");
if (StringUtils.isNotEmpty(requestHeaders)) {
this.requestHeaders = requestHeaders.toLowerCase();
}
LOG.info("RestTemplate intercepted headers are {}", StringUtils.isNotEmpty(requestHeaders) ? requestHeaders : "empty");
LOG.info("-------------------------------------------------");
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
if (StringUtils.isEmpty(requestHeaders)) {
return execution.execute(request, body);
}
ServletRequestAttributes attributes = serviceStrategyContextHolder.getRestAttributes();
if (attributes == null) {
return execution.execute(request, body);
......@@ -55,15 +66,25 @@ public class RestTemplateStrategyInterceptor implements ClientHttpRequestInterce
return execution.execute(request, body);
}
Boolean interceptLogPrint = environment.getProperty(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_INTERCEPT_LOG_PRINT, Boolean.class, Boolean.FALSE);
if (interceptLogPrint) {
LOG.info("------------- RestTemplate Route Information -----------");
}
HttpHeaders headers = request.getHeaders();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String header = previousRequest.getHeader(headerName);
if (requestHeaders.contains(headerName.toLowerCase())) {
if (interceptLogPrint) {
LOG.info("{}={}", headerName, header);
}
headers.add(headerName, header);
}
}
if (interceptLogPrint) {
LOG.info("-------------------------------------------------");
}
return execution.execute(request, body);
}
......
......@@ -40,11 +40,11 @@ public class ServiceStrategyAutoConfiguration {
private ConfigurableEnvironment environment;
@Bean
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES, matchIfMissing = false)
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_RPC_INTERCEPT_ENABLED, matchIfMissing = false)
public RpcStrategyAutoScanProxy rpcStrategyAutoScanProxy() {
String scanPackages = environment.getProperty(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES);
if (StringUtils.isEmpty(scanPackages)) {
throw new DiscoveryException(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES + "'s value can't be empty, remove it if useless");
throw new DiscoveryException(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES + "'s value can't be empty");
}
if (ServiceStrategyConstant.EXCLUSION_SCAN_PACKAGES.contains(scanPackages)) {
......@@ -55,11 +55,11 @@ public class ServiceStrategyAutoConfiguration {
}
@Bean
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES, matchIfMissing = false)
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_RPC_INTERCEPT_ENABLED, matchIfMissing = false)
public RpcStrategyInterceptor rpcStrategyInterceptor() {
String scanPackages = environment.getProperty(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES);
if (StringUtils.isEmpty(scanPackages)) {
throw new DiscoveryException(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES + " can't be empty, remove it if useless");
throw new DiscoveryException(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_SCAN_PACKAGES + "'s value can't be empty");
}
if (ServiceStrategyConstant.EXCLUSION_SCAN_PACKAGES.contains(scanPackages)) {
......@@ -70,23 +70,17 @@ public class ServiceStrategyAutoConfiguration {
}
@Bean
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REQUEST_HEADERS, matchIfMissing = false)
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REST_INTERCEPT_ENABLED, matchIfMissing = false)
public FeignStrategyInterceptor feignStrategyInterceptor() {
String requestHeaders = environment.getProperty(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REQUEST_HEADERS);
if (StringUtils.isEmpty(requestHeaders)) {
throw new DiscoveryException(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REQUEST_HEADERS + " can't be empty, remove it if useless");
}
return new FeignStrategyInterceptor(requestHeaders);
}
@Bean
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REQUEST_HEADERS, matchIfMissing = false)
@ConditionalOnProperty(value = ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REST_INTERCEPT_ENABLED, matchIfMissing = false)
public RestTemplateStrategyInterceptor restTemplateStrategyInterceptor() {
String requestHeaders = environment.getProperty(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REQUEST_HEADERS);
if (StringUtils.isEmpty(requestHeaders)) {
throw new DiscoveryException(ServiceStrategyConstant.SPRING_APPLICATION_STRATEGY_REQUEST_HEADERS + " can't be empty, remove it if useless");
}
return new RestTemplateStrategyInterceptor(requestHeaders);
}
......
......@@ -2,9 +2,9 @@
<rule>
<discovery>
<version>
<!-- 表示网关z的1.0,允许访问提供端服务a的1.0版本 -->
<!-- 表示网关g的1.0,允许访问提供端服务a的1.0版本 -->
<service consumer-service-name="discovery-springcloud-example-gateway" provider-service-name="discovery-springcloud-example-a" consumer-version-value="1.0" provider-version-value="1.0"/>
<!-- 表示网关z的1.1,允许访问提供端服务a的1.1版本 -->
<!-- 表示网关g的1.1,允许访问提供端服务a的1.1版本 -->
<service consumer-service-name="discovery-springcloud-example-gateway" provider-service-name="discovery-springcloud-example-a" consumer-version-value="1.1" provider-version-value="1.1"/>
</version>
</discovery>
......
......@@ -86,9 +86,15 @@ spring.boot.admin.client.url=http://localhost:5555
# spring.application.strategy.control.enabled=true
# 开启和关闭Ribbon默认的ZoneAvoidanceRule负载均衡策略。一旦关闭,则使用RoundRobin简单轮询负载均衡策略。缺失则默认为true
# spring.application.strategy.zone.avoidance.rule.enabled=true
# 用户自定义和编程灰度路由策略的时候,对RPC方法调用拦截的时候,需要指定对业务Controller类的扫描路径,以便传递上下文对象。该项配置只对服务有效,对网关无效。缺失则默认关闭该功能
# 启动和关闭用户自定义和编程灰度路由策略的时候,对RPC方式的调用拦截。缺失则默认为false
spring.application.strategy.rpc.intercept.enabled=true
# 用户自定义和编程灰度路由策略的时候,对RPC方式调用拦截的时候,需要指定对业务Controller类的扫描路径,以便传递上下文对象。该项配置只对服务有效,对网关无效
spring.application.strategy.scan.packages=com.nepxion.discovery.plugin.example.service.feign
# 用户自定义和编程灰度路由策略的时候,对REST调用拦截的时候(支持Feign或者RestTemplate调用),需要把来自外部的指定Header参数传递到服务里,如果多个用“;”分隔,不允许出现空格。该项配置只对服务有效,对网关无效。缺失则默认关闭该功能
# 启动和关闭用户自定义和编程灰度路由策略的时候,对REST方式的调用拦截。缺失则默认为false
spring.application.strategy.rest.intercept.enabled=true
# 用户自定义和编程灰度路由策略的时候,对REST方式调用拦截的时候(支持Feign或者RestTemplate调用),需要把来自外部的指定Header参数传递到服务里,如果多个用“;”分隔,不允许出现空格。该项配置只对服务有效,对网关无效
spring.application.strategy.request.headers=version;region;token
# 启动和关闭用户自定义和编程灰度路由策略的时候日志打印,注意每调用一次都会打印一次,会对性能有所影响,建议压测环境和生产环境关闭。缺失则默认为false
spring.application.strategy.intercept.log.print=true
# 开启服务端实现Hystrix线程隔离模式做服务隔离时,必须把spring.application.strategy.hystrix.threadlocal.supported设置为true,同时要引入discovery-plugin-strategy-starter-hystrix包,否则线程切换时会发生ThreadLocal上下文对象丢失
# spring.application.strategy.hystrix.threadlocal.supported=true
\ 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