小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

事件驅(qū)動的異步化框架:event4j

 WindySky 2017-09-03

event4j是一個實現(xiàn)了事件驅(qū)動異步化的輕量級框架,可幫助我們實現(xiàn)以事件驅(qū)動為中心的應(yīng)用,采用分派事件和監(jiān)聽事件的方式,使處理事務(wù)的上下游各個組件之間不直接發(fā)生交互,降低耦合,擴(kuò)展方便。另外,event4j讓事務(wù)的每一個處理環(huán)節(jié)都是異步化且并行執(zhí)行,使應(yīng)用的吞吐量大大提升。

實現(xiàn)一個功能時,傳統(tǒng)的做法是串行執(zhí)行一系列的操作。例如:一個用戶登陸的功能,在校驗賬號和密碼成功后,還會進(jìn)行以下操作:

  • 寫業(yè)務(wù)統(tǒng)計日志。
  • 通知相關(guān)的組件,某個賬號登陸了,并且將賬號、登陸時間、登陸的環(huán)境信息都發(fā)送過去。
  • 將一條記錄到賬號的登陸歷史中。

我們的做法通常是這樣的:在成功校驗賬號和密碼后,再寫一堆代碼來實現(xiàn)上述的三個操作。所有的操作都是串行的,如下圖所示:

事件驅(qū)動的異步化框架:event4j - 傲風(fēng) - 0與1構(gòu)筑世界,程序員創(chuàng)造時代
 

這樣做沒錯,但隨著系統(tǒng)的演進(jìn),為了統(tǒng)計需要或相關(guān)聯(lián)系統(tǒng)的業(yè)務(wù)需要做的一些額外操作,不斷地在功能點(diǎn)中增加許多與用戶登陸無關(guān)但有必要的操作。這樣,在賬號登陸的功能中摻入了許多實現(xiàn)額外功能的代碼,使之變得臃腫。而且,在系統(tǒng)并發(fā)量高的情況下會帶來一個問題:賬號登陸變慢。

面對變量的問題,我們就會開始實現(xiàn)異步化(推薦用threadpool4j),把這些額外的操作變成異步任務(wù),減少處理時間,提升賬號登陸的響應(yīng)速度。
把一些操作異步化后,代碼的主線邏輯更加清晰,臃腫的情況有很大改善。但還是會有不少處理異步任務(wù)相關(guān)的代碼在其中,那有沒有可能更進(jìn)一步,在用戶的登陸操作中不出現(xiàn)這些異步任務(wù)的代碼呢?答案是:用事件驅(qū)動。

用event4j可以非常優(yōu)雅地解決這個問題,不僅使處理賬號登陸的代碼變得非常簡潔,而且將來擴(kuò)展方便。首先,將賬號及其相關(guān)信息生成一個事件并分派出去,然后寫三個處理器監(jiān)聽這個事件即可,如果后續(xù)還有類似的在賬號登陸成功后要做一些額外的操作,再寫一個處理器監(jiān)聽這個事件就行。這樣,賬號登陸的功能中不再包含實現(xiàn)額外操作的代碼,并且通過event4j將登陸操作與其他的額外操作解耦。如下圖所示:

事件驅(qū)動的異步化框架:event4j - 傲風(fēng) - 0與1構(gòu)筑世界,程序員創(chuàng)造時代

一、編譯event4j

1、獲取threadpool4j源碼。

git clone https://github.com/aofeng/event4j

2、編譯源碼生成jar。

進(jìn)入項目根目錄,執(zhí)行ant腳本:

ant

會生成一個dist目錄,下面有兩個文件。如:

event4j-1.0.0-src.jar 源碼jar
event4j-1.0.0.jar 用于發(fā)布的二進(jìn)制jar

二、event4j入門指南

為了更好地理解event4j,通過實現(xiàn)一個簡單且可容易實現(xiàn)的實例來展示event4j的用法:

用例

