.NET下日誌系統的搭建——log4net+kafka+elk#
前言#
咱們公司的程序日誌以前都是採用log4net記錄文件日誌的方式(有關log4net的簡單使用能夠看我另外一篇博客),可是隨着後來咱們團隊愈來愈大,項目也愈來愈大,咱們的用戶量也愈來愈多。慢慢系統就暴露了不少問題,這個時候咱們的日誌系統已經不能知足咱們的要求。其主要有下面幾個問題:html
- 隨着咱們訪問量的增長,咱們的日誌文件急劇增長
- 多且亂的文件日誌,難以讓咱們對程序進行排錯
- 文件日誌的記錄耗用咱們應用服務器的資源,致使咱們的應用服務器的處理用戶請求的能力降低
- 咱們的日誌分佈在多臺應用服務器上,當程序遇到問題時,咱們的程序員都須要找運維人員要日誌,隨着團隊愈來愈大,問題愈來愈多,因而致使了程序員們排隊找運維要日誌,解決問題的速度急劇降低!
起初,用戶量不大的時候,上面的問題還能容忍。但任何一種小問題都會在用戶量訪問量變大的時候急劇的放大。終於在幾波推廣活動的時候,很悲劇的咱們又不得不天天深夜加班來爲咱們以前對這些問題的不重視來買單。因而,在推廣活動結束以後,在咱們的程序員獲得一絲喘息的機會時,我決定來搭建一個咱們本身的日誌系統,改善咱們的日誌記錄方式。根據以上問題分析咱們的日誌系統須要有如下幾點要求:java
- 日誌的寫入效率要高不能對應用服務器形成太大的影響
- 要將日誌集中在一臺服務器上(或一組)
- 提供一個方便檢索分析的可視化頁面(這個最重要,再也受不了天天找運維要日誌,拿到一堆文件來分析的日子了!)
一開始想要藉助log4net AdoAppender把咱們的日誌寫到數據庫裏,而後咱們開發一個相應的功能,來對咱們的日誌來進行查詢和分析。但考慮到寫入關係數據庫的性能問題,就放棄了,但有一個替代方案,就是寫入到Mongo中,這樣就解決了提升了必定的性能。但也須要咱們開發一個功能來查詢分析。這個時候從網上找了許多方案:程序員
//方案1:這是咱們現有的方案,優勢:簡單 缺點:效率低,不易查詢分析,難以排錯... service-->log4net-->文件 //方案2:優勢:簡單、效率高、有必定的查詢分析功能 缺點:增長mongodb,增長必定複雜性,查詢分析功能弱,須要投入開發精力和時間 service-->log4net-->Mongo-->開發一個功能查詢分析 //方案3:優勢:性能很高,查詢分析及其方便,不須要開發投入 缺點:提升了系統複雜度,須要進行大量的測試以保證其穩定性,運維須要對這些組件進行維護監控... service-->log4net-->kafka-->logstash-->elasticsearch-->kibana搜索展現 //其它方案 service-->log4net-->文件-->filebeat-->logstash-->elstaicsearch-->kibana service-->log4net-->文件-->filebeat-->elstaicsearch-->kibana service-->log4net-->文件-->logstash-->elstaicsearch-->kibana
最終和團隊交流後決定採用方案2和方案3的結合,我增長了一個log4net for mongo的appender(這個appender,nuget上也有),另外咱們的團隊開發一個能支持簡單查詢搜索的功能。我同步來搭建方案3。關於方案2就很少介紹了,很簡單。主要提一提方案3。mongodb
一. ELKB簡介#
- Elastic Search: 從名稱能夠看出,Elastic Search 是用來進行搜索的,提供數據以及相應的配置信息(什麼字段是什麼數據類型,哪些字段能夠檢索等),而後你就能夠自由地使用API搜索你的數據。
- Logstash:。日誌文件基本上都是每行一條,每一條裏面有各類信息,這個軟件的功能是將每條日誌解析爲各個字段。
- Kibana:提供一套Web界面用來和 Elastic Search 進行交互,這樣咱們不用使用API來檢索數據了,能夠直接在 Kibana 中輸入關鍵字,Kibana 會將返回的數據呈現給咱們,固然,有不少漂亮的數據可視化圖表可供選擇。
- Beats:安裝在每臺須要收集日誌的服務器上,將日誌發送給Logstash進行處理,因此Beats是一個「搬運工」,將你的日誌搬運到日誌收集服務器上。Beats分爲不少種,每一種收集特定的信息。經常使用的是Filebeat,監聽文件變化,傳送文件內容。通常日誌系統使用Filebeat就夠了。
二. kafka簡介#
2.1 簡介#
kafka是一種高吞吐量的分佈式發佈訂閱消息系統,它能夠處理消費者規模的網站中的全部動做流數據。這種動做(網頁瀏覽,搜索和其餘用戶的行動)是在現代網絡上的許多社會功能的一個關鍵因素。這些數據一般是因爲吞吐量的要求而經過處理日誌和日誌聚合來解決。docker
2.2 適用場景#
-
Messaging
對於一些常規的消息系統,kafka是個不錯的選擇;partitons/replication和容錯,可使kafka具備良好的擴展性和性能優點.不過到目前爲止,咱們應該很清楚認識到,kafka並無提供JMS中的"事務性""消息傳輸擔保(消息確認機制)""消息分組"等企業級特性;kafka只能使用做爲"常規"的消息系統,在必定程度上,還沒有確保消息的發送與接收絕對可靠(好比,消息重發,消息發送丟失等)數據庫 -
Websit activity tracking
kafka能夠做爲"網站活性跟蹤"的最佳工具;能夠將網頁/用戶操做等信息發送到kafka中.並實時監控,或者離線統計分析等json -
Log Aggregation
kafka的特性決定它很是適合做爲"日誌收集中心";application能夠將操做日誌"批量""異步"的發送到kafka集羣中,而不是保存在本地或者DB中;kafka能夠批量提交消息/壓縮消息等,這對producer端而言,幾乎感受不到性能的開支.此時consumer端可使hadoop等其餘系統化的存儲和分析系統.bootstrap
3、log4net+ELK+Kafka日誌系統#
3.1.簡介#
從上咱們能夠了解到,咱們能夠增長一個log4net kafkaappender 日誌生產者經過這個appender將日誌寫入kafka,因爲kafka批量提交、壓縮的特性,所以對咱們的應用服務器性能的開支很小。日誌消費者端使用logstash訂閱kafka中的消息,傳送到elasticsearch中,經過kibana展現給咱們。同時咱們也能夠經過kibana對咱們的日誌進行統計分析等。恰好能夠解決咱們上面的一些問題。整個流程大體以下圖:瀏覽器
關於log4net for kafka appender,我本身寫了一個,nuget上也有現成的包,你們須要能夠去nuget上找一找。
3.2.搭建#
簡單介紹一下搭建,搭建過程當中採用Docker。
3.2.1 docker 安裝kafka#
//下載 //下載zookeeper docker pull wurstmeister/zookeeper //下載kafka docker pull wurstmeister/kafka:2.11-0.11.0.3
//啓動 //啓動zookeeper docker run -d --name zookeeper --publish 2181:2181 --volume /etc/localtime:/etc/localtime wurstmeister/zookeeper //啓動kafka docker run -d --name kafka --publish 9092:9092 \ --link zookeeper \ --env KAFKA_ZOOKEEPER_CONNECT=192.168.121.205:2181 \ --env KAFKA_ADVERTISED_HOST_NAME=192.168.121.205 \ --env KAFKA_ADVERTISED_PORT=9092 \ --volume /etc/localtime:/etc/localtime \ wurstmeister/kafka:2.11-0.11.0.3
//測試 //建立topic bin/kafka-topics.sh --create --zookeeper 192.168.121.205:2181 --replication-factor 1 --partitions 1 --topic mykafka //查看topic bin/kafka-topics.sh --list --zookeeper 192.168.121.205:2181 //建立生產者 bin/kafka-console-producer.sh --broker-list 192.168.121.205:9092 --topic mykafka //建立消費者 bin/kafka-console-consumer.sh --zookeeper 192.168.121.205:2181 --topic mykafka --from-beginning
3.2.2 Docker安裝ELK#
//1.下載elk docker pull sebp/elk
//2.啓動elk //Elasticsearch至少須要單獨2G的內存 //增長了一個volume綁定,以避免重啓container之後ES的數據丟失 docker run -d -p 5044:5044 -p 127.0.0.1:5601:5601 -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -v /var/data/elk:/var/lib/elasticsearch --name=elk sebp/elk
//若啓動過程出錯通常是由於elasticsearch用戶擁有的內存權限過小,至少須要262144 切換到root用戶 執行命令: sysctl -w vm.max_map_count=262144 查看結果: sysctl -a|grep vm.max_map_count 顯示: vm.max_map_count = 262144
上述方法修改以後,若是重啓虛擬機將失效,因此:
解決辦法:
在 /etc/sysctl.conf文件最後添加一行 vm.max_map_count=262144 便可永久修改
啓動成功以後訪問:http://:5601 看到kibana頁面則說明安裝成功
配置使用
//進入容器 docker exec -it <container-name> /bin/bash
//執行命令 /opt/logstash/bin/logstash -e 'input { stdin { } } output { elasticsearch { hosts => ["localhost"] } }' /* 注意:若是看到這樣的報錯信息 Logstash could not be started because there is already another instance using the configured data directory. If you wish to run multiple instances, you must change the "path.data" setting. 請執行命令:service logstash stop 而後在執行就能夠了。 */
測試
當命令成功被執行後,看到:Successfully started Logstash API endpoint {:port=>9600} 信息後,輸入:this is a dummy entry 而後回車,模擬一條日誌進行測試。
打開瀏覽器,輸入:http://:9200/_search?pretty 如圖,就會看到咱們剛剛輸入的日誌內容。
3.2.3 logstash-kafka配置實例#
這是我測試用的一個配置文件。
input {
kafka{
//此處注意:logstash5.x版本之前kafka插件配置的是zookeeper地址,5.x之後配置的是kafka實例地址 bootstrap_servers =>["192.168.121.205:9092"] client_id => "test" group_id => "test" consumer_threads => 5 decorate_events => true topics => "logstash" } } filter{ json{ source => "message" } } output { elasticsearch { hosts => ["192.168.121.205"] index=> "hslog_2" codec => "json" } }
配置文件啓動logstash方式
/opt/logstash/bin/logstash -f "配置文件地址"
結束語#
如上,咱們的日誌系統基本搭建完畢,固然還有不少關於kafka,logstash,elstaicsearch,kibana的使用,以及咱們使用的一些問題,你們本身嘗試着搭建一下。固然,沒有最好的方案,建議你們結合本身公司和系統的現實狀況,尋找和選擇解決方案。能用簡單的方案解決問題,就不要使用複雜的方案。由於複雜的方案在解決問題的同時,也會給咱們帶來其餘的問題。就像咱們這個方案,雖然解決了咱們當時的問題,可是也增長了咱們系統的複雜度,例如:這其中的每個組件出了問題,都將致使咱們的日誌系統不可用......,此外,工欲善其事必先利其器,咱們雖然解決了器的問題,可是要想"善咱們的事"還有很長的路要走,由於究其根本,日誌記不記錄,在什麼地方記錄,記錄什麼等級的日誌,仍是由咱們選擇去記錄。日誌記錄無規範、亂記、瞎記,如何規範日誌的記錄纔是是咱們接下來要解決的大問題!歡迎你們留言,探討這些問題!