日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

从 0 到 1,看我玩弄千万日志于股掌

發(fā)布時(shí)間:2025/3/16 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从 0 到 1,看我玩弄千万日志于股掌 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

程序員的工作離不開(kāi)日志。

日志就像一個(gè)筆記本,可以記錄程序運(yùn)行時(shí)的一些信息。

日志文件

通過(guò)日志,我們可以做很多事情。

日志的作用

1. 記錄系統(tǒng)和接口的使用情況,比如請(qǐng)求日志

2. 記錄和分析用戶的行為,比如網(wǎng)站訪問(wèn)日志

3. 調(diào)試程序,和控制臺(tái)的作用類似,但是控制臺(tái)中的內(nèi)容并不會(huì)保存到文件中,而日志可以長(zhǎng)期保存。

4. 幫助我們排查和定位錯(cuò)誤。比如在系統(tǒng)拋出異常時(shí),將異常信息記錄到日志,可以事后復(fù)盤(pán)。

5. 通過(guò)分析日志還能夠優(yōu)化代碼邏輯、提升系統(tǒng)性能、穩(wěn)定性等。

日志雖然有那么多的作用,但如果數(shù)量過(guò)多,也會(huì)讓開(kāi)發(fā)人員感到頭疼。對(duì)于大型的系統(tǒng),程序員們經(jīng)常要看幾千、幾萬(wàn)行日志,常常看日志看到頭暈眼花。

但是,其實(shí)處理日志是有很多技巧的,下面分享自己和日志的故事。

故事分為 7 個(gè)階段,從看日志看到懷疑人生,再到玩弄千萬(wàn)日志于股掌,都做了哪些事情?

和日志的愛(ài)恨情仇

第一階段 無(wú)日志

剛開(kāi)始搭建新的系統(tǒng)時(shí),為了圖個(gè)方便,沒(méi)有給系統(tǒng)接入任何的日志框架,也沒(méi)有記錄任何日志,整個(gè)項(xiàng)目非常的干凈絲滑。需要調(diào)試時(shí)就直接用輸出函數(shù)將信息打印在控制臺(tái),出了異常就直接打印堆棧。

// 輸出調(diào)試 System.out.println("value = " + value); // 出現(xiàn)異常 catch(Exception e) {e.printStackTrace(); }

真是無(wú)事一身輕,爽的不得了!

可惜,好景不長(zhǎng)。在項(xiàng)目上線之后,突然有一天,系統(tǒng)出問(wèn)題了,數(shù)據(jù)查不出來(lái)了,同事找上門(mén)來(lái)了。

笑著說(shuō):“問(wèn)題不大!”

然后登錄服務(wù)器,進(jìn)入項(xiàng)目目錄,瞬間傻眼。

項(xiàng)目目錄依舊干凈絲滑,原來(lái)我特么根本沒(méi)記日志啊!

這下好了,什么問(wèn)題都查不出來(lái)。乖乖地去給項(xiàng)目加上日志功能吧。

第二階段 引入日志類庫(kù)

Java 語(yǔ)言有很多優(yōu)秀的日志類庫(kù),比如 Logback、Log4j2 等,提供了很多記錄和打印日志的方法,非常方便。可以直接使用其中一個(gè)類庫(kù),而無(wú)需自己實(shí)現(xiàn)。此處因?yàn)轫?xiàng)目使用 Spring Boot 框架進(jìn)行開(kāi)發(fā),直接使用其默認(rèn)日志庫(kù) Logback 即可。

使用方式很簡(jiǎn)單,先添加 logback.xml 配置文件,主要配置了日志文件的存儲(chǔ)路徑和格式。Logback 框架還會(huì)自動(dòng)將日志按天進(jìn)行壓縮,并且在一定天數(shù)后進(jìn)行刪除,以節(jié)約磁盤(pán)空間。最大存儲(chǔ)天數(shù)也可以在配置文件中指定。

配置文件大概長(zhǎng)這樣:

