Commit 1df28dcc by Nepxion

服务端使用Hystrix做线程模式的服务隔离时,实现服务灰度路由的功能

parent 8d46a54f
......@@ -10,6 +10,7 @@ package com.nepxion.discovery.plugin.strategy.gateway.configuration;
*/
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
import org.springframework.context.annotation.Bean;
......@@ -36,6 +37,7 @@ public class GatewayStrategyAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean
public DiscoveryEnabledAdapter discoveryEnabledAdapter() {
return new DefaultDiscoveryEnabledAdapter();
}
......
......@@ -11,19 +11,23 @@ package com.nepxion.discovery.plugin.strategy.service.adapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.nepxion.discovery.common.constant.DiscoveryConstant;
import com.nepxion.discovery.plugin.strategy.adapter.AbstractDiscoveryEnabledAdapter;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContextHolder;
import com.netflix.loadbalancer.Server;
public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdapter {
private static final Logger LOG = LoggerFactory.getLogger(DefaultDiscoveryEnabledAdapter.class);
@Autowired
private ServiceStrategyContextHolder serviceStrategyContextHolder;
@Override
protected String getVersionValue(Server server) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = serviceStrategyContextHolder.getRequestAttributes();
if (attributes == null) {
String serviceId = server.getMetaInfo().getAppName().toLowerCase();
......@@ -37,7 +41,7 @@ public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdap
@Override
protected String getRegionValue(Server server) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = serviceStrategyContextHolder.getRequestAttributes();
if (attributes == null) {
String serviceId = server.getMetaInfo().getAppName().toLowerCase();
......
......@@ -18,14 +18,19 @@ import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContextHolder;
public class FeignStrategyInterceptor implements RequestInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(FeignStrategyInterceptor.class);
private String requestHeaders;
@Autowired
private ServiceStrategyContextHolder serviceStrategyContextHolder;
public FeignStrategyInterceptor(String requestHeaders) {
this.requestHeaders = requestHeaders.toLowerCase();
......@@ -36,7 +41,7 @@ public class FeignStrategyInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = serviceStrategyContextHolder.getRequestAttributes();
if (attributes == null) {
return;
}
......
......@@ -16,19 +16,24 @@ import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContextHolder;
public class RestTemplateStrategyInterceptor implements ClientHttpRequestInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(RestTemplateStrategyInterceptor.class);
private String requestHeaders;
@Autowired
private ServiceStrategyContextHolder serviceStrategyContextHolder;
public RestTemplateStrategyInterceptor(String requestHeaders) {
this.requestHeaders = requestHeaders.toLowerCase();
......@@ -39,7 +44,7 @@ public class RestTemplateStrategyInterceptor implements ClientHttpRequestInterce
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = serviceStrategyContextHolder.getRequestAttributes();
if (attributes == null) {
return execution.execute(request, body);
}
......
......@@ -28,6 +28,7 @@ import com.nepxion.discovery.plugin.strategy.service.aop.RestTemplateStrategyInt
import com.nepxion.discovery.plugin.strategy.service.aop.ServiceStrategyAutoScanProxy;
import com.nepxion.discovery.plugin.strategy.service.aop.ServiceStrategyInterceptor;
import com.nepxion.discovery.plugin.strategy.service.constant.ServiceStrategyConstant;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContextHolder;
@Configuration
@AutoConfigureBefore(RibbonClientConfiguration.class)
......@@ -93,4 +94,9 @@ public class ServiceStrategyAutoConfiguration {
public DiscoveryEnabledAdapter discoveryEnabledAdapter() {
return new DefaultDiscoveryEnabledAdapter();
}
@Bean
public ServiceStrategyContextHolder serviceStrategyContextHolder() {
return new ServiceStrategyContextHolder();
}
}
\ No newline at end of file
package com.nepxion.discovery.plugin.strategy.service.context;
import java.util.Map;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @version 1.0
*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant;
public class ServiceStrategyContextHolder {
@Autowired
private ConfigurableEnvironment environment;
public ServletRequestAttributes getRequestAttributes() {
Boolean hystrixThreadlocalSupported = environment.getProperty(StrategyConstant.SPRING_APPLICATION_STRATEGY_HYSTRIX_THREADLOCAL_SUPPORTED, Boolean.class, Boolean.FALSE);
if (hystrixThreadlocalSupported) {
// 服务端使用Hystrix做线程模式的服务隔离时,实现服务灰度路由的功能,预留待实现
return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
} else {
return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
}
}
public Map<String, Object> getMethodAttributes() {
return ServiceStrategyContext.getCurrentContext().getAttributes();
}
}
\ No newline at end of file
......@@ -10,6 +10,7 @@ package com.nepxion.discovery.plugin.strategy.zuul.configuration;
*/
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
import org.springframework.context.annotation.Bean;
......@@ -27,6 +28,7 @@ import com.nepxion.discovery.plugin.strategy.zuul.wrapper.DefaultCallableWrapper
@ConditionalOnProperty(value = StrategyConstant.SPRING_APPLICATION_STRATEGY_CONTROL_ENABLED, matchIfMissing = true)
public class ZuulStrategyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DiscoveryEnabledAdapter discoveryEnabledAdapter() {
return new DefaultDiscoveryEnabledAdapter();
}
......
......@@ -14,19 +14,22 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.nepxion.discovery.common.constant.DiscoveryConstant;
import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledStrategy;
import com.nepxion.discovery.plugin.strategy.service.constant.ServiceStrategyConstant;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContext;
import com.nepxion.discovery.plugin.strategy.service.context.ServiceStrategyContextHolder;
import com.netflix.loadbalancer.Server;
// 实现了组合策略,版本路由策略+区域路由策略+自定义策略
public class MyDiscoveryEnabledStrategy implements DiscoveryEnabledStrategy {
private static final Logger LOG = LoggerFactory.getLogger(MyDiscoveryEnabledStrategy.class);
@Autowired
private ServiceStrategyContextHolder serviceStrategyContextHolder;
@Override
public boolean apply(Server server, Map<String, String> metadata) {
// 对Rest调用传来的Header参数(例如Token)做策略
......@@ -41,7 +44,7 @@ public class MyDiscoveryEnabledStrategy implements DiscoveryEnabledStrategy {
// 根据Rest调用传来的Header参数(例如Token),选取执行调用请求的服务实例
private boolean applyFromHeader(Server server, Map<String, String> metadata) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = serviceStrategyContextHolder.getRequestAttributes();
if (attributes == null) {
return true;
}
......@@ -67,13 +70,12 @@ public class MyDiscoveryEnabledStrategy implements DiscoveryEnabledStrategy {
// 根据RPC调用传来的方法参数(例如接口名、方法名、参数名或参数值等),选取执行调用请求的服务实例
@SuppressWarnings("unchecked")
private boolean applyFromMethod(Server server, Map<String, String> metadata) {
ServiceStrategyContext context = ServiceStrategyContext.getCurrentContext();
Map<String, Object> attributes = context.getAttributes();
Map<String, Object> attributes = serviceStrategyContextHolder.getMethodAttributes();
String serviceId = server.getMetaInfo().getAppName().toLowerCase();
String version = metadata.get(DiscoveryConstant.VERSION);
LOG.info("Serivice端负载均衡用户定制触发:serviceId={}, host={}, metadata={}, context={}", serviceId, server.toString(), metadata, context);
LOG.info("Serivice端负载均衡用户定制触发:serviceId={}, host={}, metadata={}", serviceId, server.toString(), metadata);
String filterServiceId = "discovery-springcloud-example-b";
String filterVersion = "1.0";
......
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