Commit 1df28dcc by Nepxion

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

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