有一個日志文件LoginInfoRecords.txt,里面記錄著用戶的登陸信息,每行共4個字段,用符號“`”隔開,分別是:登陸時間、來源IP、賬號、登陸結(jié)果。從日志文件中統(tǒng)計總登陸次數(shù)和登陸成功率。

實現(xiàn)思路

1、實現(xiàn)一個文件讀取器,按行讀取。每讀取一行,產(chǎn)生一個“完成讀取一行(ReadLineComplete)”的事件。
2、實現(xiàn)一個格式轉(zhuǎn)換器,監(jiān)聽事件“完成讀取一行”。完成格式轉(zhuǎn)換后,產(chǎn)生一個“完成格式轉(zhuǎn)換(LoginInfoCodecComplete)”的事件。
3、實現(xiàn)兩個數(shù)據(jù)處理器:登陸次數(shù)統(tǒng)計器、登陸成功率統(tǒng)計器,它們監(jiān)聽事件“完成格式轉(zhuǎn)換”。

事件驅(qū)動的異步化框架:event4j - 傲風(fēng) - 0與1構(gòu)筑世界,程序員創(chuàng)造時代
 

編寫程序

1、依賴關(guān)系及其配置。
event4j依賴threadpool4j,需要的jar列表如下:

  • common4j-0.1.0.jar
  • commons-lang-2.6.jar
  • log4j-1.2.16.jar
  • threadpool4j-1.0.0.jar

2、配置threadpool4j。
在應(yīng)用的CLASSPATH的任意路徑(如:應(yīng)用的classes目錄)下新文本文件建threadpool4j.xml,其內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<threadpool4j>
    <pool name="default">
        <corePoolSize>30</corePoolSize>
        <maxPoolSize>150</maxPoolSize>
        <!-- 線程空閑存話的時間。單位:秒 -->
        <keepAliveTime>5</keepAliveTime>
        <workQueueSize>100000</workQueueSize>
    </pool>
</threadpool4j>

3、配置event4j。
在應(yīng)用的CLASSPATH的任意路徑(如:應(yīng)用的classes目錄)下新建文本文件event4j.xml的配置文件,其內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<events>
    <!-- 
    <event>中的type屬性表示事件類型,可以有1至多個listener。
    <listener>沒有屬性,只有value,value值是事件監(jiān)聽器的完整類名。
     -->

    <!-- 事件:完成讀取一行 -->
    <event type="ReadLineComplete">
        <listener>cn.aofeng.event4j.example.LoginInfoCodec</listener>
    </event>

    <!-- 事件:完成格式轉(zhuǎn)換 -->
    <event type="LoginInfoCodecComplete">
        <listener>cn.aofeng.event4j.example.LoginCountProcessor</listener>
        <listener>cn.aofeng.event4j.example.LoginSuccessRateProcessor</listener>
    </event>

</events>

4、實現(xiàn)文件讀取器。

// 1. 初始化event4j
EventDispatch.getInstance().init();

// 2. 事件分派
BufferedReader reader = null;
String line = "";
try {
    InputStream ins = Event4JExample.class.getResourceAsStream("/cn/aofeng/event4j/example/LoginRecords.txt");
    reader = new BufferedReader(new InputStreamReader(ins));
    do {
        line = reader.readLine();
        if (StringUtils.isBlank(line)) {
            continue;
        }
        Event<String> event = new Event<String>("ReadLineComplete", line);
        EventDispatch.getInstance().dispatch(event);
    } while (null != line);
} catch (Exception e) {
    _logger.error("read file [CLASSPATH/cn/ofeng/event4j/example/LoginRecords.txt] occurs error", e);
} finally {
    try {
        reader.close();
    } catch (IOException e) {
        // nothing
    }
} // end of try catch finally block

// 3. 關(guān)閉event4j,釋放資源
EventDispatch.getInstance().destroy();

其源碼可查看文件Event4JExample.java

5、實現(xiàn)格式轉(zhuǎn)換器。

/**
 * 數(shù)據(jù)轉(zhuǎn)換器:將一行字符串轉(zhuǎn)換成{@link LoginInfo}對象。
 * 
 * @author <a href="mailto:aofengblog@163.com">聶勇</a>
 */
public class LoginInfoCodec extends AbstractEventListener<String> {

    @Override
    public void execute(Event<String> event) {
        // 1. 校驗數(shù)據(jù)的有效性
        String line = event.getData();
        if (StringUtils.isBlank(line)) {
            return;
        }

        // 2. 將行數(shù)據(jù)轉(zhuǎn)換成Java對象
        String[] datas = line.split("`");
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setLoginTime(Long.parseLong(datas[0]));
        loginInfo.setIp(datas[1]);
        loginInfo.setUserName(datas[2]);
        loginInfo.setResultCode(Integer.parseInt(datas[3]));

        //  3. 生成事件并分派
        Event<LoginInfo> loginInfoEvent = new Event<LoginInfo>("LoginInfoCodecComplete", loginInfo);
        EventDispatch.getInstance().dispatch(loginInfoEvent);
    }

}

其源碼可查看文件LoginInfoCodec.java

6、實現(xiàn)登陸次數(shù)統(tǒng)計器

/**
 * 登陸次數(shù)統(tǒng)計器。
 * 
 * @author <a href="mailto:aofengblog@163.com">聶勇</a>
 */
public class LoginCountProcessor extends  AbstractEventListener<LoginInfo> {

    private long _count;

    @Override
    public void execute(Event<LoginInfo> event) {
        if (null == null) {
            return;
        }

        _count ++;

        // 后續(xù)如何輸出數(shù)據(jù)可自行處理 。。。
    }

}

其源碼可查看文件LoginCountProcessor.java

7、實現(xiàn)登陸成功率統(tǒng)計器

/**
 * 登陸成功率統(tǒng)計器。
 * 
 * @author <a href="mailto:aofengblog@163.com">聶勇</a>
 */
public class LoginSuccessRateProcessor extends  AbstractEventListener<LoginInfo> {

    private long _total;

    private long _success;

    @Override
    public void execute(Event<LoginInfo> event) {
        if (null == null) {
            return;
        }

        _total ++;
        if (1 == event.getData().getResultCode()) {
            _success ++;
        }

        // 后續(xù)如何輸出數(shù)據(jù)可自行處理 。。。
    }

}

其源碼可查看文件LoginSuccessRateProcessor.java


<正文結(jié)束>

文章聲明


作者:傲風(fēng)(aofengblog@163.com)       編寫時間:2014年11月14日

網(wǎng)址:http://aofengblog.blog.163.com

作者保留所有權(quán)利,轉(zhuǎn)載請保留文章全部內(nèi)容或者說明原作者和轉(zhuǎn)載地址!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多