<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds"> <include resource="org/springframework/boot/logging/logback/defaults.xml"/><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/application.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- Daily rollover with compression --> <fileNamePattern>log/application-log-%d{yyyy-MM-dd}.gz</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:- } ...</pattern> <charset>UTF-8</charset> </encoder> </appender>... </configuration>

在要打印日志的類上創(chuàng)建一個(gè)日志對(duì)象:

Logger logger = LoggerFactory.getLogger(MyApp.class);

然后就可以使用該對(duì)象去記錄日志啦:

catch(Exception e) {logger.error("app error", e); }

加上配置文件后,啟動(dòng)項(xiàng)目,就可以看見(jiàn)生成的日志文件了。歐耶,下次系統(tǒng)再出問(wèn)題,就不怕缺乏信息來(lái)排錯(cuò)啦!

系統(tǒng)運(yùn)行了一個(gè)小時(shí)之后,同事又找上門(mén)來(lái)了,這次很有底氣,笑著說(shuō):“問(wèn)題不大!”

然后打開(kāi)日志文件一看,傻眼了,有幾千行日志,我怎么知道哪行日志是報(bào)錯(cuò)信息呢?

就這你能秒了我?直接用 Linux 命令過(guò)濾出帶 “ERROR” 字段的日志行就行了~

cat application.log | grep 'ERROR'

雖然解決了問(wèn)題,但是后面每次報(bào)錯(cuò),都要輸一遍這個(gè)篩選命令,而且隨著文件越來(lái)越大,命令執(zhí)行的速度越來(lái)越慢了。

能不能把所有錯(cuò)誤日志和正常日志區(qū)分開(kāi),放在不同的文件中呢?

第三階段 日志分級(jí)

幸運(yùn)的是,一般的日志框架都提供了日志分級(jí)存儲(chǔ)功能,可以通過(guò)修改配置文件來(lái)實(shí)現(xiàn)。

修改 logback.xml 配置文件,將 ERROR(錯(cuò)誤)級(jí)別的日志單獨(dú)輸出到 error.log 文件中,實(shí)現(xiàn)日志分級(jí):

<configuration ...> <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/error.log</file> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:- } [%15.15thread] %-50.50logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> </appender> </configuration>

啟動(dòng)項(xiàng)目,日志按預(yù)期分級(jí)寫(xiě)到了 application.log 和 error.log 兩個(gè)文件。系統(tǒng)再出現(xiàn)異常時(shí),只需打開(kāi) error.log 文件,錯(cuò)誤信息一覽無(wú)遺!

系統(tǒng)運(yùn)行一段時(shí)間后,上線了一個(gè)很重要的服務(wù),記錄了相當(dāng)多的業(yè)務(wù)日志。雖然目前錯(cuò)誤日志可以單獨(dú)查看,但是核心服務(wù)的日志和其他服務(wù)的正常日志都堆積在 application.log 中,想要僅查看核心服務(wù)的日志依舊要采用命令過(guò)濾的方式,比較麻煩。

有沒(méi)有什么辦法,把核心業(yè)務(wù)的日志單獨(dú)記錄到一個(gè)文件中呢?

第四階段 按類隔離

幸運(yùn)的是,Logback 日志框架支持將不同的類產(chǎn)生的日志記錄到不同的文件中,修改配置文件即可。比如將所有 RequestAOP 類產(chǎn)生的請(qǐng)求日志記錄到 request.log 中:

<appender name="REQUEST_HANDLER" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/request.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">... </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:- } [%15.15thread] %-50.50logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> </appender> <!-- logger 中配置類名 --> <logger name="com.yupi.RequestAOP" level="INFO" additivity="false"> <appender-ref ref="REQUEST_HANDLER"/> </logger>

啟動(dòng)項(xiàng)目,自動(dòng)生成了 request.log 文件,打開(kāi)這個(gè)文件,就可以查看所有的請(qǐng)求日志,可以用于流控分析等等,真爽死了!

后來(lái),隨著系統(tǒng)的訪問(wèn)量越來(lái)越大,單臺(tái)服務(wù)器已經(jīng)不能滿足對(duì)并發(fā)的需求,因此又加了三臺(tái)機(jī)器,共同提供服務(wù)。

