优化灰度预发布

2.x
tanghc 6 years ago
parent 994b486163
commit c1849bcaf3
  1. 2
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvGrayManager.java
  2. 1
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java
  3. 71
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java

@ -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)) {
grayServers.add(server);
} else {
notPreServers.add(server);
}
}
notPreServers.addAll(grayServers);
// 如果没有开启预发布服务和灰度发布,直接用默认的方式
if (preServers.isEmpty() && grayServers.isEmpty()) {
return super.choose(key);
}
// 如果是从预发布域名访问过来,则认为是预发布请求
if (this.isRequestFromPreDomain(request)) {
return doChoose(preServers, key);
}
// 如果是灰度请求
if (this.isRequestGrayServer(RequestContext.getCurrentContext())) {
return doChoose(grayServers, key);
}
if (!preServers.isEmpty()) { // 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器
return this.doChoose(preServers, key); return doChoose(notPreServers, key);
} }
List<Server> grayServers = allServers.stream() /**
.filter(this::isGrayServer) * 通过判断hostname来确定是否是预发布请求
.collect(Collectors.toList()); *
if (!grayServers.isEmpty()) { * @param t t
return doChoose(grayServers, key); * @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));
} }
return super.choose(key); 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) {

Loading…
Cancel
Save