自定义API缓存
当多实例分布式部署时,在页面中编辑脚本后,如何把变更同步到所有实例上,这时可以自定义缓存,通过共公组件如Redis等来维护缓存问题,即所有实例共享一份缓存,跳过变更同步问题。
IApiInfoCache.refreshNotify,receiveNotify,可实现集群环境下不重启实例也能达到各实例缓存的自动刷新和mapping重载问题。基于spring cloud 配置中心刷新思想.触发方式为: 1. 通过页面上的"Rebuild API List" 行为触发 2. 对任一接口进行编辑,新增,删除
如果搞不清楚,那就重启所有实例,没有什么问题是重启不能解决的
实现接口:com.github.alenfive.rocketapi.extend.IApiInfoCache
默认实现:
import com.github.alenfive.rocketapi.config.QLRequestMappingFactory;
import com.github.alenfive.rocketapi.entity.ApiInfo;
import com.github.alenfive.rocketapi.entity.vo.RefreshMapping;
import com.github.alenfive.rocketapi.utils.GenerateId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* API信息缓存
*/
@Component
public class DefaultApiInfoCache implements IApiInfoCache {
private Map<String, ApiInfo> cacheApiInfo = new ConcurrentHashMap<>();
private String instanceId = GenerateId.get().toHexString();
@Autowired
private QLRequestMappingFactory mappingFactory;
@Override
public ApiInfo get(ApiInfo apiInfo){
return cacheApiInfo.get(buildApiInfoKey(apiInfo));
}
@Override
public Collection<ApiInfo> getAll() {
return cacheApiInfo.values();
}
@Override
public void removeAll() {
cacheApiInfo.clear();
}
@Override
public void remove(ApiInfo apiInfo) {
cacheApiInfo.remove(buildApiInfoKey(apiInfo));
}
@Override
public void put(ApiInfo apiInfo) {
cacheApiInfo.put(buildApiInfoKey(apiInfo),apiInfo);
}
private String buildApiInfoKey(ApiInfo apiInfo) {
return apiInfo.getMethod() +" "+ apiInfo.getFullPath();
}
/**
* 发送系统缓存刷新的通知
* 1. 在页面触发"Rebuild API List"操作时,会触发此方法,refreshMapping为空,可使用Redis消息通知功能重写该方法,
* 2. 在页面触发接口编辑"Save"操作时,会触发此方法,refreshMapping为变更记录,可使用Redis消息通知功能重写该方法,
* 以达到分布式环境下多实例部署系统更新问题
*/
@Override
public void refreshNotify(RefreshMapping refreshMapping) {
this.receiveNotify(instanceId,refreshMapping);
}
/**
* 监听 "@refreshNotify"行为,来重载本地request mapping等本地实体行为的重新初始化
* @param instanceId
*/
@Override
public void receiveNotify(String instanceId, RefreshMapping refreshMapping) {
//避免本实例重复初始化
if (this.instanceId.equals(instanceId)){
return;
}
//刷新单个接口
if (refreshMapping != null){
try {
mappingFactory.refreshMapping(refreshMapping);
}catch (Exception e){
e.printStackTrace();
}
return;
}
//全局刷新
try {
mappingFactory.buildInit();
}catch (Exception e){
e.printStackTrace();
}
}
}
Last updated