perf: 优化快照接口——缓存预序列化 JSON,消除重复序列化
- Caffeine 缓存改为存储 bundle JSON 字符串而非 SiteSnapshot 对象(减少内存占用) - 新增 getActiveBundleJson 方法,SnapshotController 直接使用缓存 JSON - bundle JSON 新增 checksum 字段,ETag 比较无需额外查库 - 删除 SnapshotController.toJson 重复序列化代码 - publish 时复用已序列化的 JSON 上传 CDN
This commit is contained in:
@@ -34,6 +34,13 @@ public interface SiteSnapshotService {
|
||||
*/
|
||||
SiteSnapshot getActive(String siteId);
|
||||
|
||||
/**
|
||||
* 获取站点当前生效快照的预序列化 JSON(带 Caffeine 缓存)
|
||||
* 供 SnapshotController 使用,避免重复序列化
|
||||
* @return JSON 字符串,或 null 表示无快照
|
||||
*/
|
||||
String getActiveBundleJson(String siteId);
|
||||
|
||||
/**
|
||||
* 按 checksum 判断是否需要更新
|
||||
*/
|
||||
|
||||
@@ -43,8 +43,8 @@ public class SiteSnapshotServiceImpl implements SiteSnapshotService {
|
||||
private final CachedStorageService storageService;
|
||||
private static final ObjectMapper om = new ObjectMapper();
|
||||
|
||||
/** 已发布快照本地缓存:key=siteId, value=SiteSnapshot */
|
||||
private final Cache<String, SiteSnapshot> activeSnapshotCache = Caffeine.newBuilder()
|
||||
/** 已发布快照 JSON 缓存:key=siteId, value=预序列化的 bundle JSON */
|
||||
private final Cache<String, String> bundleJsonCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(Duration.ofMinutes(10))
|
||||
.maximumSize(500)
|
||||
.build();
|
||||
@@ -193,12 +193,12 @@ public class SiteSnapshotServiceImpl implements SiteSnapshotService {
|
||||
draft.setPublishedAt(LocalDateTime.now());
|
||||
snapshotMapper.updateById(draft);
|
||||
|
||||
// 刷新本地缓存
|
||||
activeSnapshotCache.put(siteId, draft);
|
||||
// 序列化并刷新缓存
|
||||
String bundleJson = toBundleJson(draft);
|
||||
bundleJsonCache.put(siteId, bundleJson);
|
||||
|
||||
// 上传到七牛云 CDN 作为灾备
|
||||
// 上传到七牛云 CDN 作为灾备(复用已序列化的 JSON)
|
||||
try {
|
||||
String bundleJson = toBundleJson(draft);
|
||||
String cdnPath = "snapshots/" + siteId + ".json";
|
||||
storageService.store(cdnPath, bundleJson);
|
||||
// 也保存版本化副本
|
||||
@@ -217,9 +217,19 @@ public class SiteSnapshotServiceImpl implements SiteSnapshotService {
|
||||
|
||||
@Override
|
||||
public SiteSnapshot getActive(String siteId) {
|
||||
return activeSnapshotCache.get(siteId, key -> {
|
||||
log.debug("缓存未命中,查询数据库 siteId={}", siteId);
|
||||
return snapshotMapper.selectLatestPublished(siteId);
|
||||
return snapshotMapper.selectLatestPublished(siteId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActiveBundleJson(String siteId) {
|
||||
return bundleJsonCache.get(siteId, key -> {
|
||||
SiteSnapshot active = snapshotMapper.selectLatestPublished(key);
|
||||
if (active == null) {
|
||||
log.debug("站点 {} 无 published 快照", key);
|
||||
return ""; // 空字符串表示无数据,Caffeine 会缓存
|
||||
}
|
||||
log.debug("缓存未命中,序列化 siteId={}", key);
|
||||
return toBundleJson(active);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -253,6 +263,7 @@ public class SiteSnapshotServiceImpl implements SiteSnapshotService {
|
||||
try {
|
||||
Map<String, Object> bundle = new LinkedHashMap<>();
|
||||
bundle.put("siteId", snapshot.getSiteId());
|
||||
bundle.put("checksum", snapshot.getChecksum());
|
||||
bundle.put("generatedAt", snapshot.getPublishedAt() != null
|
||||
? snapshot.getPublishedAt().toString() : LocalDateTime.now().toString());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user