parent
9bb6bcb9cb
commit
23bbf26db7
@ -1,12 +1,14 @@ |
||||
package com.gitee.sop.bridge; |
||||
|
||||
import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Import; |
||||
|
||||
/** |
||||
* https://blog.csdn.net/seashouwang/article/details/80299571
|
||||
* @author tanghc |
||||
*/ |
||||
@Configuration |
||||
@Import(AlipayGatewayConfiguration.class) |
||||
public class SopGatewayAutoConfiguration { |
||||
} |
||||
|
@ -0,0 +1,10 @@ |
||||
package com.gitee.sop.gatewaycommon.bean; |
||||
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public interface ApiParamAware<T> { |
||||
ApiParam getApiParam(T t); |
||||
} |
@ -0,0 +1,32 @@ |
||||
package com.gitee.sop.gatewaycommon.gateway.filter; |
||||
|
||||
import com.gitee.sop.gatewaycommon.gateway.loadbalancer.SopLoadBalancerClient; |
||||
import org.springframework.cloud.client.ServiceInstance; |
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; |
||||
import org.springframework.cloud.gateway.config.LoadBalancerProperties; |
||||
import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
|
||||
import java.net.URI; |
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; |
||||
|
||||
/** |
||||
* 扩展负载均衡过滤器 |
||||
* @author tanghc |
||||
*/ |
||||
public class SopLoadBalancerClientFilter extends LoadBalancerClientFilter { |
||||
public SopLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) { |
||||
super(loadBalancer, properties); |
||||
} |
||||
|
||||
@Override |
||||
protected ServiceInstance choose(ServerWebExchange exchange) { |
||||
if (loadBalancer instanceof SopLoadBalancerClient) { |
||||
SopLoadBalancerClient sopLoadBalancerClient = (SopLoadBalancerClient)loadBalancer; |
||||
return sopLoadBalancerClient.choose(((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(), exchange); |
||||
} else { |
||||
return super.choose(exchange); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,29 @@ |
||||
package com.gitee.sop.gatewaycommon.gateway.loadbalancer; |
||||
|
||||
import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; |
||||
import com.gitee.sop.gatewaycommon.loadbalancer.LoadBalanceServerChooser; |
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
import org.springframework.cloud.client.ServiceInstance; |
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class GatewayLoadBalanceServerChooser extends LoadBalanceServerChooser<ServerWebExchange, ServiceInstance> { |
||||
|
||||
public GatewayLoadBalanceServerChooser(SpringClientFactory clientFactory) { |
||||
this.setClientFactory(clientFactory); |
||||
} |
||||
|
||||
@Override |
||||
public String getHost(ServerWebExchange exchange) { |
||||
return exchange.getRequest().getURI().getHost(); |
||||
} |
||||
|
||||
@Override |
||||
public ApiParam getApiParam(ServerWebExchange exchange) { |
||||
return ServerWebExchangeUtil.getApiParam(exchange); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,23 @@ |
||||
package com.gitee.sop.gatewaycommon.gateway.loadbalancer; |
||||
|
||||
import com.netflix.loadbalancer.Server; |
||||
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer; |
||||
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class NacosServerIntrospector extends DefaultServerIntrospector { |
||||
|
||||
@Override |
||||
public Map<String, String> getMetadata(Server server) { |
||||
if (server instanceof NacosServer) { |
||||
NacosServer discoveryServer = (NacosServer)server; |
||||
return discoveryServer.getInstance().getMetadata(); |
||||
} else { |
||||
return super.getMetadata(server); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,107 @@ |
||||
package com.gitee.sop.gatewaycommon.gateway.loadbalancer; |
||||
|
||||
import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; |
||||
import com.gitee.sop.gatewaycommon.loadbalancer.ServerChooserContext; |
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
import com.netflix.client.config.IClientConfig; |
||||
import com.netflix.loadbalancer.Server; |
||||
import org.springframework.cloud.client.ServiceInstance; |
||||
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; |
||||
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient; |
||||
import org.springframework.cloud.netflix.ribbon.RibbonUtils; |
||||
import org.springframework.cloud.netflix.ribbon.ServerIntrospector; |
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
|
||||
import java.util.List; |
||||
import java.util.concurrent.ThreadLocalRandom; |
||||
|
||||
/** |
||||
* 重写负载均衡处理。 |
||||
* 默认使用的是RibbonLoadBalancerClient类,详见org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration#loadBalancerClient() |
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
public class SopLoadBalancerClient extends RibbonLoadBalancerClient implements ServerChooserContext<ServerWebExchange> { |
||||
|
||||
private final SpringClientFactory clientFactory; |
||||
private GatewayLoadBalanceServerChooser loadBalanceServerChooser; |
||||
|
||||
public SopLoadBalancerClient(SpringClientFactory clientFactory) { |
||||
super(clientFactory); |
||||
this.clientFactory = clientFactory; |
||||
this.loadBalanceServerChooser = new GatewayLoadBalanceServerChooser(clientFactory); |
||||
} |
||||
|
||||
/** |
||||
* New: Select a server using a 'key'. |
||||
*/ |
||||
@Override |
||||
public ServiceInstance choose(String serviceId, Object hint) { |
||||
return loadBalanceServerChooser.choose( |
||||
serviceId |
||||
, (ServerWebExchange) hint |
||||
, this.getLoadBalancer(serviceId) |
||||
, () -> super.choose(serviceId, hint) |
||||
, (servers) -> getRibbonServer(serviceId, servers) |
||||
); |
||||
} |
||||
|
||||
@Override |
||||
public ApiParam getApiParam(ServerWebExchange exchange) { |
||||
return ServerWebExchangeUtil.getApiParam(exchange); |
||||
} |
||||
|
||||
@Override |
||||
public String getHost(ServerWebExchange exchange) { |
||||
return exchange.getRequest().getURI().getHost(); |
||||
} |
||||
|
||||
private RibbonServer getRibbonServer(String serviceId, List<Server> servers) { |
||||
Server server = this.chooseRandomServer(servers); |
||||
if (server == null) { |
||||
return null; |
||||
} |
||||
return new RibbonServer( |
||||
serviceId |
||||
, server |
||||
, isSecure(server, serviceId) |
||||
, serverIntrospector(serviceId).getMetadata(server) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* 随机选取一台实例 |
||||
* |
||||
* @param servers 服务列表 |
||||
* @return 返回实例,没有返回null |
||||
*/ |
||||
private Server chooseRandomServer(List<Server> servers) { |
||||
if (servers.isEmpty()) { |
||||
return null; |
||||
} |
||||
int serverCount = servers.size(); |
||||
// 随机选取一台实例
|
||||
int index = chooseRandomInt(serverCount); |
||||
return servers.get(index); |
||||
} |
||||
|
||||
private int chooseRandomInt(int serverCount) { |
||||
return ThreadLocalRandom.current().nextInt(serverCount); |
||||
} |
||||
|
||||
private ServerIntrospector serverIntrospector(String serviceId) { |
||||
ServerIntrospector serverIntrospector = this.clientFactory.getInstance(serviceId, |
||||
ServerIntrospector.class); |
||||
if (serverIntrospector == null) { |
||||
serverIntrospector = new DefaultServerIntrospector(); |
||||
} |
||||
return serverIntrospector; |
||||
} |
||||
|
||||
private boolean isSecure(Server server, String serviceId) { |
||||
IClientConfig config = this.clientFactory.getClientConfig(serviceId); |
||||
ServerIntrospector serverIntrospector = serverIntrospector(serviceId); |
||||
return RibbonUtils.isSecure(config, serverIntrospector, server); |
||||
} |
||||
} |
@ -1,64 +0,0 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer; |
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.SpringContext; |
||||
import com.gitee.sop.gatewaycommon.zuul.loadbalancer.BaseServerChooser; |
||||
import com.netflix.loadbalancer.Server; |
||||
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer; |
||||
import org.springframework.core.env.Environment; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 预发布、灰度环境选择,参考自:https://segmentfault.com/a/1190000017412946
|
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
public class EnvironmentServerChooser extends BaseServerChooser { |
||||
|
||||
private static final String MEDATA_KEY_ENV = "env"; |
||||
private static final String ENV_PRE_VALUE = "pre"; |
||||
private static final String ENV_GRAY_VALUE = "gray"; |
||||
|
||||
/** |
||||
* 预发布机器域名 |
||||
*/ |
||||
private static final String PRE_DOMAIN = "localhost"; |
||||
|
||||
@Override |
||||
protected boolean isPreServer(Server server) { |
||||
String env = getEnvValue(server); |
||||
return ENV_PRE_VALUE.equals(env); |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isGrayServer(Server server) { |
||||
String env = getEnvValue(server); |
||||
return ENV_GRAY_VALUE.equals(env); |
||||
} |
||||
|
||||
private String getEnvValue(Server server) { |
||||
// eureka存储的metadata
|
||||
Map<String, String> metadata = getMetada(server); |
||||
return metadata.get(MEDATA_KEY_ENV); |
||||
} |
||||
|
||||
protected Map<String, String> getMetada(Server server) { |
||||
return ((NacosServer) server).getMetadata(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 通过判断hostname来确定是否是预发布请求,可修改此方法实现自己想要的 |
||||
* |
||||
* @param request request |
||||
* @return 返回true:可以进入到预发环境 |
||||
*/ |
||||
@Override |
||||
protected boolean canVisitPre(Server server, HttpServletRequest request) { |
||||
String serverName = request.getServerName(); |
||||
String domain = SpringContext.getBean(Environment.class).getProperty("pre.domain", PRE_DOMAIN); |
||||
return domain.equals(serverName); |
||||
} |
||||
|
||||
} |
@ -1,16 +0,0 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer; |
||||
|
||||
import com.netflix.loadbalancer.Server; |
||||
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class EurekaEnvironmentServerChooser extends EnvironmentServerChooser { |
||||
@Override |
||||
protected Map<String, String> getMetada(Server server) { |
||||
return ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata(); |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class LoadBalanceConfig { |
||||
|
||||
} |
@ -0,0 +1,127 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer; |
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.SopConstants; |
||||
import com.gitee.sop.gatewaycommon.bean.SpringContext; |
||||
import com.netflix.loadbalancer.ILoadBalancer; |
||||
import com.netflix.loadbalancer.Server; |
||||
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; |
||||
import org.springframework.cloud.netflix.ribbon.ServerIntrospector; |
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Objects; |
||||
import java.util.function.Function; |
||||
import java.util.function.Supplier; |
||||
|
||||
/** |
||||
* 预发布、灰度发布服务器选择 |
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
public abstract class LoadBalanceServerChooser<T, R> implements ServerChooserContext<T> { |
||||
|
||||
private SpringClientFactory clientFactory; |
||||
|
||||
/** |
||||
* 选择服务器 |
||||
* |
||||
* @param serviceId serviceId,仅gateway网关有作用 |
||||
* @param exchange 请求上下文 |
||||
* @param loadBalancer loadBalancer |
||||
* @param superChooser 父类默认的选择 |
||||
* @param serverChooserFunction 执行选择操作 |
||||
* @return 返回服务器实例 |
||||
*/ |
||||
public R choose( |
||||
String serviceId |
||||
, T exchange |
||||
, ILoadBalancer loadBalancer |
||||
, Supplier<R> superChooser |
||||
, Function<List<Server>, R> serverChooserFunction) { |
||||
// 获取所有服务实例
|
||||
List<Server> servers = loadBalancer.getReachableServers(); |
||||
|
||||
// 存放预发服务器
|
||||
List<Server> preServers = new ArrayList<>(4); |
||||
// 存放灰度发布服务器
|
||||
List<Server> grayServers = new ArrayList<>(4); |
||||
// 存放非预发服务器
|
||||
List<Server> notPreServers = new ArrayList<>(4); |
||||
|
||||
for (Server server : servers) { |
||||
// 获取实例metadata
|
||||
Map<String, String> metadata = getMetadata(serviceId, server); |
||||
// 是否开启了预发模式
|
||||
if (this.isPreServer(metadata)) { |
||||
preServers.add(server); |
||||
} else if (this.isGrayServer(metadata)) { |
||||
grayServers.add(server); |
||||
} else { |
||||
notPreServers.add(server); |
||||
} |
||||
} |
||||
notPreServers.addAll(grayServers); |
||||
// 如果没有开启预发布服务和灰度发布,直接用默认的方式
|
||||
if (preServers.isEmpty() && grayServers.isEmpty()) { |
||||
return superChooser.get(); |
||||
} |
||||
// 如果是从预发布域名访问过来,则认为是预发布请求
|
||||
if (this.isRequestFromPreDomain(exchange)) { |
||||
return serverChooserFunction.apply(preServers); |
||||
} |
||||
// 如果是灰度请求
|
||||
if (this.isRequestGrayServer(exchange)) { |
||||
return serverChooserFunction.apply(grayServers); |
||||
} |
||||
|
||||
// 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器
|
||||
return serverChooserFunction.apply(notPreServers); |
||||
} |
||||
|
||||
protected Map<String, String> getMetadata(String serviceId, Server server) { |
||||
return serverIntrospector(serviceId).getMetadata(server); |
||||
} |
||||
|
||||
protected SpringClientFactory getSpringClientFactory() { |
||||
if (clientFactory == null) { |
||||
clientFactory = SpringContext.getBean(SpringClientFactory.class); |
||||
} |
||||
return clientFactory; |
||||
} |
||||
|
||||
public void setClientFactory(SpringClientFactory clientFactory) { |
||||
this.clientFactory = clientFactory; |
||||
} |
||||
|
||||
private ServerIntrospector serverIntrospector(String serviceId) { |
||||
ServerIntrospector serverIntrospector = getSpringClientFactory().getInstance(serviceId, |
||||
ServerIntrospector.class); |
||||
if (serverIntrospector == null) { |
||||
serverIntrospector = new DefaultServerIntrospector(); |
||||
} |
||||
return serverIntrospector; |
||||
} |
||||
|
||||
/** |
||||
* 是否是预发布服务器 |
||||
* |
||||
* @param metadata metadata |
||||
* @return true:是 |
||||
*/ |
||||
private boolean isPreServer(Map<String, String> metadata) { |
||||
return Objects.equals(metadata.get(SopConstants.METADATA_ENV_KEY), SopConstants.METADATA_ENV_PRE_VALUE); |
||||
} |
||||
|
||||
/** |
||||
* 是否是灰度发布服务器 |
||||
* |
||||
* @param metadata metadata |
||||
* @return true:是 |
||||
*/ |
||||
private boolean isGrayServer(Map<String, String> metadata) { |
||||
return Objects.equals(metadata.get(SopConstants.METADATA_ENV_KEY), SopConstants.METADATA_ENV_GRAY_VALUE); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,35 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer; |
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiParamAware; |
||||
import com.gitee.sop.gatewaycommon.manager.EnvironmentKeys; |
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
import org.apache.commons.lang.ArrayUtils; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public interface ServerChooserContext<T> extends ApiParamAware<T> { |
||||
|
||||
/** |
||||
* 通过判断hostname来确定是否是预发布请求 |
||||
* |
||||
* @param t t |
||||
* @return 返回true:可以进入到预发环境 |
||||
*/ |
||||
default boolean isRequestFromPreDomain(T t) { |
||||
String domain = EnvironmentKeys.PRE_DOMAIN.getValue(); |
||||
if (StringUtils.isEmpty(domain)) { |
||||
return false; |
||||
} |
||||
String[] domains = domain.split("\\,"); |
||||
return ArrayUtils.contains(domains, getHost(t)); |
||||
} |
||||
|
||||
default boolean isRequestGrayServer(T t) { |
||||
ApiParam apiParam = getApiParam(t); |
||||
return apiParam.isGrayRequest(); |
||||
} |
||||
|
||||
String getHost(T t); |
||||
} |
@ -0,0 +1,19 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer.builder; |
||||
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class AppIdGrayUserBuilder implements GrayUserBuilder { |
||||
|
||||
@Override |
||||
public String buildGrayUserKey(ApiParam apiParam) { |
||||
return apiParam.fetchAppKey(); |
||||
} |
||||
|
||||
@Override |
||||
public int order() { |
||||
return 0; |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer.builder; |
||||
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public interface GrayUserBuilder { |
||||
|
||||
/** |
||||
* 获取灰度用户key |
||||
* |
||||
* @param apiParam apiParam |
||||
* @return 返回用户key |
||||
*/ |
||||
String buildGrayUserKey(ApiParam apiParam); |
||||
|
||||
/** |
||||
* 优先级,数字小优先 |
||||
* |
||||
* @return 返回数字 |
||||
*/ |
||||
int order(); |
||||
} |
@ -0,0 +1,19 @@ |
||||
package com.gitee.sop.gatewaycommon.loadbalancer.builder; |
||||
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class IpGrayUserBuilder implements GrayUserBuilder { |
||||
|
||||
@Override |
||||
public String buildGrayUserKey(ApiParam apiParam) { |
||||
return apiParam.fetchIp(); |
||||
} |
||||
|
||||
@Override |
||||
public int order() { |
||||
return 1; |
||||
} |
||||
} |
@ -1,81 +0,0 @@ |
||||
package com.gitee.sop.gatewaycommon.zuul.loadbalancer; |
||||
|
||||
import com.google.common.base.Optional; |
||||
import com.netflix.loadbalancer.ILoadBalancer; |
||||
import com.netflix.loadbalancer.Server; |
||||
import com.netflix.loadbalancer.ZoneAvoidanceRule; |
||||
import com.netflix.zuul.context.RequestContext; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* 服务实例选择器 |
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
@Slf4j |
||||
public abstract class BaseServerChooser extends ZoneAvoidanceRule { |
||||
|
||||
|
||||
/** |
||||
* 是否是预发布服务器 |
||||
* @param server 服务器 |
||||
* @return true:是 |
||||
*/ |
||||
protected abstract boolean isPreServer(Server server); |
||||
|
||||
/** |
||||
* 是否是灰度发布服务器 |
||||
* @param server 服务器 |
||||
* @return true:是 |
||||
*/ |
||||
protected abstract boolean isGrayServer(Server server); |
||||
|
||||
/** |
||||
* 能否访问预发布 |
||||
* @param server 预发布服务器 |
||||
* @param request request |
||||
* @return true:能 |
||||
*/ |
||||
protected abstract boolean canVisitPre(Server server, HttpServletRequest request); |
||||
|
||||
|
||||
@Override |
||||
public Server choose(Object key) { |
||||
ILoadBalancer lb = getLoadBalancer(); |
||||
// 获取服务实例列表
|
||||
List<Server> allServers = lb.getAllServers(); |
||||
HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); |
||||
|
||||
List<Server> preServers = allServers.stream() |
||||
.filter(this::isPreServer) |
||||
.filter(server -> canVisitPre(server, request)) |
||||
.collect(Collectors.toList()); |
||||
|
||||
if (!preServers.isEmpty()) { |
||||
return this.doChoose(preServers, key); |
||||
} |
||||
|
||||
List<Server> grayServers = allServers.stream() |
||||
.filter(this::isGrayServer) |
||||
.collect(Collectors.toList()); |
||||
if (!grayServers.isEmpty()) { |
||||
return doChoose(grayServers, key); |
||||
} |
||||
|
||||
return super.choose(key); |
||||
} |
||||
|
||||
protected Server doChoose(List<Server> servers, Object key) { |
||||
Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(servers, key); |
||||
if (server.isPresent()) { |
||||
return server.get(); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,55 @@ |
||||
package com.gitee.sop.gatewaycommon.zuul.loadbalancer; |
||||
|
||||
import com.gitee.sop.gatewaycommon.loadbalancer.ServerChooserContext; |
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext; |
||||
import com.google.common.base.Optional; |
||||
import com.netflix.loadbalancer.Server; |
||||
import com.netflix.loadbalancer.ZoneAvoidanceRule; |
||||
import com.netflix.zuul.context.RequestContext; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 预发布、灰度环境选择,参考自:https://segmentfault.com/a/1190000017412946
|
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
@Slf4j |
||||
public class EnvironmentServerChooser extends ZoneAvoidanceRule implements ServerChooserContext<HttpServletRequest> { |
||||
|
||||
private ZuulLoadBalanceServerChooser loadBalanceServerChooser = new ZuulLoadBalanceServerChooser(); |
||||
|
||||
@Override |
||||
public String getHost(HttpServletRequest request) { |
||||
return request.getServerName(); |
||||
} |
||||
|
||||
@Override |
||||
public ApiParam getApiParam(HttpServletRequest request) { |
||||
return ZuulContext.getApiParam(); |
||||
} |
||||
|
||||
@Override |
||||
public Server choose(Object key) { |
||||
return loadBalanceServerChooser.choose( |
||||
String.valueOf(key) |
||||
, RequestContext.getCurrentContext().getRequest() |
||||
, getLoadBalancer() |
||||
, () -> super.choose(key) |
||||
, (servers) -> this.doChoose(servers, key) |
||||
); |
||||
} |
||||
|
||||
protected Server doChoose(List<Server> servers, Object key) { |
||||
Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(servers, key); |
||||
if (server.isPresent()) { |
||||
return server.get(); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,24 @@ |
||||
package com.gitee.sop.gatewaycommon.zuul.loadbalancer; |
||||
|
||||
import com.gitee.sop.gatewaycommon.loadbalancer.LoadBalanceServerChooser; |
||||
import com.gitee.sop.gatewaycommon.param.ApiParam; |
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext; |
||||
import com.netflix.loadbalancer.Server; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class ZuulLoadBalanceServerChooser extends LoadBalanceServerChooser<HttpServletRequest, Server> { |
||||
|
||||
@Override |
||||
public String getHost(HttpServletRequest request) { |
||||
return request.getServerName(); |
||||
} |
||||
|
||||
@Override |
||||
public ApiParam getApiParam(HttpServletRequest request) { |
||||
return ZuulContext.getApiParam(); |
||||
} |
||||
} |
Loading…
Reference in new issue