<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      前言

      只有光頭才能變強(qiáng)。

      文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y
      <https://github.com/ZhongFuCheng3y/3y>

      記得之前寫過一篇:《阿里巴巴 Java開發(fā)手冊》讀后感
      <https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484402&idx=1&sn=786686c4d2abd958c535065de044701d&chksm=ebd742f3dca0cbe5f6f401e38391369f28287858125d52a1a169523dc4f9600e20335446a629&token=620000779&lang=zh_CN&scene=21#wechat_redirect>
      ,之前自學(xué)時(shí)由于沒怎么接觸過打“日志”,所以《手冊》中的“日志規(guī)約”我就先放一邊去了。

      而之前寫了一篇:在公司做的項(xiàng)目和自己在學(xué)校做的有什么區(qū)別?
      <https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247485368&idx=1&sn=59742409160a103eddaa6ca187a77256&chksm=ebd746b9dca0cfaffd61b35a810d806f7eea67c5a0dec820ae65be093d81abf49ac19ab1248b&token=2078489135&lang=zh_CN#rd>
      中就有提到:公司的項(xiàng)目不會有e.printStackTrace();這種代碼的存在。因?yàn)檫@打印出來的錯(cuò)誤信息沒有日期、等級等等,分析起來不方便。

      在工作中去服務(wù)器上查日志又是一個(gè)非常非常常見的操作,所以當(dāng)初我又寫了一篇 工作中常用到的Linux命令
      <https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247485440&idx=1&sn=85b40c173d66b62b3e870dd0e095c72c&chksm=ebd74901dca0c01727ed2cff30acc5d39948eda5bf4252f1d96526f951591f69edcfccbbad29&token=2078489135&lang=zh_CN#rd>
      ,里邊就談到了查日志時(shí)常用的Linux命令。

      想著,既然接觸日志也有一段時(shí)間了,不妨在回看《手冊》,看看有什么要注意的地方,于是就有了這篇筆記。

      一、Java打日志的基礎(chǔ)

      以前自己自學(xué)的時(shí)候,排查問題只會寫下面的代碼:
      try { // doSomething } catch (Exception e) { e.printStackTrace(); } ----------
      // 查看某個(gè)數(shù)據(jù)的值時(shí): System.out.println(xxxx);
      去到公司就發(fā)現(xiàn)上面的代碼全不見了,剩下的是:
      LOGGER.info("begin to run Java3y:{}", id); ---- LOGGER.error("excepiton occurs
      when run Java3y {}, exception{}", id, e.toString());
      如果使用e.printStackTrace();的話,打印在控制的信息分析不方便:



      而我們將信息分等級和時(shí)間記錄在服務(wù)器的磁盤上,有問題了就可以根據(jù)對應(yīng)的信息去查找相關(guān)的日志(這樣排查起來是十分方便的):



      我們再來看一下一般的日志長什么樣的:



      例如:現(xiàn)在有人來反饋某某某用戶好像收不到短信,給出發(fā)送時(shí)間和用戶ID
      ,我們就可以在日志上找出該用戶在我們系統(tǒng)的發(fā)送狀態(tài)(例如圖上的:state:81,我們就認(rèn)為是發(fā)送成功狀態(tài))

      那么,問題來了,我們在哪打日志?《手冊》上其實(shí)已經(jīng)給出了答案:

      謹(jǐn)慎地記錄日志。生產(chǎn)環(huán)境禁止輸出 debug 日志;有選擇地輸出 info 日志;如果使

      用 warn 來記錄剛上線時(shí)的業(yè)務(wù)行為信息,一定要注意日志輸出量的問題,避免把服務(wù)器磁盤

      撐爆,并記得及時(shí)刪除這些觀察日志。

      大量地輸出無效日志,不利于系統(tǒng)性能提升,也不利于快速定位錯(cuò)誤點(diǎn)。記錄日志時(shí)請思考:這些

      日志真的有人看嗎?看到這條日志你能做什么?能不能給問題排查帶來好處?

      1.1什么叫做 打點(diǎn) ?

      打日志最常見的就是用來打印出程序執(zhí)行時(shí)的相關(guān)信息,用于快速定位問題和排查問題。我一開始也是這么理解的,但是其實(shí)還可以延伸一下。

      我現(xiàn)在搞的那個(gè)系統(tǒng),我們還使用日志在系統(tǒng)的執(zhí)行鏈路上打點(diǎn)。比如說,我現(xiàn)在要推送一條通知消息,通知消息其實(shí)就是下面這種:



      這個(gè)過程大概是如此的:

      * 首先別人調(diào)用我的RPC提供的接口(或者我自己調(diào)用自己的接口),發(fā)現(xiàn)這是一個(gè)通知消息。于是我組裝成對應(yīng)的Task,異步放到消息隊(duì)列中
      * 另一個(gè)系統(tǒng)從消息隊(duì)列中取出Task,對這個(gè)Task進(jìn)行業(yè)務(wù)的處理(比如說是否夜間屏蔽,是否強(qiáng)制發(fā)送等等),然后調(diào)用HTTP接口把這個(gè)Task交給下游
      * 下游做的事其實(shí)也很多,整塊鏈路很長(比如要調(diào)用SDK的庫,Android和IOS又做不同的處理)


      而我們又希望在推送完了之后能統(tǒng)計(jì)出一些指標(biāo)(曝光量,點(diǎn)擊率,轉(zhuǎn)化率)等等。于是乎,就需要在一些關(guān)鍵的位置上打一個(gè)日志(專業(yè)點(diǎn)叫做打點(diǎn))

      在整塊鏈路都打通了以后,將這些點(diǎn)位
      (日志)收集起來,放到實(shí)時(shí)流式處理平臺(storm/flink)上清洗/過濾。如果是實(shí)時(shí)需要用到的放到Redis,離線的放在Hive。

      二、手冊規(guī)范

      2.1 使用門面模式的日志框架

      【強(qiáng)制】應(yīng)用中不可直接使用日志系統(tǒng)(Log4j、Logback)中的 API,而應(yīng)依賴使用日志框架

      SLF4J 中的 API,使用門面模式的日志框架,有利于維護(hù)和各個(gè)類的日志處理方式統(tǒng)一。

      門面模式我之前也寫過一篇筆記:三分鐘學(xué)會門面模式!
      <https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484556&idx=1&sn=920d00416ef76669b59937c771526345&chksm=ebd7458ddca0cc9bdda893fa034da354d97cfd0e96bdaa6ccfc2a94a0ba85a564415efa3c6ba&token=1712662964&lang=zh_CN#rd>

      其實(shí)說白了就是希望抽象出一層API,能夠在切換具體日志框架的時(shí)候不需要大面積更改。

      這個(gè)我們可以按學(xué)JDBC的時(shí)候去理解:

      無論我是接入MySQL、Oracle還是SQL Server,但我的接口永遠(yuǎn)都是那一套,切換數(shù)據(jù)庫時(shí)不需要更改我的Java API

      看了一下公司的項(xiàng)目,采用的是SLF4J+Logback

      2.2 調(diào)用RPC接口使用Throwable類攔截

      【強(qiáng)制】在調(diào)用 RPC、二方包、或動態(tài)生成類的相關(guān)方法時(shí),捕捉異常必須使用 Throwable

      類來進(jìn)行攔截。

      之前在排查問題的時(shí)候,有個(gè)問題死活排不出來,DeBug的時(shí)候一直沒進(jìn)catch模塊。后來我學(xué)長就說:“要不你改成Throwable試試?
      try { } catch (Throwable e) { }

      我就很疑問,說:“為啥要改成Throwable呢?我們用Exception不就可以捕獲所有的異常了么,Exception是Throwable的一個(gè)子類,但Exception已經(jīng)是包含所有的Java異常了呀”

      眾所周知,Throwable有兩個(gè)子類:

      * Error(一般我們都會把這個(gè)忽略掉...一般情況下出現(xiàn)了Error程序都運(yùn)行不起來)
      * Exception The Throwable class is the superclass of all errors and
      exceptions in the Java language
      在《手冊》上也有對上面的規(guī)則進(jìn)行說明:

      說明:通過反射機(jī)制來調(diào)用方法,如果找不到方法,拋出 NoSuchMethodException。什么情況會拋出

      NoSuchMethodError 呢?二方包在類沖突時(shí),仲裁機(jī)制可能導(dǎo)致引入非預(yù)期的版本使類的方法簽名不匹

      配,或者在字節(jié)碼修改框架(比如:ASM)動態(tài)創(chuàng)建或修改類時(shí),修改了相應(yīng)的方法簽名。這些情況,即

      使代碼編譯期是正確的,但在代碼運(yùn)行期時(shí),會拋出 NoSuchMethodError。

      大概的意思就是說:調(diào)用 RPC、二方包、或動態(tài)生成類的相關(guān)方法時(shí),可能直接拋出的是Error,而catch Exception是無法捕獲得到的。

      想看例子的同學(xué)可以看看這篇文章:

      * https://zhuanlan.zhihu.com/p/57950399
      <https://zhuanlan.zhihu.com/p/57950399>
      最后

      參考資料(阿里巴巴開發(fā)手冊下載地址):

      * https://github.com/alibaba/p3c <https://github.com/alibaba/p3c>
      查閱資料時(shí)發(fā)現(xiàn)的好文:

      *
      https://www.cnblogs.com/chenhongliang/p/5312517.html
      <https://www.cnblogs.com/chenhongliang/p/5312517.html>

      *
      https://www.cnblogs.com/crazyacking/p/5456347.html
      <https://www.cnblogs.com/crazyacking/p/5456347.html>

      樂于輸出干貨的Java技術(shù)公眾號:Java3y。公眾號內(nèi)有200多篇原創(chuàng)技術(shù)文章、海量視頻資源、精美腦圖,關(guān)注即可獲?。?br>


      覺得我的文章寫得不錯(cuò),點(diǎn)贊!

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          爱搞视频在线观看 | 国精产品秘 成人一区二视频 | 一区二区三区在线免费观看 | 人妻毛片A一级毛片免费看 | 亚洲激情无码视频 | 老骚逼 | 久久内射视频 | 欧美性做爰又大又粗又长 | 操逼网站网址 | 真实夫妇交换性经过 |