mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-12 07:02:14 +08:00
优化灰度预发布
This commit is contained in:
@@ -8,6 +8,8 @@ import com.gitee.sop.gatewaycommon.zuul.loadbalancer.ServiceGrayConfig;
|
|||||||
*/
|
*/
|
||||||
public interface EnvGrayManager extends BeanInitializer {
|
public interface EnvGrayManager extends BeanInitializer {
|
||||||
|
|
||||||
|
String ENV_GRAY = "sop.env-gray";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存灰度配置
|
* 保存灰度配置
|
||||||
* @param serviceGrayConfig 灰度配置
|
* @param serviceGrayConfig 灰度配置
|
||||||
|
@@ -42,6 +42,7 @@ public class PreEnvGrayFilter extends BaseZuulFilter {
|
|||||||
// 如果服务在灰度阶段,返回一个灰度版本号
|
// 如果服务在灰度阶段,返回一个灰度版本号
|
||||||
String version = envGrayManager.getVersion(serviceId, nameVersion);
|
String version = envGrayManager.getVersion(serviceId, nameVersion);
|
||||||
if (version != null && envGrayManager.containsKey(serviceId, apiParam.fetchAppKey())) {
|
if (version != null && envGrayManager.containsKey(serviceId, apiParam.fetchAppKey())) {
|
||||||
|
requestContext.set(EnvGrayManager.ENV_GRAY, true);
|
||||||
requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, version);
|
requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, version);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@@ -1,15 +1,20 @@
|
|||||||
package com.gitee.sop.gatewaycommon.zuul.loadbalancer;
|
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.google.common.base.Optional;
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
import com.netflix.loadbalancer.ILoadBalancer;
|
||||||
import com.netflix.loadbalancer.Server;
|
import com.netflix.loadbalancer.Server;
|
||||||
import com.netflix.loadbalancer.ZoneAvoidanceRule;
|
import com.netflix.loadbalancer.ZoneAvoidanceRule;
|
||||||
import com.netflix.zuul.context.RequestContext;
|
import com.netflix.zuul.context.RequestContext;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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 javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务实例选择器
|
* 服务实例选择器
|
||||||
@@ -47,26 +52,64 @@ public abstract class BaseServerChooser extends ZoneAvoidanceRule {
|
|||||||
public Server choose(Object key) {
|
public Server choose(Object key) {
|
||||||
ILoadBalancer lb = getLoadBalancer();
|
ILoadBalancer lb = getLoadBalancer();
|
||||||
// 获取服务实例列表
|
// 获取服务实例列表
|
||||||
List<Server> allServers = lb.getAllServers();
|
List<Server> servers = lb.getReachableServers();
|
||||||
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
|
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
|
||||||
|
// 存放预发服务器
|
||||||
|
List<Server> preServers = new ArrayList<>(4);
|
||||||
|
// 存放灰度发布服务器
|
||||||
|
List<Server> grayServers = new ArrayList<>(4);
|
||||||
|
// 存放非预发服务器
|
||||||
|
List<Server> notPreServers = new ArrayList<>(4);
|
||||||
|
|
||||||
List<Server> preServers = allServers.stream()
|
for (Server server : servers) {
|
||||||
.filter(this::isPreServer)
|
// 是否开启了预发模式
|
||||||
.filter(server -> canVisitPre(server, request))
|
if (this.isPreServer(server)) {
|
||||||
.collect(Collectors.toList());
|
preServers.add(server);
|
||||||
|
} else if (this.isGrayServer(server)) {
|
||||||
if (!preServers.isEmpty()) {
|
grayServers.add(server);
|
||||||
return this.doChoose(preServers, key);
|
} else {
|
||||||
|
notPreServers.add(server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
notPreServers.addAll(grayServers);
|
||||||
List<Server> grayServers = allServers.stream()
|
// 如果没有开启预发布服务和灰度发布,直接用默认的方式
|
||||||
.filter(this::isGrayServer)
|
if (preServers.isEmpty() && grayServers.isEmpty()) {
|
||||||
.collect(Collectors.toList());
|
return super.choose(key);
|
||||||
if (!grayServers.isEmpty()) {
|
}
|
||||||
|
// 如果是从预发布域名访问过来,则认为是预发布请求
|
||||||
|
if (this.isRequestFromPreDomain(request)) {
|
||||||
|
return doChoose(preServers, key);
|
||||||
|
}
|
||||||
|
// 如果是灰度请求
|
||||||
|
if (this.isRequestGrayServer(RequestContext.getCurrentContext())) {
|
||||||
return doChoose(grayServers, key);
|
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) {
|
protected Server doChoose(List<Server> servers, Object key) {
|
||||||
|
Reference in New Issue
Block a user