mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
支持预发布、灰度发布
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# changelog
|
||||
|
||||
## 1.14.0
|
||||
|
||||
- 支持预发布、灰度发布环境
|
||||
|
||||
## 1.13.4
|
||||
|
||||
- 修复admin服务列表最后更新时间不显示问题
|
||||
|
@@ -5,6 +5,7 @@ CREATE TABLE `config_gray_userkey` (
|
||||
`instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'serviceId',
|
||||
`user_key_content` text COMMENT '用户key,多个用引文逗号隔开',
|
||||
`name_version_content` text COMMENT '需要灰度的接口,goods.get=1.2,order.list=1.2',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:禁用,1:启用',
|
||||
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<curator-recipes.version>4.0.1</curator-recipes.version>
|
||||
<okhttp.version>3.11.0</okhttp.version>
|
||||
<easyopen.version>1.16.2</easyopen.version>
|
||||
<fastmybatis.version>1.8.0</fastmybatis.version>
|
||||
<fastmybatis.version>1.8.1</fastmybatis.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -1,16 +1,12 @@
|
||||
package com.gitee.sop.adminserver;
|
||||
|
||||
import com.gitee.fastmybatis.core.FastmybatisConfig;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SopAdminServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
FastmybatisConfig.defaultIgnoreUpdateColumns = Arrays.asList("gmt_create", "gmt_modified");
|
||||
SpringApplication.run(SopAdminServerApplication.class, args);
|
||||
}
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ import com.gitee.sop.adminserver.bean.UserKeyDefinition;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import com.gitee.sop.adminserver.common.BizException;
|
||||
import com.gitee.sop.adminserver.common.ChannelOperation;
|
||||
import com.gitee.sop.adminserver.common.StatusEnum;
|
||||
import com.gitee.sop.adminserver.common.ZookeeperPathExistException;
|
||||
import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException;
|
||||
import com.gitee.sop.adminserver.entity.ConfigGrayUserkey;
|
||||
@@ -49,6 +50,7 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
public class ServiceApi {
|
||||
|
||||
|
||||
@Autowired
|
||||
private RegistryService registryService;
|
||||
|
||||
@@ -219,10 +221,12 @@ public class ServiceApi {
|
||||
configGrayUserkey.setInstanceId(instanceId);
|
||||
configGrayUserkey.setUserKeyContent(userKeyContent);
|
||||
configGrayUserkey.setNameVersionContent(nameVersionContent);
|
||||
configGrayUserkey.setStatus(StatusEnum.STATUS_ENABLE.getStatus());
|
||||
configGrayUserkeyMapper.save(configGrayUserkey);
|
||||
} else {
|
||||
configGrayUserkey.setUserKeyContent(userKeyContent);
|
||||
configGrayUserkey.setNameVersionContent(nameVersionContent);
|
||||
configGrayUserkey.setStatus(StatusEnum.STATUS_ENABLE.getStatus());
|
||||
configGrayUserkeyMapper.update(configGrayUserkey);
|
||||
}
|
||||
this.sendUserKeyMsg(instanceId, ChannelOperation.GRAY_USER_KEY_SET);
|
||||
@@ -238,7 +242,13 @@ public class ServiceApi {
|
||||
try {
|
||||
MetadataEnum envPre = MetadataEnum.ENV_ONLINE;
|
||||
registryService.setMetadata(param, envPre.getKey(), envPre.getValue());
|
||||
this.sendUserKeyMsg(param.getServiceId(), ChannelOperation.GRAY_USER_KEY_CLEAR);
|
||||
|
||||
ConfigGrayUserkey configGrayUserkey = configGrayUserkeyMapper.getByColumn("instance_id", param.getInstanceId());
|
||||
if (configGrayUserkey != null && configGrayUserkey.getStatus() == StatusEnum.STATUS_ENABLE.getStatus()) {
|
||||
configGrayUserkey.setStatus(StatusEnum.STATUS_DISABLE.getStatus());
|
||||
configGrayUserkeyMapper.update(configGrayUserkey);
|
||||
}
|
||||
this.sendUserKeyMsg(param.getInstanceId(), ChannelOperation.GRAY_USER_KEY_CLEAR);
|
||||
} catch (Exception e) {
|
||||
log.error("上线失败,param:{}", param, e);
|
||||
throw new BizException("上线失败,请查看日志");
|
||||
@@ -250,9 +260,9 @@ public class ServiceApi {
|
||||
return configGrayUserkeyMapper.getByColumn("instance_id", param.getInstanceId());
|
||||
}
|
||||
|
||||
private void sendUserKeyMsg(String serviceId, ChannelOperation channelOperation) {
|
||||
private void sendUserKeyMsg(String instanceId, ChannelOperation channelOperation) {
|
||||
UserKeyDefinition userKeyDefinition = new UserKeyDefinition();
|
||||
userKeyDefinition.setServiceId(serviceId);
|
||||
userKeyDefinition.setInstanceId(instanceId);
|
||||
ChannelMsg channelMsg = new ChannelMsg(channelOperation, userKeyDefinition);
|
||||
String jsonData = JSON.toJSONString(channelMsg);
|
||||
String path = ZookeeperContext.getUserKeyChannelPath();
|
||||
|
@@ -7,6 +7,6 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
public class UserKeyDefinition {
|
||||
private String serviceId;
|
||||
private String instanceId;
|
||||
private String data;
|
||||
}
|
||||
|
@@ -0,0 +1,26 @@
|
||||
package com.gitee.sop.adminserver.common;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 通用状态枚举
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Getter
|
||||
public enum StatusEnum {
|
||||
/**
|
||||
* 启用
|
||||
*/
|
||||
STATUS_ENABLE((byte)1),
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
STATUS_DISABLE((byte)0),
|
||||
;
|
||||
private byte status;
|
||||
|
||||
StatusEnum(byte status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
@@ -34,6 +34,9 @@ public class ConfigGrayUserkey {
|
||||
/** 需要灰度的接口,goods.get=1.2,order.list=1.2, 数据库字段:name_version_content */
|
||||
private String nameVersionContent;
|
||||
|
||||
/** 0:禁用,1:启用, 数据库字段:status */
|
||||
private Byte status;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
|
@@ -44,5 +44,9 @@ registry.name=eureka
|
||||
|
||||
logging.level.com.gitee=debug
|
||||
|
||||
# 不用改
|
||||
mybatis.ignore-update-columns[0]=gmt_create
|
||||
mybatis.ignore-update-columns[1]=gmt_modified
|
||||
|
||||
# 不用改,如果要改,请全局替换修改
|
||||
zuul.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC
|
||||
|
@@ -163,7 +163,7 @@
|
||||
</el-form-item>
|
||||
</td>
|
||||
<td style="vertical-align: baseline;">
|
||||
<el-button v-if="index > 0" type="text" @click.prevent="removeNameVersion(grayRouteConfig)">删除</el-button>
|
||||
<el-button v-show="grayForm.grayRouteConfigList.length > 1" type="text" @click.prevent="removeNameVersion(grayRouteConfig)">删除</el-button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -203,11 +203,7 @@ export default {
|
||||
ipPort: '',
|
||||
userKeyContent: '',
|
||||
onlyUpdateGrayUserkey: false,
|
||||
grayRouteConfigList: [{
|
||||
oldRouteId: '',
|
||||
newVersion: '',
|
||||
key: Date.now()
|
||||
}]
|
||||
grayRouteConfigList: []
|
||||
},
|
||||
tabsActiveName: 'first',
|
||||
routeList: [],
|
||||
|
@@ -10,11 +10,13 @@ import com.gitee.sop.gatewaycommon.manager.DefaultIsvRoutePermissionManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.DefaultLimitConfigManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.DefaultRouteConfigManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.DefaultServiceErrorManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.DefaultUserKeyManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.IPBlacklistManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.UserKeyManager;
|
||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||
import com.gitee.sop.gatewaycommon.result.DataNameBuilder;
|
||||
import com.gitee.sop.gatewaycommon.result.DefaultDataNameBuilder;
|
||||
@@ -97,11 +99,6 @@ public class ApiConfig {
|
||||
*/
|
||||
private SessionManager sessionManager = new ApiSessionManager();
|
||||
|
||||
/**
|
||||
* zuul网关全局异常处理
|
||||
*/
|
||||
private ZuulErrorController zuulErrorController = new ZuulErrorController();
|
||||
|
||||
/**
|
||||
* isv路由权限
|
||||
*/
|
||||
@@ -127,6 +124,11 @@ public class ApiConfig {
|
||||
*/
|
||||
private LimitManager limitManager = new DefaultLimitManager();
|
||||
|
||||
/**
|
||||
* 用户key管理
|
||||
*/
|
||||
private UserKeyManager userKeyManager = new DefaultUserKeyManager();
|
||||
|
||||
/**
|
||||
* 构建数据节点名称
|
||||
*/
|
||||
@@ -142,6 +144,11 @@ public class ApiConfig {
|
||||
*/
|
||||
private ServiceErrorManager serviceErrorManager = new DefaultServiceErrorManager();
|
||||
|
||||
/**
|
||||
* zuul网关全局异常处理
|
||||
*/
|
||||
private ZuulErrorController zuulErrorController = new ZuulErrorController();
|
||||
|
||||
// -------- fields ---------
|
||||
|
||||
/**
|
||||
|
@@ -1,21 +1,14 @@
|
||||
package com.gitee.sop.gatewaycommon.bean;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class SpringContext implements ApplicationContextAware {
|
||||
public class SpringContext {
|
||||
|
||||
private static ApplicationContext ctx;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
ctx = applicationContext;
|
||||
}
|
||||
|
||||
public static <T> T getBean(Class<T> clazz) {
|
||||
return ctx.getBean(clazz);
|
||||
}
|
||||
@@ -24,6 +17,10 @@ public class SpringContext implements ApplicationContextAware {
|
||||
return ctx.getBean(beanName);
|
||||
}
|
||||
|
||||
public static void setApplicationContext(ApplicationContext ctx) {
|
||||
SpringContext.ctx = ctx;
|
||||
}
|
||||
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return ctx;
|
||||
}
|
||||
|
@@ -7,6 +7,6 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
public class UserKeyDefinition {
|
||||
private String serviceId;
|
||||
private String instanceId;
|
||||
private String data;
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package com.gitee.sop.gatewaycommon.gateway.filter;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
||||
import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
@@ -19,14 +19,18 @@ import reactor.core.publisher.Mono;
|
||||
@Slf4j
|
||||
public class ValidateFilter implements GlobalFilter, Ordered {
|
||||
|
||||
@Autowired
|
||||
private ParamBuilder<ServerWebExchange> paramBuilder;
|
||||
|
||||
@Autowired
|
||||
private Validator validator;
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
ApiConfig apiConfig = ApiContext.getApiConfig();
|
||||
// 解析参数
|
||||
ApiParam param = apiConfig.getGatewayParamBuilder().build(exchange);
|
||||
ApiParam param = paramBuilder.build(exchange);
|
||||
GatewayContext.setApiParam(exchange, param);
|
||||
// 验证操作,这里有负责验证签名参数
|
||||
Validator validator = apiConfig.getValidator();
|
||||
try {
|
||||
validator.validate(param);
|
||||
} catch (ApiException e) {
|
||||
|
@@ -3,10 +3,15 @@ package com.gitee.sop.gatewaycommon.manager;
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||
import com.gitee.sop.gatewaycommon.bean.BeanInitializer;
|
||||
import com.gitee.sop.gatewaycommon.bean.SpringContext;
|
||||
import com.gitee.sop.gatewaycommon.limit.LimitManager;
|
||||
import com.gitee.sop.gatewaycommon.message.ErrorFactory;
|
||||
import com.gitee.sop.gatewaycommon.secret.IsvManager;
|
||||
import com.gitee.sop.gatewaycommon.session.SessionManager;
|
||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -35,30 +40,59 @@ public class AbstractConfiguration implements ApplicationContextAware {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
Validator validator() {
|
||||
return ApiConfig.getInstance().getValidator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
IsvManager isvManager() {
|
||||
return ApiConfig.getInstance().getIsvManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
IsvRoutePermissionManager isvRoutePermissionManager() {
|
||||
return ApiConfig.getInstance().getIsvRoutePermissionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
RouteConfigManager routeConfigManager() {
|
||||
return ApiConfig.getInstance().getRouteConfigManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
LimitConfigManager limitConfigManager() {
|
||||
return ApiConfig.getInstance().getLimitConfigManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
LimitManager limitManager() {
|
||||
return ApiConfig.getInstance().getLimitManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
IPBlacklistManager ipBlacklistManager() {
|
||||
return ApiConfig.getInstance().getIpBlacklistManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
UserKeyManager userKeyManager() {
|
||||
return ApiConfig.getInstance().getUserKeyManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
SessionManager sessionManager() {
|
||||
return ApiConfig.getInstance().getSessionManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 跨域过滤器
|
||||
*
|
||||
@@ -89,6 +123,7 @@ public class AbstractConfiguration implements ApplicationContextAware {
|
||||
|
||||
@PostConstruct
|
||||
public final void after() {
|
||||
SpringContext.setApplicationContext(applicationContext);
|
||||
if (RouteRepositoryContext.getRouteRepository() == null) {
|
||||
throw new IllegalArgumentException("RouteRepositoryContext.setRouteRepository()方法未使用");
|
||||
}
|
||||
|
@@ -0,0 +1,51 @@
|
||||
package com.gitee.sop.gatewaycommon.manager;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.zuul.loadbalancer.ServiceGrayConfig;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class DefaultUserKeyManager implements UserKeyManager {
|
||||
|
||||
/**
|
||||
* KEY:instanceId
|
||||
*/
|
||||
private Map<String, ServiceGrayConfig> serviceUserKeyMap = Maps.newConcurrentMap();
|
||||
|
||||
@Override
|
||||
public boolean containsKey(String instanceId, Object userKey) {
|
||||
if (instanceId == null || userKey == null) {
|
||||
return false;
|
||||
}
|
||||
return this.getServiceGrayConfig(instanceId).containsKey(userKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion(String instanceId, String nameVersion) {
|
||||
if (instanceId == null || nameVersion == null) {
|
||||
return null;
|
||||
}
|
||||
return this.getServiceGrayConfig(instanceId).getVersion(nameVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceGrayConfig getServiceGrayConfig(String instanceId) {
|
||||
ServiceGrayConfig serviceGrayConfig = serviceUserKeyMap.get(instanceId);
|
||||
if (serviceGrayConfig == null) {
|
||||
serviceGrayConfig = new ServiceGrayConfig();
|
||||
serviceGrayConfig.setUserKeys(Sets.newConcurrentHashSet());
|
||||
serviceGrayConfig.setGrayNameVersion(Maps.newConcurrentMap());
|
||||
serviceUserKeyMap.put(instanceId, serviceGrayConfig);
|
||||
}
|
||||
return serviceGrayConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package com.gitee.sop.gatewaycommon.manager;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class ManagerContext {
|
||||
|
||||
private static ApplicationContext ctx;
|
||||
|
||||
public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
ctx = applicationContext;
|
||||
}
|
||||
|
||||
public static <T> T getManager(Class<T> clazz) {
|
||||
return ctx.getBean(clazz);
|
||||
}
|
||||
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return ctx;
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package com.gitee.sop.gatewaycommon.manager;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.BeanInitializer;
|
||||
import com.gitee.sop.gatewaycommon.zuul.loadbalancer.ServiceGrayConfig;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface UserKeyManager extends BeanInitializer {
|
||||
boolean containsKey(String instanceId, Object userKey);
|
||||
|
||||
String getVersion(String instanceId, String nameVersion);
|
||||
|
||||
ServiceGrayConfig getServiceGrayConfig(String instanceId);
|
||||
}
|
@@ -45,7 +45,7 @@ public class ParamNames {
|
||||
/** 返回sign名称 */
|
||||
public static String RESPONSE_SIGN_NAME = "sign";
|
||||
|
||||
public static String HEADER_VERSION_NAME = "x-sop-version";
|
||||
public static String GRAY_HEADER_VERSION_NAME = "sop_gray_version";
|
||||
|
||||
|
||||
}
|
||||
|
@@ -15,11 +15,11 @@ import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||
import com.gitee.sop.gatewaycommon.param.UploadContext;
|
||||
import com.gitee.sop.gatewaycommon.secret.IsvManager;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@@ -35,15 +35,26 @@ import java.util.List;
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
@Getter
|
||||
public class ApiValidator implements Validator {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApiValidator.class);
|
||||
|
||||
private static final int MILLISECOND_OF_ONE_SECOND = 1000;
|
||||
public static final int STATUS_FORBIDDEN = 2;
|
||||
|
||||
private static final int STATUS_FORBIDDEN = 2;
|
||||
|
||||
private static List<String> FORMAT_LIST = Arrays.asList("json", "xml");
|
||||
|
||||
@Autowired
|
||||
private IsvManager isvManager;
|
||||
|
||||
@Autowired
|
||||
private IsvRoutePermissionManager isvRoutePermissionManager;
|
||||
|
||||
@Autowired
|
||||
private IPBlacklistManager ipBlacklistManager;
|
||||
|
||||
@Autowired
|
||||
private RouteConfigManager routeConfigManager;
|
||||
|
||||
@Override
|
||||
public void validate(ApiParam param) {
|
||||
@@ -52,8 +63,8 @@ public class ApiValidator implements Validator {
|
||||
|
||||
ApiConfig apiConfig = ApiContext.getApiConfig();
|
||||
if (apiConfig.isIgnoreValidate() || param.fetchIgnoreValidate()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("忽略所有验证(ignoreValidate=true), name:{}, version:{}", param.fetchName(), param.fetchVersion());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("忽略所有验证(ignoreValidate=true), name:{}, version:{}", param.fetchName(), param.fetchVersion());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -71,7 +82,6 @@ public class ApiValidator implements Validator {
|
||||
* @param param 接口参数
|
||||
*/
|
||||
protected void checkIP(ApiParam param) {
|
||||
IPBlacklistManager ipBlacklistManager = ApiConfig.getInstance().getIpBlacklistManager();
|
||||
String ip = param.fetchIp();
|
||||
if (ipBlacklistManager.contains(ip)) {
|
||||
throw ErrorEnum.ISV_IP_FORBIDDEN.getErrorMeta().getException();
|
||||
@@ -87,7 +97,6 @@ public class ApiValidator implements Validator {
|
||||
// 检查路由是否存在
|
||||
RouteRepositoryContext.checkExist(routeId, ErrorEnum.ISV_INVALID_METHOD);
|
||||
// 检查路由是否启用
|
||||
RouteConfigManager routeConfigManager = ApiConfig.getInstance().getRouteConfigManager();
|
||||
RouteConfig routeConfig = routeConfigManager.get(routeId);
|
||||
if (!routeConfig.enable()) {
|
||||
throw ErrorEnum.ISP_API_DISABLED.getErrorMeta().getException();
|
||||
@@ -115,7 +124,7 @@ public class ApiValidator implements Validator {
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("验证上传文件MD5错误", e);
|
||||
log.error("验证上传文件MD5错误", e);
|
||||
throw ErrorEnum.ISV_UPLOAD_FAIL.getErrorMeta().getException();
|
||||
}
|
||||
}
|
||||
@@ -147,8 +156,6 @@ public class ApiValidator implements Validator {
|
||||
if (StringUtils.isEmpty(param.fetchAppKey())) {
|
||||
throw ErrorEnum.ISV_MISSING_APP_ID.getErrorMeta().getException();
|
||||
}
|
||||
IsvManager isvManager = ApiContext.getApiConfig().getIsvManager();
|
||||
Assert.notNull(isvManager, "isvManager未初始化");
|
||||
Isv isv = isvManager.getIsv(param.fetchAppKey());
|
||||
// 没有用户
|
||||
if (isv == null) {
|
||||
@@ -167,7 +174,6 @@ public class ApiValidator implements Validator {
|
||||
throw ErrorEnum.ISV_MISSING_SIGNATURE.getErrorMeta().getException(param.fetchNameVersion(), ParamNames.SIGN_NAME);
|
||||
}
|
||||
ApiConfig apiConfig = ApiContext.getApiConfig();
|
||||
IsvManager isvManager = apiConfig.getIsvManager();
|
||||
// 根据appId获取秘钥
|
||||
Isv isvInfo = isvManager.getIsv(param.fetchAppKey());
|
||||
String secret = isvInfo.getSecretInfo();
|
||||
@@ -205,7 +211,6 @@ public class ApiValidator implements Validator {
|
||||
BaseRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
|
||||
boolean needCheckPermission = BooleanUtils.toBoolean(routeDefinition.getPermission());
|
||||
if (needCheckPermission) {
|
||||
IsvRoutePermissionManager isvRoutePermissionManager = ApiConfig.getInstance().getIsvRoutePermissionManager();
|
||||
String appKey = apiParam.fetchAppKey();
|
||||
boolean hasPermission = isvRoutePermissionManager.hasPermission(appKey, routeId);
|
||||
if (!hasPermission) {
|
||||
|
@@ -69,20 +69,6 @@ public class ZuulContext extends ApiContext {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回自定义的session,被SessionManager管理
|
||||
*
|
||||
* @return 如果sessionId为null,则返回null
|
||||
*/
|
||||
public static HttpSession getManagedSession() {
|
||||
String sessionId = getSessionId();
|
||||
if (sessionId != null) {
|
||||
return getSessionManager().getSession(sessionId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登陆的token
|
||||
*
|
||||
|
@@ -1,9 +1,10 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.configuration;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||
import com.gitee.sop.gatewaycommon.bean.SpringContext;
|
||||
import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration;
|
||||
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
|
||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter;
|
||||
@@ -14,6 +15,7 @@ import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt;
|
||||
import com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator;
|
||||
import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteRepository;
|
||||
import com.gitee.sop.gatewaycommon.zuul.route.ZuulZookeeperRouteManager;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
@@ -37,8 +39,8 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
SpringContext springContext() {
|
||||
return new SpringContext();
|
||||
ParamBuilder<RequestContext> paramBuilder() {
|
||||
return ApiConfig.getInstance().getZuulParamBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,6 +131,7 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
|
||||
* 统一错误处理
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ZuulErrorController baseZuulController() {
|
||||
return ApiContext.getApiConfig().getZuulErrorController();
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.netflix.zuul.exception.ZuulException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
@@ -26,6 +27,12 @@ import java.util.List;
|
||||
*/
|
||||
public class PreLimitFilter extends BaseZuulFilter {
|
||||
|
||||
@Autowired
|
||||
private LimitManager limitManager;
|
||||
|
||||
@Autowired
|
||||
private LimitConfigManager limitConfigManager;
|
||||
|
||||
@Override
|
||||
protected FilterType getFilterType() {
|
||||
return FilterType.PRE;
|
||||
@@ -53,7 +60,6 @@ public class PreLimitFilter extends BaseZuulFilter {
|
||||
return null;
|
||||
}
|
||||
byte limitType = configLimitDto.getLimitType().byteValue();
|
||||
LimitManager limitManager = ApiConfig.getInstance().getLimitManager();
|
||||
// 如果是漏桶策略
|
||||
if (limitType == LimitType.LEAKY_BUCKET.getType()) {
|
||||
boolean acquire = limitManager.acquire(configLimitDto);
|
||||
@@ -67,8 +73,6 @@ public class PreLimitFilter extends BaseZuulFilter {
|
||||
}
|
||||
|
||||
protected ConfigLimitDto findConfigLimitDto(ApiConfig apiConfig, ApiParam apiParam, HttpServletRequest request) {
|
||||
LimitConfigManager limitConfigManager = apiConfig.getLimitConfigManager();
|
||||
|
||||
String routeId = apiParam.fetchNameVersion();
|
||||
String appKey = apiParam.fetchAppKey();
|
||||
String ip = RequestUtil.getIP(request);
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.filter;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
|
||||
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
|
||||
import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
|
||||
@@ -11,6 +10,7 @@ import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.netflix.zuul.exception.ZuulException;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* 路由权限校验,有些接口需要配置权限才能访问。
|
||||
@@ -19,6 +19,10 @@ import org.apache.commons.lang3.BooleanUtils;
|
||||
*/
|
||||
@Deprecated
|
||||
public class PreRoutePermissionFilter extends BaseZuulFilter {
|
||||
|
||||
@Autowired
|
||||
private IsvRoutePermissionManager isvRoutePermissionManager;
|
||||
|
||||
@Override
|
||||
protected FilterType getFilterType() {
|
||||
return FilterType.PRE;
|
||||
@@ -38,7 +42,6 @@ public class PreRoutePermissionFilter extends BaseZuulFilter {
|
||||
BaseRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
|
||||
boolean needCheckPermission = BooleanUtils.toBoolean(routeDefinition.getPermission());
|
||||
if (needCheckPermission) {
|
||||
IsvRoutePermissionManager isvRoutePermissionManager = ApiConfig.getInstance().getIsvRoutePermissionManager();
|
||||
String appKey = apiParam.fetchAppKey();
|
||||
boolean hasPermission = isvRoutePermissionManager.hasPermission(appKey, routeId);
|
||||
if (!hasPermission) {
|
||||
|
@@ -1,13 +1,13 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.filter;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.netflix.zuul.exception.ZuulException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* 前置校验
|
||||
@@ -15,6 +15,13 @@ import com.netflix.zuul.exception.ZuulException;
|
||||
* @author tanghc
|
||||
*/
|
||||
public class PreValidateFilter extends BaseZuulFilter {
|
||||
|
||||
@Autowired
|
||||
private ParamBuilder<RequestContext> paramBuilder;
|
||||
|
||||
@Autowired
|
||||
private Validator validator;
|
||||
|
||||
@Override
|
||||
protected FilterType getFilterType() {
|
||||
return FilterType.PRE;
|
||||
@@ -27,12 +34,10 @@ public class PreValidateFilter extends BaseZuulFilter {
|
||||
|
||||
@Override
|
||||
protected Object doRun(RequestContext requestContext) throws ZuulException {
|
||||
ApiConfig apiConfig = ApiContext.getApiConfig();
|
||||
// 解析参数
|
||||
ApiParam param = apiConfig.getZuulParamBuilder().build(requestContext);
|
||||
ApiParam param = paramBuilder.build(requestContext);
|
||||
ZuulContext.setApiParam(param);
|
||||
// 验证操作,这里有负责验证签名参数
|
||||
Validator validator = apiConfig.getValidator();
|
||||
try {
|
||||
validator.validate(param);
|
||||
} catch (ApiException e) {
|
||||
|
@@ -0,0 +1,23 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.loadbalancer;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.support.HttpRequestWrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class EnvHttpRequestInterceptor implements ClientHttpRequestInterceptor {
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
|
||||
HttpRequestWrapper requestWrapper = new HttpRequestWrapper(request);
|
||||
String newVersion = HystrixRequestVariableContext.getVersion();
|
||||
requestWrapper.getHeaders().add(ParamNames.GRAY_HEADER_VERSION_NAME, newVersion);
|
||||
return execution.execute(requestWrapper, body);
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.loadbalancer;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class HystrixRequestVariableContext {
|
||||
// private static final HystrixRequestVariableDefault<String> VERSION_HOLDER = new HystrixRequestVariableDefault<>();
|
||||
private static final ThreadLocal<String> VERSION_HOLDER = new ThreadLocal<>();
|
||||
|
||||
public static void setVersion(String version) {
|
||||
VERSION_HOLDER.set(version);
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return VERSION_HOLDER.get();
|
||||
}
|
||||
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.sop.gateway.loadbalancer;
|
||||
package com.gitee.sop.gatewaycommon.zuul.loadbalancer;
|
||||
|
||||
import lombok.Data;
|
||||
|
@@ -34,7 +34,7 @@ public class ZuulZookeeperRouteManager extends BaseRouteManager<ZuulServiceRoute
|
||||
|
||||
@Override
|
||||
protected ZuulTargetRoute buildRouteDefinition(ZuulServiceRouteInfo serviceRouteInfo, ZuulRouteDefinition routeDefinition) {
|
||||
Route route = new Route(routeDefinition.getId(), routeDefinition.getPath(), RouteUtil.getZuulLocation(routeDefinition.getUri()), null, RETRYABLE, null);
|
||||
Route route = new Route(routeDefinition.getId(), routeDefinition.getPath(), RouteUtil.getZuulLocation(routeDefinition.getUri()), "", RETRYABLE, null);
|
||||
return new ZuulTargetRoute(serviceRouteInfo, routeDefinition, route);
|
||||
}
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@ public class ParamNames {
|
||||
/** 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 */
|
||||
public static String BIZ_CONTENT_NAME = "biz_content";
|
||||
|
||||
public static String HEADER_VERSION_NAME = "x-sop-version";
|
||||
public static String HEADER_VERSION_NAME = "sop_gray_version";
|
||||
|
||||
/** 时间戳格式 */
|
||||
public static String TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||
|
@@ -15,7 +15,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
@Slf4j
|
||||
public class ApiMappingRequestCondition implements RequestCondition<ApiMappingRequestCondition> {
|
||||
|
||||
public static final String UTF_8 = "UTF-8";
|
||||
private String defaultVersion = ServiceConfig.getInstance().getDefaultVersion();
|
||||
|
||||
private ApiMappingInfo apiMappingInfo;
|
||||
|
@@ -130,7 +130,7 @@ public class AlipayController {
|
||||
public Story getStory() {
|
||||
Story story = new Story();
|
||||
story.setId(1);
|
||||
story.setName("海底小纵队(alipay.story.get),2222");
|
||||
story.setName("海底小纵队(alipay.story.get1.0)");
|
||||
return story;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,10 @@ public class AlipayController {
|
||||
*/
|
||||
@ApiMapping(value = "alipay.story.get", version = "1.2")
|
||||
public Story getStory11(Story story) {
|
||||
return story;
|
||||
Story story2 = new Story();
|
||||
story2.setId(1);
|
||||
story2.setName("海底小纵队(alipay.story.get1.2)");
|
||||
return story2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package com.gitee.sop.gateway.config;
|
||||
|
||||
import com.gitee.sop.gateway.manager.ManagerInitializer;
|
||||
import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration;
|
||||
|
||||
|
||||
@@ -20,9 +19,6 @@ import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfigurat
|
||||
//@Configuration
|
||||
public class GatewayConfig extends AlipayGatewayConfiguration {
|
||||
|
||||
static {
|
||||
new ManagerInitializer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -7,7 +7,6 @@ package com.gitee.sop.gateway.config;
|
||||
*/
|
||||
|
||||
import com.gitee.sop.gateway.loadbalancer.SopPropertiesFactory;
|
||||
import com.gitee.sop.gateway.manager.ManagerInitializer;
|
||||
import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.PropertiesFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -20,10 +19,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Configuration
|
||||
public class ZuulConfig extends AlipayZuulConfiguration {
|
||||
|
||||
static {
|
||||
new ManagerInitializer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
PropertiesFactory propertiesFactory() {
|
||||
return new SopPropertiesFactory();
|
||||
|
@@ -34,6 +34,9 @@ public class ConfigGrayUserkey {
|
||||
/** 需要灰度的接口,goods.get=1.2,order.list=1.2, 数据库字段:name_version_content */
|
||||
private String nameVersionContent;
|
||||
|
||||
/** 0:禁用,1:启用, 数据库字段:status */
|
||||
private Byte status;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.gitee.sop.gateway.loadbalancer;
|
||||
|
||||
import com.gitee.sop.gateway.manager.UserKeyManager;
|
||||
import com.gitee.sop.gateway.manager.DbUserKeyManager;
|
||||
import com.gitee.sop.gatewaycommon.bean.SpringContext;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.param.Param;
|
||||
@@ -83,14 +83,15 @@ public class EnvironmentServerChooser extends BaseServerChooser {
|
||||
*/
|
||||
protected boolean canVisitGray(Server server, HttpServletRequest request) {
|
||||
ApiParam apiParam = ZuulContext.getApiParam();
|
||||
UserKeyManager userKeyManager = SpringContext.getBean(UserKeyManager.class);
|
||||
DbUserKeyManager userKeyManager = SpringContext.getBean(DbUserKeyManager.class);
|
||||
boolean canVisit = false;
|
||||
if (this.isGrayUser(apiParam, userKeyManager, server, request)) {
|
||||
// 指定灰度版本号
|
||||
String instanceId = server.getId();
|
||||
String instanceId = server.getMetaInfo().getInstanceId();
|
||||
String newVersion = userKeyManager.getVersion(instanceId, apiParam.fetchNameVersion());
|
||||
if (newVersion != null) {
|
||||
RequestContext.getCurrentContext().getZuulRequestHeaders().put(ParamNames.HEADER_VERSION_NAME, newVersion);
|
||||
// 在header中设置新的版本号,然后微服务端先获取这个新版本号
|
||||
RequestContext.getCurrentContext().addZuulRequestHeader(ParamNames.GRAY_HEADER_VERSION_NAME, newVersion);
|
||||
canVisit = true;
|
||||
}
|
||||
}
|
||||
@@ -107,8 +108,8 @@ public class EnvironmentServerChooser extends BaseServerChooser {
|
||||
* @param request request
|
||||
* @return true:是
|
||||
*/
|
||||
protected boolean isGrayUser(Param param, UserKeyManager userKeyManager, Server server, HttpServletRequest request) {
|
||||
String instanceId = server.getId();
|
||||
protected boolean isGrayUser(Param param, DbUserKeyManager userKeyManager, Server server, HttpServletRequest request) {
|
||||
String instanceId = server.getMetaInfo().getInstanceId();
|
||||
// 这里的灰度用户为appKey,包含此appKey则为灰度用户,允许访问
|
||||
String appKey = param.fetchAppKey();
|
||||
return userKeyManager.containsKey(instanceId, appKey);
|
||||
|
@@ -9,6 +9,7 @@ import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
@@ -19,6 +20,7 @@ import java.util.List;
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DbIPBlacklistManager extends DefaultIPBlacklistManager {
|
||||
|
||||
@Autowired
|
||||
|
@@ -3,6 +3,7 @@ package com.gitee.sop.gateway.manager;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.sop.gateway.entity.IsvDetailDTO;
|
||||
import com.gitee.sop.gateway.mapper.IsvInfoMapper;
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
|
||||
import com.gitee.sop.gatewaycommon.bean.IsvDefinition;
|
||||
import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
|
||||
@@ -11,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
@@ -19,6 +21,7 @@ import java.util.List;
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DbIsvManager extends CacheIsvManager {
|
||||
|
||||
@Autowired
|
||||
@@ -41,6 +44,7 @@ public class DbIsvManager extends CacheIsvManager {
|
||||
|
||||
@PostConstruct
|
||||
protected void after() throws Exception {
|
||||
ApiConfig.getInstance().setIsvManager(this);
|
||||
ZookeeperContext.setEnvironment(environment);
|
||||
String isvChannelPath = ZookeeperContext.getIsvInfoChannelPath();
|
||||
ZookeeperContext.listenPath(isvChannelPath, nodeCache -> {
|
||||
|
@@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@@ -35,6 +36,7 @@ import static java.util.stream.Collectors.toList;
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManager {
|
||||
|
||||
@Autowired
|
||||
|
@@ -11,6 +11,7 @@ import com.gitee.sop.gatewaycommon.util.MyBeanUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@@ -19,6 +20,7 @@ import javax.annotation.PostConstruct;
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DbLimitConfigManager extends DefaultLimitConfigManager {
|
||||
|
||||
@Autowired
|
||||
|
@@ -14,6 +14,7 @@ import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Collection;
|
||||
@@ -22,6 +23,7 @@ import java.util.Collection;
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DbRouteConfigManager extends DefaultRouteConfigManager {
|
||||
|
||||
@Autowired
|
||||
|
@@ -1,14 +1,14 @@
|
||||
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.loadbalancer.ServiceGrayConfig;
|
||||
import com.gitee.sop.gateway.mapper.ConfigGrayUserkeyMapper;
|
||||
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
|
||||
import com.gitee.sop.gatewaycommon.bean.UserKeyDefinition;
|
||||
import com.gitee.sop.gatewaycommon.manager.DefaultUserKeyManager;
|
||||
import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.gitee.sop.gatewaycommon.zuul.loadbalancer.ServiceGrayConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -27,14 +27,11 @@ import java.util.stream.Stream;
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class UserKeyManager {
|
||||
@Service
|
||||
public class DbUserKeyManager extends DefaultUserKeyManager {
|
||||
|
||||
/**
|
||||
* KEY:instanceId
|
||||
*/
|
||||
private Map<String, ServiceGrayConfig> serviceUserKeyMap = Maps.newConcurrentMap();
|
||||
private static final int STATUS_ENABLE = 1;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
@@ -42,18 +39,14 @@ public class UserKeyManager {
|
||||
@Autowired
|
||||
private ConfigGrayUserkeyMapper configGrayUserkeyMapper;
|
||||
|
||||
public boolean containsKey(String serviceId, Object userKey) {
|
||||
if (serviceId == null || userKey == null) {
|
||||
return false;
|
||||
@Override
|
||||
public void load() {
|
||||
Query query = new Query();
|
||||
query.eq("status", STATUS_ENABLE);
|
||||
List<ConfigGrayUserkey> list = configGrayUserkeyMapper.list(query);
|
||||
for (ConfigGrayUserkey configGrayUserkey : list) {
|
||||
this.setServiceGrayConfig(configGrayUserkey);
|
||||
}
|
||||
return this.getServiceGrayConfig(serviceId).containsKey(userKey);
|
||||
}
|
||||
|
||||
public String getVersion(String serviceId, String nameVersion) {
|
||||
if (serviceId == null || nameVersion == null) {
|
||||
return null;
|
||||
}
|
||||
return this.getServiceGrayConfig(serviceId).getVersion(nameVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,11 +54,12 @@ public class UserKeyManager {
|
||||
*
|
||||
* @param configGrayUserkey 灰度配置
|
||||
*/
|
||||
public void setServiceGrayConfig(String serviceId, ConfigGrayUserkey configGrayUserkey) {
|
||||
public void setServiceGrayConfig(ConfigGrayUserkey configGrayUserkey) {
|
||||
if (configGrayUserkey == null) {
|
||||
return;
|
||||
}
|
||||
this.clear(serviceId);
|
||||
String instanceId = configGrayUserkey.getInstanceId();
|
||||
this.clear(instanceId);
|
||||
String userKeyData = configGrayUserkey.getUserKeyContent();
|
||||
String nameVersionContent = configGrayUserkey.getNameVersionContent();
|
||||
String[] userKeys = StringUtils.split(userKeyData, ',');
|
||||
@@ -73,7 +67,7 @@ public class UserKeyManager {
|
||||
log.info("添加userKey,userKeys.length:{}, nameVersionList:{}", userKeys.length, Arrays.toString(nameVersionList));
|
||||
|
||||
List<String> list = Stream.of(userKeys).collect(Collectors.toList());
|
||||
ServiceGrayConfig serviceGrayConfig = getServiceGrayConfig(serviceId);
|
||||
ServiceGrayConfig serviceGrayConfig = getServiceGrayConfig(instanceId);
|
||||
serviceGrayConfig.getUserKeys().addAll(list);
|
||||
|
||||
Map<String, String> grayNameVersion = serviceGrayConfig.getGrayNameVersion();
|
||||
@@ -89,20 +83,10 @@ public class UserKeyManager {
|
||||
/**
|
||||
* 清空用户key
|
||||
*/
|
||||
public void clear(String serviceId) {
|
||||
getServiceGrayConfig(serviceId).clear();
|
||||
public void clear(String instanceId) {
|
||||
getServiceGrayConfig(instanceId).clear();
|
||||
}
|
||||
|
||||
public ServiceGrayConfig getServiceGrayConfig(String serviceId) {
|
||||
ServiceGrayConfig serviceGrayConfig = serviceUserKeyMap.get(serviceId);
|
||||
if (serviceGrayConfig == null) {
|
||||
serviceGrayConfig = new ServiceGrayConfig();
|
||||
serviceGrayConfig.setUserKeys(Sets.newConcurrentHashSet());
|
||||
serviceGrayConfig.setGrayNameVersion(Maps.newConcurrentMap());
|
||||
serviceUserKeyMap.put(serviceId, serviceGrayConfig);
|
||||
}
|
||||
return serviceGrayConfig;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
protected void after() throws Exception {
|
||||
@@ -113,14 +97,14 @@ public class UserKeyManager {
|
||||
ChannelMsg channelMsg = JSON.parseObject(nodeData, ChannelMsg.class);
|
||||
String data = channelMsg.getData();
|
||||
UserKeyDefinition userKeyDefinition = JSON.parseObject(data, UserKeyDefinition.class);
|
||||
String serviceId = userKeyDefinition.getServiceId();
|
||||
String instanceId = userKeyDefinition.getInstanceId();
|
||||
switch (channelMsg.getOperation()) {
|
||||
case "set":
|
||||
ConfigGrayUserkey configGrayUserkey = configGrayUserkeyMapper.getByColumn("service_id", serviceId);
|
||||
this.setServiceGrayConfig(serviceId, configGrayUserkey);
|
||||
ConfigGrayUserkey configGrayUserkey = configGrayUserkeyMapper.getByColumn("instance_id", instanceId);
|
||||
this.setServiceGrayConfig(configGrayUserkey);
|
||||
break;
|
||||
case "clear":
|
||||
clear(serviceId);
|
||||
clear(instanceId);
|
||||
break;
|
||||
default:
|
||||
log.error("userKey消息,错误的消息指令,nodeData:{}", nodeData);
|
@@ -14,5 +14,6 @@ public class ManagerInitializer {
|
||||
apiConfig.setRouteConfigManager(new DbRouteConfigManager());
|
||||
apiConfig.setLimitConfigManager(new DbLimitConfigManager());
|
||||
apiConfig.setIpBlacklistManager(new DbIPBlacklistManager());
|
||||
apiConfig.setUserKeyManager(new DbUserKeyManager());
|
||||
}
|
||||
}
|
||||
|
@@ -231,4 +231,35 @@ public class AlipayClientPostTest extends TestBase {
|
||||
System.out.println(responseData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApiAbility() throws AlipayApiException {
|
||||
// 公共请求参数
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("app_id", appId);
|
||||
params.put("method", "getStory2");
|
||||
params.put("version", "1.0");
|
||||
params.put("format", "json");
|
||||
params.put("charset", "utf-8");
|
||||
params.put("sign_type", "RSA2");
|
||||
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
// 业务参数
|
||||
Map<String, String> bizContent = new HashMap<>();
|
||||
|
||||
params.put("biz_content", JSON.toJSONString(bizContent));
|
||||
|
||||
System.out.println("----------- 请求信息 -----------");
|
||||
System.out.println("请求参数:" + buildParamQuery(params));
|
||||
System.out.println("商户秘钥:" + privateKey);
|
||||
String content = AlipaySignature.getSignContent(params);
|
||||
System.out.println("待签名内容:" + content);
|
||||
String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8");
|
||||
System.out.println("签名(sign):" + sign);
|
||||
|
||||
params.put("sign", sign);
|
||||
|
||||
System.out.println("----------- 返回结果 -----------");
|
||||
String responseData = get(url, params);// 发送请求
|
||||
System.out.println(responseData);
|
||||
}
|
||||
|
||||
}
|
||||
|
1
sop.sql
1
sop.sql
@@ -181,6 +181,7 @@ CREATE TABLE `config_gray_userkey` (
|
||||
`instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'serviceId',
|
||||
`user_key_content` text COMMENT '用户key,多个用引文逗号隔开',
|
||||
`name_version_content` text COMMENT '需要灰度的接口,goods.get=1.2,order.list=1.2',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:禁用,1:启用',
|
||||
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
|
Reference in New Issue
Block a user