|
|
|
@ -1,15 +1,20 @@ |
|
|
|
|
package com.gitee.sop.gatewaycommon.zuul.loadbalancer; |
|
|
|
|
|
|
|
|
|
import com.gitee.sop.gatewaycommon.bean.SpringContext; |
|
|
|
|
import com.gitee.sop.gatewaycommon.manager.EnvGrayManager; |
|
|
|
|
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 org.apache.commons.lang.ArrayUtils; |
|
|
|
|
import org.springframework.core.env.Environment; |
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 服务实例选择器 |
|
|
|
@ -47,26 +52,64 @@ public abstract class BaseServerChooser extends ZoneAvoidanceRule { |
|
|
|
|
public Server choose(Object key) { |
|
|
|
|
ILoadBalancer lb = getLoadBalancer(); |
|
|
|
|
// 获取服务实例列表
|
|
|
|
|
List<Server> allServers = lb.getAllServers(); |
|
|
|
|
HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); |
|
|
|
|
List<Server> servers = lb.getReachableServers(); |
|
|
|
|
RequestContext currentContext = RequestContext.getCurrentContext(); |
|
|
|
|
// 存放预发服务器
|
|
|
|
|
List<Server> preServers = new ArrayList<>(4); |
|
|
|
|
// 存放灰度发布服务器
|
|
|
|
|
List<Server> grayServers = new ArrayList<>(4); |
|
|
|
|
// 存放非预发服务器
|
|
|
|
|
List<Server> notPreServers = new ArrayList<>(4); |
|
|
|
|
|
|
|
|
|
List<Server> preServers = allServers.stream() |
|
|
|
|
.filter(this::isPreServer) |
|
|
|
|
.filter(server -> canVisitPre(server, request)) |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
|
|
|
|
|
if (!preServers.isEmpty()) { |
|
|
|
|
return this.doChoose(preServers, key); |
|
|
|
|
for (Server server : servers) { |
|
|
|
|
// 是否开启了预发模式
|
|
|
|
|
if (this.isPreServer(server)) { |
|
|
|
|
preServers.add(server); |
|
|
|
|
} else if (this.isGrayServer(server)) { |
|
|
|
|
grayServers.add(server); |
|
|
|
|
} else { |
|
|
|
|
notPreServers.add(server); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<Server> grayServers = allServers.stream() |
|
|
|
|
.filter(this::isGrayServer) |
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
if (!grayServers.isEmpty()) { |
|
|
|
|
notPreServers.addAll(grayServers); |
|
|
|
|
// 如果没有开启预发布服务和灰度发布,直接用默认的方式
|
|
|
|
|
if (preServers.isEmpty() && grayServers.isEmpty()) { |
|
|
|
|
return super.choose(key); |
|
|
|
|
} |
|
|
|
|
// 如果是从预发布域名访问过来,则认为是预发布请求
|
|
|
|
|
if (this.isRequestFromPreDomain(currentContext.getRequest())) { |
|
|
|
|
return doChoose(preServers, key); |
|
|
|
|
} |
|
|
|
|
// 如果是灰度请求
|
|
|
|
|
if (this.isRequestGrayServer(currentContext)) { |
|
|
|
|
return doChoose(grayServers, key); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return super.choose(key); |
|
|
|
|
// 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器
|
|
|
|
|
return doChoose(notPreServers, key); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 通过判断hostname来确定是否是预发布请求 |
|
|
|
|
* |
|
|
|
|
* @param t t |
|
|
|
|
* @return 返回true:可以进入到预发环境 |
|
|
|
|
*/ |
|
|
|
|
protected boolean isRequestFromPreDomain(HttpServletRequest t) { |
|
|
|
|
String domain = SpringContext.getBean(Environment.class).getProperty("pre.domain"); |
|
|
|
|
if (StringUtils.isEmpty(domain)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
String[] domains = domain.split("\\,"); |
|
|
|
|
return ArrayUtils.contains(domains, getHost(t)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected boolean isRequestGrayServer(RequestContext t) { |
|
|
|
|
return t.get(EnvGrayManager.ENV_GRAY) != null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected String getHost(HttpServletRequest t) { |
|
|
|
|
return t.getServerName(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected Server doChoose(List<Server> servers, Object key) { |
|
|
|
|