成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Log42j 源代碼分析:日志回滾

libin19890520 / 1266人閱讀

摘要:前言一般都會對應(yīng)用程序日志做回滾處理,本文簡要分析日志回滾實現(xiàn)觸發(fā)策略使用接口來抽象日志回滾觸發(fā)策略,使用了設(shè)計模式方法用于初始化策略,方法用于判斷是否需要回滾,接口的不同實現(xiàn)類對應(yīng)不同的策略組合模式,聚合不同的策略類基于時間的回滾策略基于

前言

一般都會對應(yīng)用程序日志做回滾處理,本文簡要分析 log4j2 日志回滾實現(xiàn)

觸發(fā)策略

log4j2 使用 TriggeringPolity 接口來抽象日志回滾觸發(fā)策略,使用了 Strategy + Compose 設(shè)計模式

public interface TriggeringPolicy {
    void initialize(final RollingFileManager manager);
    boolean isTriggeringEvent(final LogEvent event);
}

initialize 方法用于初始化策略,isTriggeringEvent 方法用于判斷是否需要回滾,TriggeringPolicy 接口的不同實現(xiàn)類對應(yīng)不同的策略

// 組合模式,聚合不同的策略類
public final class CompositeTriggeringPolicy implements TriggeringPolicy {
    ...
}
// 基于時間的回滾策略
public final class TimeBasedTriggeringPolicy implements TriggeringPolicy {
    ...
}
// 基于文件大小的回滾策略
public final class SizeBasedTriggeringPolicy implements TriggeringPolicy {
    ...
}
基于時間的觸發(fā)策略 回滾策略

log4j2 使用 RolloverStrategy 接口抽象日志回滾策略

public interface RolloverStrategy {
    RolloverDescription rollover(final RollingFileManager manager)
        throws SecurityException;
}

rollover 方法并不直接執(zhí)行回滾操作,而是返回一個 RolloverDescription 接口,該接口用于獲取日志回滾需要進(jìn)行的操作: Action

public interface RolloverDescription {
    String getActiveFileName();
    boolean getAppend();
    Action getSynchronous();
    Action getAsynchronous();
}
回滾動作

log4j2 使用 Action 接口抽象日志回滾過程中的一系列動作,使用了 Command + Compose 設(shè)計模式

public interface Action extends Runnable {
    boolean execute() throws IOException;
    void close();
    boolean isComplete();
}

AbstractAction 類是 Action 接口的抽象實現(xiàn),使用了 Method template 設(shè)計模式,子類通過 override execute 方法執(zhí)行不同的動作

public synchronized void run() {
    if (!interrupted) {
        try {
            execute();
        } catch (final IOException ex) {
            reportException(ex);
        }
        complete = true;
        interrupted = true;
    }
}

public abstract boolean execute() throws IOException;

文件重命名,F(xiàn)ileRenameAction

文件刪除,DeleteAction

文件壓縮,GzCompressAction, ZipCompressAction

聚合,CompositeAction

回滾管理

log4j2 每個 Appender 都有一個 Manager 與之對應(yīng)(多對一), RollingFileAppender 對應(yīng)的 Manager 為RollingFileManager, 它管理著日志的寫入,回滾 .etc,類層次結(jié)構(gòu)

AbstractManager
    OutputStreamManager
        FileManager
            RollingFileManager

非常經(jīng)典的 面向?qū)ο?設(shè)計,單一職責(zé). AbstractManager 保存 Manager 基本信息,例如 name(名字),count(引用計數(shù)),并提供靜態(tài)工廠方法根據(jù)名字獲取 Manager,這個方法同樣值得學(xué)習(xí)和借鑒

    public static  M getManager(final String name,
        final ManagerFactory factory, final T data) {
        // 獲取鎖
        LOCK.lock();
        try {
            @SuppressWarnings("unchecked")
            M manager = (M) MAP.get(name);
            if (manager == null) {
                // 使用工廠類創(chuàng)建具體的 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);
            }
            // 增加引用計數(shù)
            manager.count++;
            return manager;
        } finally {
            // 釋放鎖
            LOCK.unlock();
        }
    }

