摘要:前言一般都會對應用程序日志做回滾處理,本文簡要分析日志回滾實現觸發策略使用接口來抽象日志回滾觸發策略,使用了設計模式方法用于初始化策略,方法用于判斷是否需要回滾,接口的不同實現類對應不同的策略組合模式,聚合不同的策略類基于時間的回滾策略基于
前言
一般都會對應用程序日志做回滾處理,本文簡要分析 log4j2 日志回滾實現
觸發策略log4j2 使用 TriggeringPolity 接口來抽象日志回滾觸發策略,使用了 Strategy + Compose 設計模式
public interface TriggeringPolicy { void initialize(final RollingFileManager manager); boolean isTriggeringEvent(final LogEvent event); }
initialize 方法用于初始化策略,isTriggeringEvent 方法用于判斷是否需要回滾,TriggeringPolicy 接口的不同實現類對應不同的策略
// 組合模式,聚合不同的策略類 public final class CompositeTriggeringPolicy implements TriggeringPolicy { ... } // 基于時間的回滾策略 public final class TimeBasedTriggeringPolicy implements TriggeringPolicy { ... } // 基于文件大小的回滾策略 public final class SizeBasedTriggeringPolicy implements TriggeringPolicy { ... }基于時間的觸發策略 回滾策略
log4j2 使用 RolloverStrategy 接口抽象日志回滾策略
public interface RolloverStrategy { RolloverDescription rollover(final RollingFileManager manager) throws SecurityException; }
rollover 方法并不直接執行回滾操作,而是返回一個 RolloverDescription 接口,該接口用于獲取日志回滾需要進行的操作: Action
public interface RolloverDescription { String getActiveFileName(); boolean getAppend(); Action getSynchronous(); Action getAsynchronous(); }回滾動作
log4j2 使用 Action 接口抽象日志回滾過程中的一系列動作,使用了 Command + Compose 設計模式
public interface Action extends Runnable { boolean execute() throws IOException; void close(); boolean isComplete(); }
AbstractAction 類是 Action 接口的抽象實現,使用了 Method template 設計模式,子類通過 override execute 方法執行不同的動作
public synchronized void run() { if (!interrupted) { try { execute(); } catch (final IOException ex) { reportException(ex); } complete = true; interrupted = true; } } public abstract boolean execute() throws IOException;
文件重命名,FileRenameAction
文件刪除,DeleteAction
文件壓縮,GzCompressAction, ZipCompressAction
聚合,CompositeAction
回滾管理log4j2 每個 Appender 都有一個 Manager 與之對應(多對一), RollingFileAppender 對應的 Manager 為RollingFileManager, 它管理著日志的寫入,回滾 .etc,類層次結構
AbstractManager OutputStreamManager FileManager RollingFileManager
非常經典的 面向對象 設計,單一職責. AbstractManager 保存 Manager 基本信息,例如 name(名字),count(引用計數),并提供靜態工廠方法根據名字獲取 Manager,這個方法同樣值得學習和借鑒
public staticM getManager(final String name, final ManagerFactory factory, final T data) { // 獲取鎖 LOCK.lock(); try { @SuppressWarnings("unchecked") M manager = (M) MAP.get(name); if (manager == null) { // 使用工廠類創建具體的 Manager manager = factory.createManager(name, data); if (manager == null) { throw new IllegalStateException("ManagerFactory [" + factory + "] unable to create manager for [" + name + "] with data [" + data + "]"); } MAP.put(name, manager); } else { manager.updateData(data); } // 增加引用計數 manager.count++; return manager; } finally { // 釋放鎖 LOCK.unlock(); } }
RollingFileAppender 在 append LogEvent 時會先調用 RollingFileManager 的 checkRollover 方法嘗試進行日志回滾,然后再調用父類的 append 方法,這種子類通過 override 方法 "攔截" 父類默認實現增加自己的處理邏輯的方法很常見
// RollingFileAppender.java @Override public void append(final LogEvent event) { getManager().checkRollover(event); super.append(event); }
RollingFileManager 的 checkRollover 方法使用上文提到的 觸發策略類 TriggeringPolicy 判斷是否符合觸發條件,如果符合調用 rollover 方法
public synchronized void checkRollover(final LogEvent event) { if (triggeringPolicy.isTriggeringEvent(event)) { rollover(); } }
不帶參數的 rollover 方法最終調用帶 RolloverStrategy(回滾策略)類型參數的版本,為了代碼顯示更加緊湊特意省略掉了日志輸出和異常處理邏輯,有幾個地方值得品味
使用信號量進行同步,所以不要太頻繁打 log 觸發回滾,會 block 線程
同步 Action 在當前線程立即執行,異步 Action 則啟動一個線程執行
如果異步 Action 很可執行完畢(某些極端情況),finally 語句塊會釋放 semaphore
private boolean rollover(final RolloverStrategy strategy) { semaphore.acquire(); boolean success = false; Thread thread = null; try { final RolloverDescription descriptor = strategy.rollover(this); if (descriptor != null) { writeFooter(); close(); if (descriptor.getSynchronous() != null) { success = descriptor.getSynchronous().execute(); } if (success && descriptor.getAsynchronous() != null) { thread = new Log4jThread(new AsyncAction( descriptor.getAsynchronous(), this)); thread.start(); } return true; } return false; } finally { if (thread == null || !thread.isAlive()) { semaphore.release(); } } }總結
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66823.html
摘要:前言使用插件機制加載各種組件,本文簡要分析插件機制實現注解注解提供了一種便捷的方法將一個類聲明成的插件,比如,單例類用來保存插件信息,暴露了一些方法從配置文件中加載內置插件,使用了單例設計模式線程安全的數據結構使用了一些多線程編程的最佳實踐 前言 log4j2 使用插件機制加載各種組件:appender, logger .etc,本文簡要分析 log4j2 插件機制實現 Plugin ...
摘要:如上圖所示,的實際上是已中間件的形式放在應用層,不用依賴數據庫對協議的支持,完全剝離了分布式事務方案對數據庫在協議支持上的要求。 微信公眾號「后端進階」,專注后端技術分享:Java、Golang、WEB框架、分布式中間件、服務治理等等。 在微服務架構體系下,我們可以按照業務模塊分層設計,單獨部署,減輕了服務部署壓力,也解耦了業務的耦合,避免了應用逐漸變成一個龐然怪物,從而可以輕松擴展,...
摘要:上一篇文章模塊分析第節模塊一日志記錄的級別優先級,記錄調試的詳細信息,只在調試時開啟優先級,記錄普通的消息,報告錯誤和警告等待。監聽端口號上一篇文章模塊分析第節模塊 上一篇文章:Python模塊分析:第3節-typing模塊 一、日志記錄的級別 debug:優先級10,記錄調試的詳細信息,只在調試時開啟 info:優先級20,記錄普通的消息,報告錯誤和警告等待。 warning:優...
閱讀 2919·2023-04-25 19:08
閱讀 1416·2021-11-16 11:45
閱讀 1965·2021-10-13 09:40
閱讀 4128·2021-09-30 09:47
閱讀 2415·2019-08-30 15:44
閱讀 2261·2019-08-30 13:03
閱讀 1387·2019-08-30 12:56
閱讀 1890·2019-08-26 14:04