Commit 03a1a74b by Neptune Committed by GitHub

Merge pull request #21 from Nepxion/Finchley-Hystrix

Finchley hystrix
parents 5b7f03f5 f9266082
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
@title Nepxion Discovery @title Nepxion Discovery
@color 0a @color 0a
call mvn clean deploy -DskipTests -e -P release -pl discovery-plugin-starter-eureka,discovery-plugin-starter-consul,discovery-plugin-starter-zookeeper,discovery-plugin-config-center-starter-apollo,discovery-plugin-config-center-starter-nacos,discovery-plugin-config-center-starter-redis,discovery-console-starter-apollo,discovery-console-starter-nacos,discovery-console-starter-redis,discovery-plugin-strategy-starter-service,discovery-plugin-strategy-starter-zuul,discovery-plugin-strategy-starter-gateway -am call mvn clean deploy -DskipTests -e -P release -pl discovery-plugin-starter-eureka,discovery-plugin-starter-consul,discovery-plugin-starter-zookeeper,discovery-plugin-config-center-starter-apollo,discovery-plugin-config-center-starter-nacos,discovery-plugin-config-center-starter-redis,discovery-console-starter-apollo,discovery-console-starter-nacos,discovery-console-starter-redis,discovery-plugin-strategy-starter-service,discovery-plugin-strategy-starter-zuul,discovery-plugin-strategy-starter-gateway,discovery-plugin-strategy-starter-hystrix -am
pause pause
\ No newline at end of file
...@@ -9,19 +9,30 @@ package com.nepxion.discovery.plugin.strategy.gateway.adapter; ...@@ -9,19 +9,30 @@ package com.nepxion.discovery.plugin.strategy.gateway.adapter;
* @version 1.0 * @version 1.0
*/ */
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
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.gateway.context.GatewayStrategyContext; import com.nepxion.discovery.plugin.strategy.gateway.context.GatewayStrategyContextHolder;
import com.netflix.loadbalancer.Server;
public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdapter { public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdapter {
@Override private static final Logger LOG = LoggerFactory.getLogger(DefaultDiscoveryEnabledAdapter.class);
protected String getVersionValue() {
GatewayStrategyContext context = GatewayStrategyContext.getCurrentContext(); @Autowired
private GatewayStrategyContextHolder gatewayStrategyContextHolder;
ServerWebExchange exchange = context.getExchange(); @Override
protected String getVersionValue(Server server) {
ServerWebExchange exchange = gatewayStrategyContextHolder.getExchange();
if (exchange == null) { if (exchange == null) {
String serviceId = server.getMetaInfo().getAppName().toLowerCase();
LOG.warn("The ServerWebExchange object is null, ignore to do version filter for service={}...", serviceId);
return null; return null;
} }
...@@ -29,11 +40,13 @@ public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdap ...@@ -29,11 +40,13 @@ public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdap
} }
@Override @Override
protected String getRegionValue() { protected String getRegionValue(Server server) {
GatewayStrategyContext context = GatewayStrategyContext.getCurrentContext(); ServerWebExchange exchange = gatewayStrategyContextHolder.getExchange();
ServerWebExchange exchange = context.getExchange();
if (exchange == null) { if (exchange == null) {
String serviceId = server.getMetaInfo().getAppName().toLowerCase();
LOG.warn("The ServerWebExchange object is null, ignore to do region filter for service={}...", serviceId);
return null; return null;
} }
......
...@@ -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;
...@@ -18,6 +19,7 @@ import org.springframework.context.annotation.Configuration; ...@@ -18,6 +19,7 @@ import org.springframework.context.annotation.Configuration;
import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledAdapter; import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledAdapter;
import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant; import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant;
import com.nepxion.discovery.plugin.strategy.gateway.adapter.DefaultDiscoveryEnabledAdapter; import com.nepxion.discovery.plugin.strategy.gateway.adapter.DefaultDiscoveryEnabledAdapter;
import com.nepxion.discovery.plugin.strategy.gateway.context.GatewayStrategyContextHolder;
import com.nepxion.discovery.plugin.strategy.gateway.filter.GatewayStrategyFilter; import com.nepxion.discovery.plugin.strategy.gateway.filter.GatewayStrategyFilter;
@Configuration @Configuration
...@@ -30,6 +32,12 @@ public class GatewayStrategyAutoConfiguration { ...@@ -30,6 +32,12 @@ public class GatewayStrategyAutoConfiguration {
} }
@Bean @Bean
public GatewayStrategyContextHolder gatewayStrategyContextHolder() {
return new GatewayStrategyContextHolder();
}
@Bean
@ConditionalOnMissingBean
public DiscoveryEnabledAdapter discoveryEnabledAdapter() { public DiscoveryEnabledAdapter discoveryEnabledAdapter() {
return new DefaultDiscoveryEnabledAdapter(); return new DefaultDiscoveryEnabledAdapter();
} }
......
package com.nepxion.discovery.plugin.strategy.gateway.context;
/**
* <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.server.ServerWebExchange;
import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant;
public class GatewayStrategyContextHolder {
@Autowired
private ConfigurableEnvironment environment;
public ServerWebExchange getExchange() {
Boolean hystrixThreadlocalSupported = environment.getProperty(StrategyConstant.SPRING_APPLICATION_STRATEGY_HYSTRIX_THREADLOCAL_SUPPORTED, Boolean.class, Boolean.FALSE);
if (hystrixThreadlocalSupported) {
// Spring Cloud Gateway网关端使用Hystrix做线程模式的服务隔离时,实现服务灰度路由的功能
return GatewayStrategyContext.getCurrentContext().getExchange();
} else {
return GatewayStrategyContext.getCurrentContext().getExchange();
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<artifactId>discovery-plugin-strategy-starter-hystrix</artifactId>
<name>Nepxion Discovery Plugin Strategy Starter Hystrix</name>
<packaging>jar</packaging>
<modelVersion>4.0.0</modelVersion>
<description>Nepxion Discovery is an enhancement for Spring Cloud Discovery</description>
<url>http://www.nepxion.com</url>
<parent>
<groupId>com.nepxion</groupId>
<artifactId>discovery</artifactId>
<version>4.7.12</version>
</parent>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-plugin-strategy</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.nepxion.discovery.plugin.strategy.hystrix.configuration;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @author Hao Wang
* @version 1.0
*/
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant;
import com.nepxion.discovery.plugin.strategy.hystrix.context.HystrixContextConcurrencyStrategy;
import com.netflix.hystrix.Hystrix;
@Configuration
@ConditionalOnClass(Hystrix.class)
@ConditionalOnProperty(value = StrategyConstant.SPRING_APPLICATION_STRATEGY_HYSTRIX_THREADLOCAL_SUPPORTED, matchIfMissing = false)
public class HystrixStrategyAutoConfiguration {
@Bean
public HystrixContextConcurrencyStrategy hystrixContextConcurrencyStrategy() {
return new HystrixContextConcurrencyStrategy();
}
}
\ No newline at end of file
package com.nepxion.discovery.plugin.strategy.hystrix.context;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @author Hao Wang
* @version 1.0
*/
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import com.nepxion.discovery.plugin.strategy.wrapper.CallableWrapper;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
// 使用线程隔离模式时,无法获取ThreadLocal中信息,自定义并发策略解决
public class HystrixContextConcurrencyStrategy extends HystrixConcurrencyStrategy {
@Autowired
private CallableWrapper wrapper;
private HystrixConcurrencyStrategy delegate;
public HystrixContextConcurrencyStrategy() {
// HystrixPlugins只能注册一次策略,保留原对象
this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
// Keeps references of existing Hystrix plugins.
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy();
HystrixPlugins.reset();
// Registers existing plugins excepts the Concurrent Strategy plugin.
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
}
@Override
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
return delegate.getBlockingQueue(maxQueueSize);
}
@Override
public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
return delegate.getRequestVariable(rv);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize, HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
return delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
return delegate.getThreadPool(threadPoolKey, threadPoolProperties);
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return wrapper.wrapCallable(callable);
}
}
\ No newline at end of file
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.nepxion.discovery.plugin.strategy.hystrix.configuration.HystrixStrategyAutoConfiguration
\ No newline at end of file
...@@ -9,17 +9,30 @@ package com.nepxion.discovery.plugin.strategy.service.adapter; ...@@ -9,17 +9,30 @@ package com.nepxion.discovery.plugin.strategy.service.adapter;
* @version 1.0 * @version 1.0
*/ */
import org.springframework.web.context.request.RequestContextHolder; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdapter { public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdapter {
private static final Logger LOG = LoggerFactory.getLogger(DefaultDiscoveryEnabledAdapter.class);
@Autowired
private ServiceStrategyContextHolder serviceStrategyContextHolder;
@Override @Override
protected String getVersionValue() { 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();
LOG.warn("The ServletRequestAttributes object is null, ignore to do version filter for service={}...", serviceId);
return null; return null;
} }
...@@ -27,9 +40,13 @@ public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdap ...@@ -27,9 +40,13 @@ public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdap
} }
@Override @Override
protected String getRegionValue() { 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();
LOG.warn("The ServletRequestAttributes object is null, ignore to do region filter for service={}...", serviceId);
return null; return null;
} }
......
...@@ -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,13 +41,12 @@ public class FeignStrategyInterceptor implements RequestInterceptor { ...@@ -36,13 +41,12 @@ 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;
} }
HttpServletRequest previousRequest = attributes.getRequest(); HttpServletRequest previousRequest = attributes.getRequest();
Enumeration<String> headerNames = previousRequest.getHeaderNames(); Enumeration<String> headerNames = previousRequest.getHeaderNames();
if (headerNames == null) { if (headerNames == 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,20 +44,18 @@ public class RestTemplateStrategyInterceptor implements ClientHttpRequestInterce ...@@ -39,20 +44,18 @@ 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);
} }
HttpServletRequest previousRequest = attributes.getRequest(); HttpServletRequest previousRequest = attributes.getRequest();
Enumeration<String> headerNames = previousRequest.getHeaderNames(); Enumeration<String> headerNames = previousRequest.getHeaderNames();
if (headerNames == null) { if (headerNames == null) {
return execution.execute(request, body); return execution.execute(request, body);
} }
HttpHeaders headers = request.getHeaders(); HttpHeaders headers = request.getHeaders();
while (headerNames.hasMoreElements()) { while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement(); String headerName = headerNames.nextElement();
String header = previousRequest.getHeader(headerName); String header = previousRequest.getHeader(headerName);
......
...@@ -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
...@@ -9,22 +9,48 @@ package com.nepxion.discovery.plugin.strategy.zuul.adapter; ...@@ -9,22 +9,48 @@ package com.nepxion.discovery.plugin.strategy.zuul.adapter;
* @version 1.0 * @version 1.0
*/ */
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.netflix.zuul.context.RequestContext; import com.nepxion.discovery.plugin.strategy.zuul.context.ZuulStrategyContextHolder;
import com.netflix.loadbalancer.Server;
public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdapter { public class DefaultDiscoveryEnabledAdapter extends AbstractDiscoveryEnabledAdapter {
private static final Logger LOG = LoggerFactory.getLogger(DefaultDiscoveryEnabledAdapter.class);
@Autowired
private ZuulStrategyContextHolder zuulStrategyContextHolder;
@Override @Override
protected String getVersionValue() { protected String getVersionValue(Server server) {
RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = zuulStrategyContextHolder.getRequest();
if (request == null) {
String serviceId = server.getMetaInfo().getAppName().toLowerCase();
return context.getRequest().getHeader(DiscoveryConstant.VERSION); LOG.warn("The HttpServletRequest object is null, ignore to do version filter for service={}...", serviceId);
return null;
}
return request.getHeader(DiscoveryConstant.VERSION);
} }
@Override @Override
protected String getRegionValue() { protected String getRegionValue(Server server) {
RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = zuulStrategyContextHolder.getRequest();
if (request == null) {
String serviceId = server.getMetaInfo().getAppName().toLowerCase();
LOG.warn("The HttpServletRequest object is null, ignore to do region filter for service={}...", serviceId);
return null;
}
return context.getRequest().getHeader(DiscoveryConstant.REGION); return request.getHeader(DiscoveryConstant.REGION);
} }
} }
\ 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;
...@@ -17,14 +18,29 @@ import org.springframework.context.annotation.Configuration; ...@@ -17,14 +18,29 @@ import org.springframework.context.annotation.Configuration;
import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledAdapter; import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledAdapter;
import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant; import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant;
import com.nepxion.discovery.plugin.strategy.wrapper.CallableWrapper;
import com.nepxion.discovery.plugin.strategy.zuul.adapter.DefaultDiscoveryEnabledAdapter; import com.nepxion.discovery.plugin.strategy.zuul.adapter.DefaultDiscoveryEnabledAdapter;
import com.nepxion.discovery.plugin.strategy.zuul.context.ZuulStrategyContextHolder;
import com.nepxion.discovery.plugin.strategy.zuul.wrapper.DefaultCallableWrapper;
@Configuration @Configuration
@AutoConfigureBefore(RibbonClientConfiguration.class) @AutoConfigureBefore(RibbonClientConfiguration.class)
@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();
} }
@Bean
public ZuulStrategyContextHolder zuulStrategyContextHolder() {
return new ZuulStrategyContextHolder();
}
@Bean
@ConditionalOnProperty(value = StrategyConstant.SPRING_APPLICATION_STRATEGY_HYSTRIX_THREADLOCAL_SUPPORTED, matchIfMissing = false)
public CallableWrapper callableWrapper() {
return new DefaultCallableWrapper();
}
} }
\ No newline at end of file
package com.nepxion.discovery.plugin.strategy.zuul.context;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @author Hao Wang
* @version 1.0
*/
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class ZuulStrategyContext {
private static final ThreadLocal<ZuulStrategyContext> THREAD_LOCAL = new InheritableThreadLocal<ZuulStrategyContext>() {
@Override
protected ZuulStrategyContext initialValue() {
return new ZuulStrategyContext();
}
};
public static ZuulStrategyContext getCurrentContext() {
return THREAD_LOCAL.get();
}
public static void clearCurrentContext() {
THREAD_LOCAL.remove();
}
private HttpServletRequest request;
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object object) {
return EqualsBuilder.reflectionEquals(this, object);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}
\ No newline at end of file
package com.nepxion.discovery.plugin.strategy.zuul.context;
/**
* <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 javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import com.nepxion.discovery.plugin.strategy.constant.StrategyConstant;
import com.netflix.zuul.context.RequestContext;
public class ZuulStrategyContextHolder {
@Autowired
private ConfigurableEnvironment environment;
public HttpServletRequest getRequest() {
Boolean hystrixThreadlocalSupported = environment.getProperty(StrategyConstant.SPRING_APPLICATION_STRATEGY_HYSTRIX_THREADLOCAL_SUPPORTED, Boolean.class, Boolean.FALSE);
if (hystrixThreadlocalSupported) {
return ZuulStrategyContext.getCurrentContext().getRequest();
} else {
return RequestContext.getCurrentContext().getRequest();
}
}
}
\ No newline at end of file
package com.nepxion.discovery.plugin.strategy.zuul.wrapper;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @author Hao Wang
* @version 1.0
*/
import java.util.concurrent.Callable;
import javax.servlet.http.HttpServletRequest;
import com.nepxion.discovery.plugin.strategy.wrapper.CallableWrapper;
import com.nepxion.discovery.plugin.strategy.zuul.context.ZuulStrategyContext;
import com.netflix.zuul.context.RequestContext;
public class DefaultCallableWrapper implements CallableWrapper {
@Override
public <T> Callable<T> wrapCallable(Callable<T> delegate) {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
return new Callable<T>() {
@Override
public T call() throws Exception {
try {
ZuulStrategyContext.getCurrentContext().setRequest(request);
return delegate.call();
} finally {
ZuulStrategyContext.clearCurrentContext();
}
}
};
}
}
\ No newline at end of file
...@@ -39,7 +39,7 @@ public abstract class AbstractDiscoveryEnabledAdapter implements DiscoveryEnable ...@@ -39,7 +39,7 @@ public abstract class AbstractDiscoveryEnabledAdapter implements DiscoveryEnable
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private boolean applyVersion(Server server, Map<String, String> metadata) { private boolean applyVersion(Server server, Map<String, String> metadata) {
String versionValue = getVersionValue(); String versionValue = getVersionValue(server);
if (StringUtils.isEmpty(versionValue)) { if (StringUtils.isEmpty(versionValue)) {
return true; return true;
} }
...@@ -64,7 +64,7 @@ public abstract class AbstractDiscoveryEnabledAdapter implements DiscoveryEnable ...@@ -64,7 +64,7 @@ public abstract class AbstractDiscoveryEnabledAdapter implements DiscoveryEnable
} }
private boolean applyRegion(Server server, Map<String, String> metadata) { private boolean applyRegion(Server server, Map<String, String> metadata) {
String regionValue = getRegionValue(); String regionValue = getRegionValue(server);
if (StringUtils.isEmpty(regionValue)) { if (StringUtils.isEmpty(regionValue)) {
return true; return true;
} }
...@@ -89,7 +89,7 @@ public abstract class AbstractDiscoveryEnabledAdapter implements DiscoveryEnable ...@@ -89,7 +89,7 @@ public abstract class AbstractDiscoveryEnabledAdapter implements DiscoveryEnable
return discoveryEnabledStrategy.apply(server, metadata); return discoveryEnabledStrategy.apply(server, metadata);
} }
protected abstract String getVersionValue(); protected abstract String getVersionValue(Server server);
protected abstract String getRegionValue(); protected abstract String getRegionValue(Server server);
} }
\ No newline at end of file
...@@ -12,4 +12,5 @@ package com.nepxion.discovery.plugin.strategy.constant; ...@@ -12,4 +12,5 @@ package com.nepxion.discovery.plugin.strategy.constant;
public class StrategyConstant { public class StrategyConstant {
public static final String SPRING_APPLICATION_STRATEGY_CONTROL_ENABLED = "spring.application.strategy.control.enabled"; public static final String SPRING_APPLICATION_STRATEGY_CONTROL_ENABLED = "spring.application.strategy.control.enabled";
public static final String SPRING_APPLICATION_STRATEGY_ZONE_AVOIDANCE_RULE_ENABLED = "spring.application.strategy.zone.avoidance.rule.enabled"; public static final String SPRING_APPLICATION_STRATEGY_ZONE_AVOIDANCE_RULE_ENABLED = "spring.application.strategy.zone.avoidance.rule.enabled";
public static final String SPRING_APPLICATION_STRATEGY_HYSTRIX_THREADLOCAL_SUPPORTED = "spring.application.strategy.hystrix.threadlocal.supported";
} }
\ No newline at end of file
package com.nepxion.discovery.plugin.strategy.wrapper;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @author Hao Wang
* @version 1.0
*/
import java.util.concurrent.Callable;
public interface CallableWrapper {
<T> Callable<T> wrapCallable(Callable<T> delegate);
}
\ No newline at end of file
...@@ -14,15 +14,20 @@ import java.util.Map; ...@@ -14,15 +14,20 @@ 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.beans.factory.annotation.Autowired;
import org.springframework.web.server.ServerWebExchange;
import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledStrategy; import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledStrategy;
import com.nepxion.discovery.plugin.strategy.gateway.context.GatewayStrategyContext; import com.nepxion.discovery.plugin.strategy.gateway.context.GatewayStrategyContextHolder;
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 GatewayStrategyContextHolder gatewayStrategyContextHolder;
@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)做策略
...@@ -31,13 +36,17 @@ public class MyDiscoveryEnabledStrategy implements DiscoveryEnabledStrategy { ...@@ -31,13 +36,17 @@ 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) {
GatewayStrategyContext context = GatewayStrategyContext.getCurrentContext(); ServerWebExchange exchange = gatewayStrategyContextHolder.getExchange();
String token = context.getExchange().getRequest().getHeaders().getFirst("token"); if (exchange == null) {
// String value = context.getExchange().getRequest().getQueryParams().getFirst("value"); return true;
}
String token = exchange.getRequest().getHeaders().getFirst("token");
// String value = exchange.getRequest().getQueryParams().getFirst("value");
String serviceId = server.getMetaInfo().getAppName().toLowerCase(); String serviceId = server.getMetaInfo().getAppName().toLowerCase();
LOG.info("Gateway端负载均衡用户定制触发:serviceId={}, host={}, metadata={}, context={}", serviceId, server.toString(), metadata, context); LOG.info("Gateway端负载均衡用户定制触发:serviceId={}, host={}, metadata={}", serviceId, server.toString(), metadata);
String filterToken = "abc"; String filterToken = "abc";
if (StringUtils.isNotEmpty(token) && token.contains(filterToken)) { if (StringUtils.isNotEmpty(token) && token.contains(filterToken)) {
......
...@@ -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={}, attributes={}", serviceId, server.toString(), metadata, attributes);
String filterServiceId = "discovery-springcloud-example-b"; String filterServiceId = "discovery-springcloud-example-b";
String filterVersion = "1.0"; String filterVersion = "1.0";
......
...@@ -72,6 +72,12 @@ ...@@ -72,6 +72,12 @@
<artifactId>discovery-plugin-strategy-starter-zuul</artifactId> <artifactId>discovery-plugin-strategy-starter-zuul</artifactId>
</dependency> </dependency>
<!-- Used for zuul hystrix thread isolation -->
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-strategy-starter-hystrix</artifactId>
</dependency>
<dependency> <dependency>
<groupId>de.codecentric</groupId> <groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId> <artifactId>spring-boot-admin-starter-client</artifactId>
......
...@@ -11,18 +11,24 @@ package com.nepxion.discovery.plugin.example.zuul.impl; ...@@ -11,18 +11,24 @@ package com.nepxion.discovery.plugin.example.zuul.impl;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest;
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.beans.factory.annotation.Autowired;
import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledStrategy; import com.nepxion.discovery.plugin.strategy.adapter.DiscoveryEnabledStrategy;
import com.nepxion.discovery.plugin.strategy.zuul.context.ZuulStrategyContextHolder;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import com.netflix.zuul.context.RequestContext;
// 实现了组合策略,版本路由策略+区域路由策略+自定义策略 // 实现了组合策略,版本路由策略+区域路由策略+自定义策略
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 ZuulStrategyContextHolder zuulStrategyContextHolder;
@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)做策略
...@@ -31,13 +37,17 @@ public class MyDiscoveryEnabledStrategy implements DiscoveryEnabledStrategy { ...@@ -31,13 +37,17 @@ 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) {
RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = zuulStrategyContextHolder.getRequest();
String token = context.getRequest().getHeader("token"); if (request == null) {
// String value = context.getRequest().getParameter("value"); return true;
}
String token = request.getHeader("token");
// String value = request.getParameter("value");
String serviceId = server.getMetaInfo().getAppName().toLowerCase(); String serviceId = server.getMetaInfo().getAppName().toLowerCase();
LOG.info("Zuul端负载均衡用户定制触发:serviceId={}, host={}, metadata={}, context={}", serviceId, server.toString(), metadata, context); LOG.info("Zuul端负载均衡用户定制触发:serviceId={}, host={}, metadata={}", serviceId, server.toString(), metadata);
String filterToken = "abc"; String filterToken = "abc";
if (StringUtils.isNotEmpty(token) && token.contains(filterToken)) { if (StringUtils.isNotEmpty(token) && token.contains(filterToken)) {
......
...@@ -71,4 +71,7 @@ spring.boot.admin.url=http://localhost:5555 ...@@ -71,4 +71,7 @@ spring.boot.admin.url=http://localhost:5555
# 开启和关闭策略扩展功能的控制。一旦关闭,用户自定义和编程灰度路由策略功能将失效。缺失则默认为true # 开启和关闭策略扩展功能的控制。一旦关闭,用户自定义和编程灰度路由策略功能将失效。缺失则默认为true
# spring.application.strategy.control.enabled=true # spring.application.strategy.control.enabled=true
# 开启和关闭Ribbon默认的ZoneAvoidanceRule负载均衡策略。一旦关闭,则使用RoundRobin简单轮询负载均衡策略。缺失则默认为true # 开启和关闭Ribbon默认的ZoneAvoidanceRule负载均衡策略。一旦关闭,则使用RoundRobin简单轮询负载均衡策略。缺失则默认为true
# spring.application.strategy.zone.avoidance.rule.enabled=true # spring.application.strategy.zone.avoidance.rule.enabled=true
\ No newline at end of file # 开启Zuul网关上实现Hystrix线程隔离模式做服务隔离时,必须把spring.application.strategy.hystrix.threadlocal.supported设置为true,同时要引入discovery-plugin-strategy-starter-hystrix包,否则线程切换时会发生ThreadLocal上下文对象丢失
# zuul.ribbon-isolation-strategy=thread
# spring.application.strategy.hystrix.threadlocal.supported=true
\ No newline at end of file
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
<module>discovery-plugin-strategy-starter-service</module> <module>discovery-plugin-strategy-starter-service</module>
<module>discovery-plugin-strategy-starter-zuul</module> <module>discovery-plugin-strategy-starter-zuul</module>
<module>discovery-plugin-strategy-starter-gateway</module> <module>discovery-plugin-strategy-starter-gateway</module>
<module>discovery-plugin-strategy-starter-hystrix</module>
<module>discovery-console</module> <module>discovery-console</module>
<module>discovery-console-starter-apollo</module> <module>discovery-console-starter-apollo</module>
<module>discovery-console-starter-nacos</module> <module>discovery-console-starter-nacos</module>
...@@ -187,6 +188,12 @@ ...@@ -187,6 +188,12 @@
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>discovery-plugin-strategy-starter-hystrix</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-console</artifactId> <artifactId>discovery-console</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
......
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