有一天,系統(tǒng)又出問(wèn)題了,同事找上門(mén)來(lái),心想:信不信分分鐘給你解決 bug!

一頓操作猛如虎,登錄一臺(tái)服務(wù)器查看日志,結(jié)果錯(cuò)誤日志空空如也,比兜兒都干凈。

奇怪了,怎么找不到錯(cuò)誤信息?

對(duì)啊,現(xiàn)在有四臺(tái)機(jī)器,請(qǐng)求可能落在了其他機(jī)器上,因此錯(cuò)誤日志也可能在別的機(jī)器上!

哎,沒(méi)辦法,一臺(tái)一臺(tái)登錄服務(wù)器去找錯(cuò)誤信息吧。

其實(shí)四臺(tái)機(jī)器還能忍,但是后來(lái)隨著并發(fā)量的增大,負(fù)責(zé)的系統(tǒng)已經(jīng)有十臺(tái)機(jī)器了,每次查看日志要依次登錄十臺(tái)機(jī)器去找!而且單個(gè)日志數(shù)據(jù)的量已經(jīng)達(dá)到幾十萬(wàn)行,無(wú)論怎么切分看起來(lái)都太累了。

哦,喬治,這太難受了!有沒(méi)有什么辦法,能讓我在一個(gè)地方集中看日志啊!

要不直接把日志記錄到數(shù)據(jù)庫(kù)中?

不行不行,日志數(shù)據(jù)量太大了,數(shù)據(jù)庫(kù)肯定存不下。而且寫(xiě)入數(shù)據(jù)庫(kù)的速度受到網(wǎng)絡(luò)傳輸?shù)认拗?#xff0c;比較緩慢。

怎么辦啊?算了,先睡一覺(jué)。

第五階段 日志上報(bào)與集中式管理

“嘿,少年,你想要力量么?”

“廢話,誰(shuí)不想要!”

“聽(tīng)說(shuō)過(guò) ELK 么?他會(huì)指引你前進(jìn)的方向。”

從夢(mèng)中驚醒,對(duì)啊,可以用 ELK 搭建一個(gè)分布式日志收集系統(tǒng)啊!

ELK 是 Elasticsearch、Logstash 和 Kibana 的簡(jiǎn)稱,不是單獨(dú)的一個(gè)軟件,而是一整套問(wèn)題的解決方案

Elasticsearch(簡(jiǎn)稱 ES)是全文搜索引擎,能夠?qū)A繑?shù)據(jù)進(jìn)行存儲(chǔ)和高效的搜索。

Logstash 是一個(gè)數(shù)據(jù)管道,能夠從各種數(shù)據(jù)源(比如 MySQL 數(shù)據(jù)庫(kù))收集數(shù)據(jù),將數(shù)據(jù)從一處傳輸?shù)搅硪惶?#xff0c;并加以解析和轉(zhuǎn)換。

Kibana 是數(shù)據(jù)可視化平臺(tái),可以將 Elasticsearch 中存儲(chǔ)的數(shù)據(jù)進(jìn)行展示。在 Kibana 上,我們不僅可以看到所有原始的日志信息,還能夠自定義各種精美直觀的可視化圖表。

通常使用 Logstash 統(tǒng)一收集各個(gè)機(jī)器上的數(shù)據(jù),并傳輸至 Elasticsearch 進(jìn)行存儲(chǔ),最后通過(guò) Kibana 進(jìn)行數(shù)據(jù)展示,之后就可以利用 Kibana 輕松地查看和分析所有的數(shù)據(jù)了。

既然可以解決問(wèn)題,那就接入 ELK 吧~

但是使用 ELK 相當(dāng)于為系統(tǒng)引入了三個(gè)新組件,考慮到系統(tǒng)使用的組件越多,復(fù)雜度越高,就越難維護(hù);而且 Logstash 比較重,對(duì) CPU 和內(nèi)存的占用較高。因此,靈機(jī)一動(dòng),干脆舍棄掉 Logstash,直接將 Elasticsearch 當(dāng)成數(shù)據(jù)庫(kù)來(lái)使用。