RollingFileAppender 在 append LogEvent 時會先調(diào)用 RollingFileManager 的 checkRollover 方法嘗試進(jìn)行日志回滾,然后再調(diào)用父類的 append 方法,這種子類通過 override 方法 "攔截" 父類默認(rèn)實現(xiàn)增加自己的處理邏輯的方法很常見

// RollingFileAppender.java

@Override
public void append(final LogEvent event) {
    getManager().checkRollover(event);
    super.append(event);
}

RollingFileManager 的 checkRollover 方法使用上文提到的 觸發(fā)策略類 TriggeringPolicy 判斷是否符合觸發(fā)條件,如果符合調(diào)用 rollover 方法

public synchronized void checkRollover(final LogEvent event) {
    if (triggeringPolicy.isTriggeringEvent(event)) {
        rollover();
    }
}

不帶參數(shù)的 rollover 方法最終調(diào)用帶 RolloverStrategy(回滾策略)類型參數(shù)的版本,為了代碼顯示更加緊湊特意省略掉了日志輸出和異常處理邏輯,有幾個地方值得品味

使用信號量進(jìn)行同步,所以不要太頻繁打 log 觸發(fā)回滾,會 block 線程

同步 Action 在當(dāng)前線程立即執(zhí)行,異步 Action 則啟動一個線程執(zhí)行

如果異步 Action 很可執(zhí)行完畢(某些極端情況),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();
            }
        }
    }
總結(jié)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66823.html

相關(guān)文章

  • Log42j 代碼分析:plugin(插件)機(jī)制

    摘要:前言使用插件機(jī)制加載各種組件,本文簡要分析插件機(jī)制實現(xiàn)注解注解提供了一種便捷的方法將一個類聲明成的插件,比如,單例類用來保存插件信息,暴露了一些方法從配置文件中加載內(nèi)置插件,使用了單例設(shè)計模式線程安全的數(shù)據(jù)結(jié)構(gòu)使用了一些多線程編程的最佳實踐 前言 log4j2 使用插件機(jī)制加載各種組件:appender, logger .etc,本文簡要分析 log4j2 插件機(jī)制實現(xiàn) Plugin ...

    learning 評論0 收藏0
  • 分布式事務(wù)中間件Seata的設(shè)計原理

    摘要:如上圖所示,的實際上是已中間件的形式放在應(yīng)用層,不用依賴數(shù)據(jù)庫對協(xié)議的支持,完全剝離了分布式事務(wù)方案對數(shù)據(jù)庫在協(xié)議支持上的要求。 微信公眾號「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。 在微服務(wù)架構(gòu)體系下,我們可以按照業(yè)務(wù)模塊分層設(shè)計,單獨部署,減輕了服務(wù)部署壓力,也解耦了業(yè)務(wù)的耦合,避免了應(yīng)用逐漸變成一個龐然怪物,從而可以輕松擴(kuò)展,...

    Kylin_Mountain 評論0 收藏0
  • Python模塊分析:第4節(jié)-logging日志模塊

    摘要:上一篇文章模塊分析第節(jié)模塊一日志記錄的級別優(yōu)先級,記錄調(diào)試的詳細(xì)信息,只在調(diào)試時開啟優(yōu)先級,記錄普通的消息,報告錯誤和警告等待。監(jiān)聽端口號上一篇文章模塊分析第節(jié)模塊 上一篇文章:Python模塊分析:第3節(jié)-typing模塊 一、日志記錄的級別 debug:優(yōu)先級10,記錄調(diào)試的詳細(xì)信息,只在調(diào)試時開啟 info:優(yōu)先級20,記錄普通的消息,報告錯誤和警告等待。 warning:優(yōu)...

    MartinHan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<