mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
支持预发布、灰度发布
This commit is contained in:
@@ -11,35 +11,29 @@ import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:config_gray_userkey
|
||||
* 备注:灰度发布用户key
|
||||
* 表名:config_gray
|
||||
* 备注:服务灰度配置
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "config_gray_userkey")
|
||||
@Table(name = "config_gray")
|
||||
@Data
|
||||
public class ConfigGrayUserkey {
|
||||
public class ConfigGray {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** serviceId, 数据库字段:service_id */
|
||||
/** 数据库字段:service_id */
|
||||
private String serviceId;
|
||||
|
||||
/** instanceId, 数据库字段:instance_id */
|
||||
private String instanceId;
|
||||
|
||||
/** 用户key,多个用引文逗号隔开, 数据库字段:user_key_content */
|
||||
private String userKeyContent;
|
||||
|
||||
/** 需要灰度的接口,goods.get=1.2,order.list=1.2, 数据库字段:name_version_content */
|
||||
/** 需要灰度的接口,goods.get1.0=1.2,多个用英文逗号隔开, 数据库字段:name_version_content */
|
||||
private String nameVersionContent;
|
||||
|
||||
/** 0:禁用,1:启用, 数据库字段:status */
|
||||
private Byte status;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
@@ -0,0 +1,41 @@
|
||||
package com.gitee.sop.gateway.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:config_gray_instance
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "config_gray_instance")
|
||||
@Data
|
||||
public class ConfigGrayInstance {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** instance_id, 数据库字段:instance_id */
|
||||
private String instanceId;
|
||||
|
||||
/** service_id, 数据库字段:service_id */
|
||||
private String serviceId;
|
||||
|
||||
/** 0:禁用,1:启用, 数据库字段:status */
|
||||
private Byte status;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -2,12 +2,11 @@ package com.gitee.sop.gateway.loadbalancer;
|
||||
|
||||
import com.gitee.sop.gateway.manager.DbEnvGrayManager;
|
||||
import com.gitee.sop.gatewaycommon.bean.SpringContext;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.param.Param;
|
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||
import com.gitee.sop.gatewaycommon.zuul.loadbalancer.BaseServerChooser;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
@@ -56,22 +55,10 @@ public class EnvironmentServerChooser extends BaseServerChooser {
|
||||
@Override
|
||||
protected boolean canVisitPre(Server server, HttpServletRequest request) {
|
||||
String serverName = request.getServerName();
|
||||
return PRE_DOMAIN.equals(serverName);
|
||||
String domain = SpringContext.getBean(Environment.class).getProperty("pre.domain", PRE_DOMAIN);
|
||||
return domain.equals(serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 能否进入灰度环境
|
||||
*
|
||||
* @param request request
|
||||
* @return 返回true:可以进入到预发环境
|
||||
*/
|
||||
protected boolean canVisitGray(Server server, HttpServletRequest request) {
|
||||
ApiParam apiParam = ZuulContext.getApiParam();
|
||||
DbEnvGrayManager userKeyManager = SpringContext.getBean(DbEnvGrayManager.class);
|
||||
return this.isGrayUser(apiParam, userKeyManager, server, request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否是灰度用户,可修改此方法实现自己想要的
|
||||
*
|
||||
|
@@ -2,13 +2,16 @@ package com.gitee.sop.gateway.manager;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.gateway.entity.ConfigGrayUserkey;
|
||||
import com.gitee.sop.gateway.mapper.ConfigGrayUserkeyMapper;
|
||||
import com.gitee.sop.gateway.entity.ConfigGray;
|
||||
import com.gitee.sop.gateway.entity.ConfigGrayInstance;
|
||||
import com.gitee.sop.gateway.mapper.ConfigGrayInstanceMapper;
|
||||
import com.gitee.sop.gateway.mapper.ConfigGrayMapper;
|
||||
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
|
||||
import com.gitee.sop.gatewaycommon.bean.UserKeyDefinition;
|
||||
import com.gitee.sop.gatewaycommon.bean.ServiceGrayDefinition;
|
||||
import com.gitee.sop.gatewaycommon.manager.DefaultEnvGrayManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
|
||||
import com.gitee.sop.gatewaycommon.zuul.loadbalancer.ServiceGrayConfig;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -19,6 +22,8 @@ import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -33,82 +38,86 @@ public class DbEnvGrayManager extends DefaultEnvGrayManager {
|
||||
|
||||
private static final int STATUS_ENABLE = 1;
|
||||
|
||||
private static final Function<String[], String> FUNCTION_KEY = arr -> arr[0];
|
||||
private static final Function<String[], String> FUNCTION_VALUE = arr -> arr[1];
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Autowired
|
||||
private ConfigGrayUserkeyMapper configGrayUserkeyMapper;
|
||||
private ConfigGrayMapper configGrayMapper;
|
||||
|
||||
@Autowired
|
||||
private ConfigGrayInstanceMapper configGrayInstanceMapper;
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
|
||||
List<ConfigGray> list = configGrayMapper.list(new Query());
|
||||
for (ConfigGray configGray : list) {
|
||||
this.setServiceGrayConfig(configGray);
|
||||
}
|
||||
|
||||
Query query = new Query();
|
||||
query.eq("status", STATUS_ENABLE);
|
||||
List<ConfigGrayUserkey> list = configGrayUserkeyMapper.list(query);
|
||||
for (ConfigGrayUserkey configGrayUserkey : list) {
|
||||
this.setServiceGrayConfig(configGrayUserkey);
|
||||
List<ConfigGrayInstance> grayInstanceList = configGrayInstanceMapper.list(query);
|
||||
for (ConfigGrayInstance configGrayInstance : grayInstanceList) {
|
||||
this.openGray(configGrayInstance.getInstanceId(), configGrayInstance.getServiceId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户key
|
||||
*
|
||||
* @param configGrayUserkey 灰度配置
|
||||
* @param configGray 灰度配置
|
||||
*/
|
||||
public void setServiceGrayConfig(ConfigGrayUserkey configGrayUserkey) {
|
||||
if (configGrayUserkey == null) {
|
||||
public void setServiceGrayConfig(ConfigGray configGray) {
|
||||
if (configGray == null) {
|
||||
return;
|
||||
}
|
||||
String instanceId = configGrayUserkey.getInstanceId();
|
||||
this.clear(instanceId);
|
||||
String userKeyData = configGrayUserkey.getUserKeyContent();
|
||||
String nameVersionContent = configGrayUserkey.getNameVersionContent();
|
||||
String userKeyData = configGray.getUserKeyContent();
|
||||
String nameVersionContent = configGray.getNameVersionContent();
|
||||
String[] userKeys = StringUtils.split(userKeyData, ',');
|
||||
String[] nameVersionList = StringUtils.split(nameVersionContent, ',');
|
||||
log.info("添加userKey,userKeys.length:{}, nameVersionList:{}", userKeys.length, Arrays.toString(nameVersionList));
|
||||
log.info("灰度配置,userKeys.length:{}, nameVersionList:{}", userKeys.length, Arrays.toString(nameVersionList));
|
||||
|
||||
List<String> list = Stream.of(userKeys).collect(Collectors.toList());
|
||||
ServiceGrayConfig serviceGrayConfig = getServiceGrayConfig(instanceId);
|
||||
serviceGrayConfig.setServiceId(configGrayUserkey.getServiceId());
|
||||
serviceGrayConfig.getUserKeys().addAll(list);
|
||||
Set<String> userKeySet = Stream.of(userKeys)
|
||||
.collect(Collectors.toCollection(Sets::newConcurrentHashSet));
|
||||
|
||||
Map<String, String> grayNameVersion = serviceGrayConfig.getGrayNameVersion();
|
||||
for (String nameVersion : nameVersionList) {
|
||||
String[] nameVersionInfo = StringUtils.split(nameVersion, '=');
|
||||
String name = nameVersionInfo[0];
|
||||
String version = nameVersionInfo[1];
|
||||
grayNameVersion.put(name, version);
|
||||
}
|
||||
Map<String, String> grayNameVersionMap = Stream.of(nameVersionList)
|
||||
.map(nameVersion -> StringUtils.split(nameVersion, '='))
|
||||
.collect(Collectors.toConcurrentMap(FUNCTION_KEY, FUNCTION_VALUE));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空用户key
|
||||
*/
|
||||
public void clear(String instanceId) {
|
||||
getServiceGrayConfig(instanceId).clear();
|
||||
ServiceGrayConfig serviceGrayConfig = new ServiceGrayConfig();
|
||||
serviceGrayConfig.setServiceId(configGray.getServiceId());
|
||||
serviceGrayConfig.setUserKeys(userKeySet);
|
||||
serviceGrayConfig.setGrayNameVersion(grayNameVersionMap);
|
||||
this.saveServiceGrayConfig(serviceGrayConfig);
|
||||
}
|
||||
|
||||
|
||||
@PostConstruct
|
||||
protected void after() throws Exception {
|
||||
ZookeeperContext.setEnvironment(environment);
|
||||
String isvChannelPath = ZookeeperContext.getUserKeyChannelPath();
|
||||
String isvChannelPath = ZookeeperContext.getServiceGrayChannelPath();
|
||||
ZookeeperContext.listenPath(isvChannelPath, nodeCache -> {
|
||||
String nodeData = new String(nodeCache.getCurrentData().getData());
|
||||
ChannelMsg channelMsg = JSON.parseObject(nodeData, ChannelMsg.class);
|
||||
String data = channelMsg.getData();
|
||||
UserKeyDefinition userKeyDefinition = JSON.parseObject(data, UserKeyDefinition.class);
|
||||
String instanceId = userKeyDefinition.getInstanceId();
|
||||
ServiceGrayDefinition userKeyDefinition = JSON.parseObject(data, ServiceGrayDefinition.class);
|
||||
String serviceId = userKeyDefinition.getServiceId();
|
||||
switch (channelMsg.getOperation()) {
|
||||
case "set":
|
||||
ConfigGrayUserkey configGrayUserkey = configGrayUserkeyMapper.getByColumn("instance_id", instanceId);
|
||||
this.setServiceGrayConfig(configGrayUserkey);
|
||||
ConfigGray configGray = configGrayMapper.getByColumn("service_id", serviceId);
|
||||
this.setServiceGrayConfig(configGray);
|
||||
break;
|
||||
case "clear":
|
||||
clear(instanceId);
|
||||
case "open":
|
||||
openGray(userKeyDefinition.getInstanceId(), serviceId);
|
||||
break;
|
||||
case "close":
|
||||
closeGray(userKeyDefinition.getInstanceId());
|
||||
break;
|
||||
default:
|
||||
log.error("userKey消息,错误的消息指令,nodeData:{}", nodeData);
|
||||
|
||||
}
|
||||
});
|
||||
|
@@ -56,7 +56,6 @@ public class DbIPBlacklistManager extends DefaultIPBlacklistManager {
|
||||
remove(ip);
|
||||
break;
|
||||
default:
|
||||
log.error("IP黑名单,错误的消息指令,nodeData:{}", nodeData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -61,7 +61,6 @@ public class DbIsvManager extends CacheIsvManager {
|
||||
remove(isvDefinition.getAppKey());
|
||||
break;
|
||||
default:
|
||||
log.error("ISV信息,错误的消息指令,nodeData:{}", nodeData);
|
||||
|
||||
}
|
||||
});
|
||||
|
@@ -152,6 +152,8 @@ public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManage
|
||||
log.info("删除ISV路由权限信息,isvRoutePermission:{}", isvRoutePermission);
|
||||
remove(isvRoutePermission.getAppKey());
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -63,7 +63,6 @@ public class DbLimitConfigManager extends DefaultLimitConfigManager {
|
||||
update(configLimitDto);
|
||||
break;
|
||||
default:
|
||||
log.error("限流配置信息,错误的消息指令,nodeData:{}", nodeData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -87,7 +87,6 @@ public class DbRouteConfigManager extends DefaultRouteConfigManager {
|
||||
update(routeConfig);
|
||||
break;
|
||||
default:
|
||||
log.error("路由配置信息,错误的消息指令,nodeData:{}", nodeData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -0,0 +1,11 @@
|
||||
package com.gitee.sop.gateway.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
import com.gitee.sop.gateway.entity.ConfigGrayInstance;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface ConfigGrayInstanceMapper extends CrudMapper<ConfigGrayInstance, Long> {
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.gitee.sop.gateway.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
import com.gitee.sop.gateway.entity.ConfigGray;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface ConfigGrayMapper extends CrudMapper<ConfigGray, Long> {
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
package com.gitee.sop.gateway.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
import com.gitee.sop.gateway.entity.ConfigGrayUserkey;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface ConfigGrayUserkeyMapper extends CrudMapper<ConfigGrayUserkey, Long> {
|
||||
}
|
@@ -12,6 +12,9 @@ eureka.url=http://localhost:1111/eureka/
|
||||
zookeeper.url=localhost:2181
|
||||
# zipkin服务监控地址,没有开启不用改
|
||||
zipkin.url=http://127.0.0.1:9411/
|
||||
|
||||
# 预发布网关域名
|
||||
pre.domain=localhost
|
||||
# ------- 需要改的配置end -------
|
||||
|
||||
# 入口地址,不用改,默认是/zuul
|
||||
|
Reference in New Issue
Block a user