針對高併發、海量數據的大型網站,頁面靜態化是提升性能、降低數據庫壓力的核心手段。本文構建一套分佈式文件存儲 + 模板引擎生成 + 異步任務調度的完整解決方案。
將靜態頁面分散存儲於多台文件服務器,通過 SMB (Server Message Block) 協議實現跨平台文件共享。核心挑戰:文件與服務器的映射關係管理。
文件路徑 -> 服務器地址 映射持久化至數據庫,讀取時查詢映射表定位服務器。import jcifs.smb.SmbFile;
public class SmbUtil {
// 構建帶認證的 SMB 路徑
private static String buildPath(String filepath, String username, String pwd) {
return "smb://" + username + ":" + pwd + "@" + filepath;
}
// 判斷文件/目錄是否存在
public static boolean exists(String filepath, String username, String pwd) {
try {
return new SmbFile(buildPath(filepath, username, pwd)).exists();
} catch (Exception e) {
return false;
}
}
// 重命名文件/目錄
public static boolean rename(String filepath, String newName, String username, String pwd) {
try {
SmbFile f = new SmbFile(buildPath(filepath, username, pwd));
String parent = filepath.substring(0, filepath.lastIndexOf("/"));
String newPath = buildPath(parent, username, pwd) + "/" + newName;
f.renameTo(new SmbFile(newPath));
return true;
} catch (Exception e) {
return false;
}
}
// 創建目錄(含多級)
public static void mkdir(String dir, String username, String pwd) {
try {
SmbFile f = new SmbFile(buildPath(dir, username, pwd));
if (!f.exists()) f.mkdir();
} catch (Exception e) { /* log */ }
}
// 創建空文件
public static void createFile(String filepath, String username, String pwd) {
try {
SmbFile f = new SmbFile(buildPath(filepath, username, pwd));
if (!f.exists()) f.createNewFile();
} catch (Exception e) { /* log */ }
}
// 創建文件並寫入內容
public static void createFileWithContent(String filepath, String username, String pwd, String content) {
createFile(filepath, username, pwd);
writeFile(filepath, content, username, pwd); // 需實現寫入邏輯
}
// 判斷是否為目錄
public static boolean isDirectory(String filepath, String username, String pwd) throws Exception {
return new SmbFile(buildPath(filepath, username, pwd)).isDirectory();
}
}
依賴: 需引入 jcifs 庫(jcifs-1.3.19.jar 或更新版)。
FreeMarker 是成熟的 Java 模板引擎,支援指令、插值、內建函數、宏定義等豐富特性,極適合生成靜態 HTML。
import freemarker.template.Configuration;
import freemarker.template.Template;
import java.io.StringWriter;
import java.util.Map;
public class StaticPageGenerator {
private static Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
static {
cfg.setClassForTemplateLoading(StaticPageGenerator.class, "/templates");
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
}
// 生成靜態頁面內容字符串
public static String generate(String templateName, Map dataModel) throws Exception {
Template template = cfg.getTemplate(templateName);
StringWriter out = new StringWriter();
template.process(dataModel, out);
return out.toString();
}
// 直接寫入文件(結合 SMB)
public static void generateToFile(String templateName, Map dataModel,
String smbPath, String username, String pwd) throws Exception {
String content = generate(templateName, dataModel);
// 此處調用 SMBUtil 寫入文件服務器
SmbUtil.createFileWithContent(smbPath, username, pwd, content);
}
}
<html>
<head><title>${article.title}</title></head>
<body>
<h1>${article.title}</h1>
<div class="meta">作者:${article.author} | 發布:${article.publishTime?string("yyyy-MM-dd HH:mm")}</div>
<div class="content">${article.content}</div>
<#list article.tags as tag>
<span class="tag">${tag}</span>
</#list>
</body>
</html>
靜態化請求(如發布文章、數據更新)不應同步阻塞業務線程,需異步化處理。
StaticPageGenerator 生成頁面並通過 SMB 寫入文件服務器。public class StaticizeTask {
private String taskId; // 唯一標識
private String templateName; // 模板文件名
private Map dataModel; // 數據模型
private String targetPath; // 目標 SMB 路徑
private int priority; // 優先級
private long createTime; // 創建時間
private int retryCount; // 重試次數
// getter/setter 省略
}
public interface StaticizeScheduler {
// 提交任務(異步)
void submit(StaticizeTask task);
// 批量提交
void submitBatch(List tasks);
// 取消任務
boolean cancel(String taskId);
// 查詢任務狀態
TaskStatus getStatus(String taskId);
}
| 維度 | 策略 |
|---|---|
| 高併發寫入 | 文件服務器採用 SSD + RAID10;SMB 連接池複用;大文件分片寫入 |
| 緩存一致性 | 生成成功後主動刷新 CDN 緩存(API 刷新 URL);失敗則保留舊版本 |
| 模板熱更新 | FreeMarker cfg.setTemplateUpdateDelay(0) 開發模式實時加載;生產環境設 60s 平衡性能 |
| 併發控制 | 同一頁面並發生成請求去重(Redis 分佈式鎖),避免重複渲染 |
| 存儲擴容 | 一致性哈希映射 + 數據庫元數據,新增服務器只需同步映射表 |
| 監控告警 | 任務隊列積壓、生成耗時、失敗率、磁盤空間納入監控體系 |
「分佈式 SMB 存儲 + FreeMarker 渲染 + 異步調度」構成了大型網站靜態化的經典鐵三角。實際落地時,建議優先考慮對象存儲(MinIO/S3)替代 SMB,配合 CDN 回源,實現存儲與分發的一體化;調度層接入成熟框架(XXL-JOB)而非自研,專注業務邏輯開發。核心原則:生成異步化、存儲分佈式、模板組件化、監控可視化。