歷史
在幾年前,我們使用了一個(gè)根據(jù)msyslog修改過(guò)來(lái)的版本,它也是一個(gè)插件化的架構(gòu)。但是,和很多syslog的實(shí)現(xiàn)者一樣,它也是基于BSD的syslog的單線(xiàn)程架構(gòu)實(shí)現(xiàn)的,所以它繼承了所有syslog的缺點(diǎn)。我們很快就發(fā)現(xiàn)我們需要一個(gè)更好的日志解決方案。接著,我們就開(kāi)始尋找其他解決方案,有很多像rsyslog、syslog-ng這樣的方案是可以拿來(lái)代替msyslog的,但是大多數(shù)方案還是單線(xiàn)程的,并且不是原生支持Windows系統(tǒng)的。于是我們就開(kāi)始開(kāi)發(fā)NxLog,Nxlog從2009年開(kāi)始開(kāi)發(fā),當(dāng)時(shí)是一個(gè)閉源項(xiàng)目,知道2011年我們才放出了開(kāi)源的CE版本
概念
大多數(shù)日志處理程序都有很類(lèi)似的概念,Input是用于從數(shù)據(jù)源讀取數(shù)據(jù)的,然后就會(huì)對(duì)日志進(jìn)行出來(lái),最早會(huì)通過(guò)Output送到其他的地方。當(dāng)一個(gè)事件在應(yīng)用程序或者設(shè)備上觸發(fā)了,一個(gè)相關(guān)的日志消息也會(huì)被觸發(fā)。這種日志我們通常稱(chēng)之為event log。這些日志信息通常都有不同的格式,也會(huì)有不同的協(xié)議。但是有一點(diǎn)他們是相同的,所有的Event log都包含了一些重要的信息,例如時(shí)間、IP、用戶(hù)等。這樣看的話(huà),事件也可以變成一個(gè)Key-Value的數(shù)據(jù)結(jié)構(gòu),我們通常稱(chēng)之為字段。例如原始日志
<30>Nov 21 11:40:27 log4ensics sshd[26459]:
Accepted publickey for log4ensics from 192.168.1.1 port 41193 ssh2
變成鍵值對(duì)之后
AuthMethod publickey
SourceIPAddress 192.168.1.1
AccountName log4ensics
SyslogFacility DAEMON
SyslogSeverity INFO
Severity INFO
EventTime 2009-11-21 11:40:27.0
Hostname log4ensics
ProcessID 26459
SourceName sshd
Message Accepted publickey for log4ensics from 192.168.1.1 port 41193 ssh2
在nxlog里面有個(gè)特殊的字段,叫做$raw_event,這個(gè)字段會(huì)被UDP、TCP、File等處理模塊所使用,他們讀入數(shù)據(jù)之后,會(huì)對(duì)這個(gè)字段進(jìn)行填充。
架構(gòu)
由于整體的架構(gòu)是可插拔式的,NXLog的架構(gòu)可以讀取任何類(lèi)型的輸入,并且轉(zhuǎn)換成各種類(lèi)型的日志并且輸出。不同的輸入、轉(zhuǎn)換、輸出是可以同時(shí)使用的

NXLog Core主要負(fù)責(zé)讀取配置文件,監(jiān)控文件、Socket還有內(nèi)部事件的變化。它是一個(gè)基于事件的架構(gòu),所有的模塊都可以給core調(diào)度。nxlog是個(gè)多線(xiàn)程的應(yīng)用程序,主函數(shù)負(fù)責(zé)監(jiān)控文件和Socket。有一個(gè)線(xiàn)程專(zhuān)門(mén)負(fù)責(zé)處理內(nèi)部事件,它在下一個(gè)事件進(jìn)來(lái)之前都一直保持休眠狀態(tài)。
Nxlog實(shí)現(xiàn)了一個(gè)線(xiàn)程池的模型,這讓nxlog core可以集中控制所有的事件,也能讓事件具備優(yōu)先級(jí),用于處理Socket和文件的模塊是用非阻塞式IO進(jìn)行編寫(xiě)的,能夠保證線(xiàn)程永遠(yuǎn)都是非阻塞的。處理Socket和文件的模塊,使用非阻塞的方式來(lái)確保工作線(xiàn)程不會(huì)阻塞。屬于同一模塊的每一個(gè)事件都是按順序執(zhí)行的,而不是同時(shí)執(zhí)行的。這確保了消息的順序被保留,并有一個(gè)很大的好處,不必處理模塊中的并發(fā)問(wèn)題。
當(dāng)輸入模塊接受到了數(shù)據(jù),它將會(huì)創(chuàng)建一個(gè)由原始日志和額外的字段組成的結(jié)構(gòu)體,然后它將會(huì)被放到下一個(gè)處理模塊的隊(duì)列中。下一個(gè)模塊可以是處理數(shù)據(jù)模塊或者是一個(gè)輸出模塊。當(dāng)然,輸入或者輸出模塊也可以嵌入一些NXlog語(yǔ)言的處理代碼。不同的是這些處理模塊會(huì)在另外一個(gè)線(xiàn)程中運(yùn)行,考慮到日志處理模塊也可能會(huì)被調(diào)用,這樣的做法可以更好的發(fā)揮多核CPU的性能