先在 Spring Boot 中整合 Elasticsearch,然后將日志數(shù)據(jù)通過(guò)依賴包提供的 API 接口存儲(chǔ)到 Elasticsearch,最后接入 Kibana 進(jìn)行展示。

Maven 引入依賴:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> <version>2.3.4.RELEASE</version> </dependency>

訪問(wèn) ES 的接口:

@Repository public interface UserRepository extends ElasticsearchRepository<HouseIndexTemplate, Long> {}

想法是美好的,現(xiàn)實(shí)卻是賊特么殘酷的。

雖然 Spring Boot 接入 Elasticsearch 的確很方便,但是要把整個(gè)項(xiàng)目中的記日志代碼全部替換成寫(xiě)入 ES 的代碼,對(duì)項(xiàng)目的改動(dòng)和侵入性太大了。而且將日志存入 ES 的耗時(shí)遠(yuǎn)遠(yuǎn)大于原來(lái)異步寫(xiě)入文件的耗時(shí),并發(fā)量很大時(shí),偶爾出現(xiàn)日志寫(xiě)入失敗的情況。因此改代碼改到一半時(shí),就抓狂放棄了,直接把改了的代碼全部還原。

再次陷入沉思,有沒(méi)有一種方式,可以在不改動(dòng)一行代碼的情況下,將日志寫(xiě)入 ES 呢?

第六階段 日志代

如果不改動(dòng)任何代碼,每臺(tái)機(jī)器產(chǎn)生的日志仍然是獨(dú)立記錄到當(dāng)前機(jī)器的日志文件中的,想要通過(guò)一個(gè)界面集中查看各機(jī)器上的日志非常麻煩。

那如果把日志文件中的數(shù)據(jù)自動(dòng)同步到 ES 上,不就能通過(guò) Kibana 方便地查看了么!

誰(shuí)來(lái)做同步這件事呢?難道要我自己寫(xiě)個(gè)定時(shí)任務(wù)程序把日志文件上傳到 ES 上?如果是那樣,我還不如繼續(xù)改原來(lái)項(xiàng)目的代碼。

能不能找個(gè)代理來(lái)幫我做這件事呢?

就像我們每天丟辣雞一樣,把辣雞丟到小區(qū)門(mén)口的辣雞桶就行了,然后辣雞車會(huì)幫我們把辣雞運(yùn)送至辣雞站集中處理。

我們的日志文件相當(dāng)于辣雞,代理就相當(dāng)于辣雞車,而 ES 就相當(dāng)于辣雞站。

通過(guò)百度,發(fā)現(xiàn) ELK 早就升級(jí)為 ElasticStack 了,除了上面說(shuō)的三大組件外,還多了一個(gè) Beats。

Beats 是輕量級(jí)數(shù)據(jù)采集器,針對(duì)不同的數(shù)據(jù)類型提供了不同的組件。

要將日志文件數(shù)據(jù)上傳到 ES 進(jìn)行存儲(chǔ),可以使用 Filebeat。Filebeat 是輕量型日志采集器,其提供了一種輕量型方法,用于轉(zhuǎn)發(fā)和匯總?cè)罩九c文件,讓我們輕松面對(duì)成百上千、甚至成千上萬(wàn)的服務(wù)器、虛擬機(jī)和容器生成的日志。

Filebeat 就相當(dāng)于一個(gè)代理(agent),可以幫助收集各個(gè)機(jī)器上的日志,然后傳輸給 Logstash 進(jìn)行處理或者直接傳輸?shù)?Elasticsearch 進(jìn)行存儲(chǔ)。這樣就完全不用修改項(xiàng)目的代碼!

ElasticStack 整體架構(gòu)如下:

那怎么使用 Filebeat 呢?

其實(shí)非常簡(jiǎn)單,直接將 Filebeat 安裝到日志文件所在的服務(wù)器上,然后在其配置文件中定義輸入(要采集的日志文件路徑)和輸出(要將采集到的數(shù)據(jù)發(fā)送到哪里)即可。比如在下面的配置中,會(huì)采集 system 日志并傳輸給 Logstash:

filebeat.inputs: - type: logpaths:- /var/log/system.logoutput.logstash:hosts: ["127.0.0.1:5044"]

搞定,這下真是爽死了!曾經(jīng)幾千行日志就能將我淹沒(méi),不知所措。而現(xiàn)在,只需要打開(kāi) Kibana 控制臺(tái),動(dòng)動(dòng)手指,就能輕松地查看和分析幾十萬(wàn)、幾百萬(wàn)的日志。

感覺(jué)自己就像一個(gè)大將軍,這些日志是我統(tǒng)治的小兵,都得乖乖聽(tīng)我號(hào)令,好不痛快!

第七階段?完善日志架構(gòu)

利用 ElasticStack,已經(jīng)能夠輕松地集中管理海量的日志,而且 Elasticsearch 支持水平擴(kuò)容,可以應(yīng)對(duì)日志量級(jí)的持續(xù)增大,存?zhèn)€千萬(wàn)條數(shù)據(jù)完全沒(méi)有問(wèn)題。

但是,當(dāng)每秒產(chǎn)生的日志量過(guò)多時(shí),ElasticStack 并不是無(wú)敵的,雖然 Filebeat、Elasticsearch、Kibana 都很強(qiáng)勁,但往往 Logstash 是那阿喀琉斯之踵(或者三娃的屁股)!

因?yàn)?Logstash 要同時(shí)接受多個(gè) Filebeat 采集的日志,機(jī)器越多,部署的 Filebeat 也就越多,Logstash 的壓力就會(huì)越大。雖然也可以像擴(kuò)容 ES 一樣增加 Logstash 的節(jié)點(diǎn)數(shù),但是并不能從根本上解決問(wèn)題,當(dāng)日志量級(jí)增大到一定程度時(shí),不僅是 Logstash,連 ES 集群都有可能撐不住!

因此,我們需要接入一些中間件來(lái)進(jìn)行緩沖,首選的可靠且高性能的消息隊(duì)列 Kafka(依賴分布式協(xié)調(diào)工具 Zookeeper)。

最終,完善的分布式日志收集系統(tǒng)架構(gòu)如下:

至此,終于將千萬(wàn)日志玩弄于股掌,這種感覺(jué)真的是太爽了。

如果你也正在被日志折磨,一定要試著搭建一套完善的日志系統(tǒng)。

最后分享自己記錄日志的經(jīng)驗(yàn)

1. 不要過(guò)度依賴日志,什么都記,日志應(yīng)當(dāng)簡(jiǎn)潔明晰,具有實(shí)際價(jià)值。

2. 在保證可理解的同時(shí)適當(dāng)減少日志的長(zhǎng)度,比如把 this is an apple 簡(jiǎn)化為 apple。

3. 將日志進(jìn)行分級(jí)和分類,僅在開(kāi)發(fā)和測(cè)試環(huán)境輸出 DEBUG 級(jí)別日志,不要在生產(chǎn)環(huán)境中使用。

4. 統(tǒng)一日志的格式,便于后續(xù)處理分析,通常在日志框架配置即可。

5. 不要把日志當(dāng)成存儲(chǔ)數(shù)據(jù)的工具!注意日志信息中不能出現(xiàn)敏感信息,也不要對(duì)外公開(kāi)!


從 0 到 1,經(jīng)歷了七個(gè)階段,成功地玩弄千萬(wàn)日志于股掌。其實(shí),無(wú)論是學(xué)習(xí)還是實(shí)際應(yīng)用,我們都需要有這種持續(xù)實(shí)踐、探索和優(yōu)化的精神

會(huì)當(dāng)凌絕頂,一覽眾山小。

有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)

歡迎大家關(guān)注Java之道公眾號(hào)

好文章,我在看??

總結(jié)

以上是生活随笔為你收集整理的从 0 到 1,看我玩弄千万日志于股掌的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。