習慣每週寫一篇基於技術的帖子,描述一些本身的想法和故事,一方面是整理本身的思路,另外一方面是歡迎拍磚。
這幾天看到一些論壇裏的技術帖子,順便梳理了一下2016全部的技術精英大賽的C++帖子。
把一些好的思想,結合本身的實踐,變爲本身的,非常愉快。
有時間,好好的和Billing的同事去學習一下區塊鏈,那裏真是一個寶庫,呵呵。
說正文吧,
有幾篇帖子說到日誌的難管理,以及問題出現了,運維人員只能打電話給程序,讓他們幫忙分析問題。
這是不少項目的通病。
程序通常喜歡打日誌,這裏打一點,那裏打一點,弄的處處都是日誌。
而實際運維繫統上的人,基本看不懂這些日誌,以致於日積月累,巨大量的日誌,哪一個能夠刪,哪一個不能夠刪?
你讓程序員本身去清理?靠譜麼?可能這個開發說,"那天出問題了我還要用呢,別刪!!"
又好比,週末,程序員正在休息,運維發現問題,打電話給程序,每每最多說的是。"XXX目前不正常", 負責一點的,"XXX進程好像掛了",程序聽了這些,內心多半會說:"和沒說同樣,什麼還得本身去看。"
這樣的問題,我遇到過好屢次了。
運維抱怨研發弄的亂七八糟,而研發抱怨運維只是一個高級傳話筒。
這種隔閡,形成了不少項目的"內傷",這種"內傷"就像大堤的裂縫,那天說不定就形成大事件。
2008年,我開源了一套本身的服務器引擎,基於ACE的。
一開始用途就是想把本身從無盡的IO重寫中拯救出來。當時作了好幾個系統,因爲接口關係,本身寫了無數遍的select epoll。雖然說都那麼幾百行代碼反過來調過去,就是不爽。當時想法很簡單,別人用不用我無論,我只要本身用的爽就好了。反正我是不想再每次都重複寫IO了。
2011年,沒想到民生銀行的一個開發和我聯繫,問我關於這個開源系統的一些實現細節,他們要用。
當時以爲頗有趣,就幫助他們藉助個人工具實現了一些東西,權當提升本身的能力。
其中有一個細節特別值得我記憶和總結。
他們遇到的問題,就是外包的有些模塊,日誌處處都是,再加上各類交接,有些日誌誰也不清楚究竟是什麼,有沒有用。以致於不敢動,身爲運維很是的頭痛。
結合本身的經歷,回想起本身的項目寫的日誌,時間一長,不看代碼,都不知道在幹什麼的,本身有些臉紅。
因而開始思考,如何讓運維硬起來?(好的設計,必須從問題產出者的出發點去思考)
因而設計出了一套運維插件規則,直接理順了當時的整合項目,起到了很好的效果。
今天先說日誌部分。
在我看來,日誌必須是運維的關鍵性檢查指標之一。
甚至,在某些時候,它的強度和研發是一致的。運維懂研發的日誌,那麼更加就能直接的反應問題了。再也不受必須研發出現的制約。
因而我就提出,身爲運維,必須提供一個日誌插件體系,全部的研發必須只能用此體系。
怎麼理解這句話?
也就是,運維提供一個基於C++的日誌系統插件,供研發使用。全部的研發不得使用本身的寫日誌文件。所有必須使用此日誌接口的API實現本身的日誌記錄。(當時的項目是C++的,後來,這個插件擴展到支持Java和python)
再說的細一點,運維必須提供一個日誌記錄的功能代碼集合,甚至是能夠加載的so文件。具體根據項目而定。
分級日誌插件系統就這麼出來了。
首先,我寫的這個日誌插件,就是實現研發平常的日誌記錄。和程序員本身使用的記錄日誌代碼本質上沒有什麼區別。
可是有一條,個人這個插件,支持規則限制。
什麼叫規則限制?
也就是能夠作到,運維能夠任意配置日誌規則,而這個配置規則,徹底不須要研發參與。
怎麼理解?
來看看,個人日誌插件依賴的是一個XML的配置文件。python
這個配置文件,在測試階段,是研發配置的,可是在生產環境,彷佛運維配置的。
這裏有幾個參數稍微解釋一下。
這是描述生成一個日誌文件的具體描述。(文件規則目前是一天一個,以日期爲後綴)
logid是惟一的數字標識,用於匹配指定的日誌文件模塊,下面我會介紹如何使用它。
logtype目前支持兩種狀態,一種是正常流水日誌(0),一種是異常日誌(1)。這個由具體日誌的使用者配置。
Display表示的是當前輸出的日誌,是否輸出到屏幕,仍是輸出到文件。0是文件,1是屏幕
Level當前日誌級別,這個和整個日誌系統互動。一會我會詳細說明。
logname日誌文件名稱,實際生成的日誌名稱的主詞,我會根據這個名稱自動生成一個子目錄,並在裏面根據天天的日誌自動生成日誌信息。
好了,有了這個,再說明一下運維須要設置的關鍵參數
CurrLevel當前日誌插件的運行模式級別,這個怎麼理解?每一個日誌模塊都有一個Level字段。在進程運行的時候,凡是大於此級別的日誌纔會被輸出,這樣作,就等於放權給了運維,你決定,那些級別的日誌在生產環境是輸出成文件的,低於此級別的日誌,所有不會生成文件。
全部的日誌配置文件,所有由運維和研發商量給出定級標準。
而最終日誌配置文件如何配置,由運維給出。
在開發運行過程當中,嚴禁使用諸如printf,fprint之類的東西,或者本身的日誌類。全部日誌輸出必須使用此插件的輸出。
目前對研發,它支持3個API接口。研發不用知道日誌是怎麼實現的,只要先會用就好了。
//nLogType對應logid字段,研發只管寫就好了,你不用管運維是如何配置你的日誌文件級別。
int WriteLog(int nLogType, const char* fmt, ...);
//二進制字段的輸出
int WriteLogBinary(int nLogType, const char* pData, int nLen);
//郵件輸出
int WriteToMail(int nLogType, uint32 u4MailID, char* pTitle, const char* fmt, ...);
這裏三個API基本能知足全部的日誌要求了,文本,二進制,你們都知道。
那麼第三個郵件輸出,是指,你能夠配置一個郵件服務器,當某些日誌產生(研發決定),將會將當前日誌輸出成一封郵件發送出來給指定的郵箱。這個能夠權當報警事件或者事件通知事件來處理,運維在生產環境下,能夠經過xml來配置本身的郵箱實現對研發的某些約定進行郵件通知的機制。
運維在生產環境上配置的日誌插件文件,決定了運維知道哪些日誌是幹什麼的。那麼,爲何要運行級別呢?有意思的來了。
咱們在實際運行任務中,常常會發現某些數據不正常,須要打印出日誌。
可是,若是咱們在全部的地方都打印日誌,就未免太多了,運維人員也會看花眼。
那麼怎麼辦呢?
咱們可讓運維在全部的日誌等級上設置級別。
啓動進程的時候,好比大於5級的日誌,纔會輸出。
那麼當出現問題的時候怎麼辦?
咱們須要運維能夠手動的"降級"當前生產環境的日誌。這個階段,進程不須要中止。發送一個指令,讓日誌插件從5級降到3級,輸出全部大於3級的日誌。
而後能夠導出給研發,或者本身分析後給研發。
導出後,能夠再將日誌級別"升級"爲正常的運維級別(不停機)。保留最少最必要的日誌。
這樣,就實現了,運維提供日誌插件,而研發執行日誌輸出。至於實際生產環境如何配置,研發不用知道,只要協調好了便可。
這個思惟後來被我擴展了,那就是,運維"插件化"的思想。
有時候,並非全部的東西,都須要研發同事去作的,有些東西,徹底能夠從運維出發去作,作成可獨立封裝的類,交付研發,達到本身的目的,誰說運維不會編程?有些高級核心運維寫程序比研發還要強呢。
插件化運維的核心思想,就是把本身要收集的資料收集到本身的手裏。合理的分配權限,日誌可不止只有你研發去看,運維也在看,而更多的是,運維能夠動態的決定日誌的輸出,將極大的提升運維自己的效率。
最後的結果是,民生銀行採用了這套運維架構,直接要求全部的第三方產生使用統一的日誌模塊,並接受日誌管理。極大的減輕了運維"低級傳話筒"的角色,經過日誌的動態"升級" "降級"。甚至能夠在不停機的時候導出必要的分析數據。直接升級到了更高級的管理者。而且,結合日誌,運維能夠開發各類工具實現"表格展現",好比一些通用的開源的圖表展現系統,在這裏就不介紹了,github本身搜搜吧。
運維人員決定,那些日誌,我如今是須要的。而不是研發,畢竟,研發更專一的是實現,而不是運維過程。你們物盡其用,互不干擾。
好了,個人話說完了,但願你們多多提提意見。
哦,固然,我知道,或許大家也想知道代碼是怎麼實現的是吧,沒問題。
附件就是日誌插件的源碼,有興趣能夠玩玩,你玩的越愉快,我越高興。固然,歡迎交流git