無異常日誌,就不能排查問題了???

小聲逼逼

衆所周知,日誌是排查問題的重要手段。關於日誌設計,以及怎麼根據從【用戶報障】環節開始到秒級定位問題這個咱們下一期說(絕非套路),這一期,主要講一下,在沒有異常日誌的狀況下,如何定位問題。沒有日誌當真能排查問題,不會是標題黨吧!git

圖片

案例一

從最大的同性交友網站中拉取【dubbo-spring-boot-project】的代碼。github

圖片

而後把demo跑起來。面試

本場景是由真實案例改編,由於公司代碼比較複雜也不方便透露,而這個demo在github上你們都能找到,既保證了原汁原味,又能讓你們方便本身體驗排查過程。spring

好了,咱們先設置owner = "feichao",而後看一下控制檯編程



一切正常springboot

那麼,當我設置成owner = "feichaozhenshuai!",再啓動微信


看似一切都正常,那麼,咱們到控制檯一看。app


什麼狀況,怎麼就沒owner了?異步

這是在哪一個環節出問題了?其實肥朝當初在公司遇到這個問題的時候,場景比這個複雜得多。由於公司的業務裏沒有owner的話,在運行時會出現一些其餘異常,涉及公司業務這裏就不展開了,咱們言歸正傳,爲毛我設置成feichaozhenshuai!就不行了,那我設置成肥朝大帥比電腦會不會爆炸啊???ide


常見的錯誤作法是,把這個問題截圖往羣裏一丟,問「大家有沒有遇到過dubbo裏面,owner設置不生效的問題?」


而關注了肥朝公衆號的【真愛粉絲】會這麼問,「dubbo裏面設置owner卻不生效,大家以爲我要從個角度排查問題?」。一看到這麼正確的提問方式,我以爲我不回覆你都很差意思。好了,回到主題,這個時候,沒有一點點錯誤日誌,可是卻設置不成功,咱們有哪些排查手段?

套路一

直接找set方法,看看是否是代碼作了判斷,防止在owner字段裏面set相似肥朝真帥這種詞語,避免把帥這件事走露風聲!。這麼一分析彷佛挺有道理對吧,那麼,如何快速找到這個set方法呢?如圖


public void setOwner(String owner) {
    checkMultiName("owner", owner);
    this.owner = owner;
}

咱們跟進checkMultiName代碼後發現

protected static void checkProperty(String property, String value, int maxlength, Pattern pattern) {
    if (StringUtils.isEmpty(value)) {
        return;
    }
    if (value.length() > maxlength) {
        throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" is longer than " + maxlength);
    }
    if (pattern != null) {
        Matcher matcher = pattern.matcher(value);
        if (!matcher.matches()) {
            throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" contains illegal " +
                    "character, only digit, letter, '-', '_' or '.' is legal.");
        }
    }
}

從異常描述就很明顯能夠看出,原來owner裏面是隻支持-_等這類特殊符號,!是不支持的,因此設置成不成功,和肥朝帥不帥是不要緊的,和後面的!是有關係的。擦,原來是肥朝想多了,給本身加戲了!!!

固然肥朝能夠告訴你,在後面的版本,修復了這個bug,日誌會看獲得異常了。這個時候你以爲問題就解決了?

我相信此時不少假粉就會關掉文章,或者說下次肥朝發了一些他們不喜歡看的文章(你懂的)後,他們就今後取關,可是肥朝想說,且慢動手!!!


你想嘛,萬一你之後又遇到相似的問題呢?並且源碼層次很深,就不是簡單的搜個set方法這麼簡單,此次給你搜到了set方法並解決問題,簡直是偶然成功。所以,我才屢次強調,要持續關注肥朝,掌握更多套路。這難道是想騙你關注?我這分明是愛你啊!

那麼,萬一之後遇到一些吞掉異常,亦或者某些緣由致使日誌沒打印,咱們到底如何排查?

套路二

咱們知道idea裏面有不少好用的功能,好比肥朝以前的【看源碼,我爲何推薦IDEA?】中就提到了條件斷點,除此以外,還有一個被你們低估的功能,叫作異常斷點


肥朝掃了一眼,裏面的單詞都是小學的英語單詞,所以怎麼使用就不作過多解釋。遇到這個問題時,咱們能夠這樣設置異常斷點。


運行起來以下:


這樣,運行起來的時候,就會迅速定位到異常位置。而後一頓分析,應該很容易找出問題。

是否是有點感受了?那咱們再來一個題型練習一下。

案例二

咱們先在看以前肥朝粉絲羣的提問



圖片


考慮到部分粉絲不在羣裏,我就簡單描述一下這個粉絲的問題,他代碼有個異常,而後catch打異常日誌,可是日誌卻沒輸出。

固然你仍是不理解也不要緊,我根據該粉絲的問題,給你搭建了一個最簡模型的demo,模型雖然簡單,可是問題是一樣的,原汁原味,熟悉的配方,熟悉的味道。git地址以下:【https://gitee.com/HelloToby/springboot-run-exception】咱們運行起來看一下

@Slf4j
public class HelloSpringApplicationRunListener implements SpringApplicationRunListener {

    public HelloSpringApplicationRunListener(SpringApplication application, String[] args) {
    }

    @Override
    public void starting() {

    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {

    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        throw new RuntimeException("歡迎關注微信公衆號【肥朝】");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {

    }

    @Override
    public void finished(ConfigurableApplicationContext context, Throwable exception) {
    }
}


你會發現,一運行起來進程就中止,一點日誌都沒。絕大部分假粉絲遇到這個狀況,都是菊花一緊,一點頭緒都沒,又去羣裏問」大家有沒有遇到過,Springboot一塊兒來進程就沒了,可是沒有日誌的問題?「。正確提問姿式肥朝已經強調過,這裏很少說。那麼咱們用前面學到的排查套路,再來走一波



咱們根據異常棧順藤摸瓜


咱們從代碼中看出兩個關鍵單詞【reportFailure】、【context.close()】,通過斷點咱們發現,確實是會先打印日誌,再關掉容器。可是爲啥日誌先執行,再關掉容器,日誌沒輸出,容器就關掉了呢?由於,這個demo中,日誌是全異步日誌,異步日誌還沒執行,容器就關了,致使了日誌沒有輸出。

該粉絲遇到的問題是相似的,他是單元測試中,代碼中的異步日誌還沒輸出,單元測試執行完進程就中止了。知道了原理解決起來也很簡單,好比最簡單的,跑單元測試的時候末尾先sleep一下等日誌輸出。

在使用Springboot中,其實常常會遇到這種,啓動期間出現異常,可是日誌是異步的,日誌還沒輸出就容器中止,致使沒有異常日誌。知道了原理以後,要完全解決這類問題,能夠增長一個SpringApplicationRunListener

/**
 * 負責應用啓動時的異常輸出
 */

@Slf4j
public class OutstandingExceptionReporter implements SpringApplicationRunListener {

    public OutstandingExceptionReporter(SpringApplication application, String[] args) {
    }

    @Override
    public void starting() {

    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {

    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {

    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {

    }

    @Override
    public void finished(ConfigurableApplicationContext context, Throwable exception) {
        if (exception != null) {
            log.error("application started failed",exception);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                log.error("application started failed", e);
            }
        }
    }
}

再囉嗦一句,其實日誌輸出不了,除了這個異步日誌的案例外,還有不少狀況的,好比日誌衝突之類的,排查套路還不少,所以,建議持續關注,每個套路,都想和你分享!

什麼是編程思想?

肥朝始終以爲,要想比別人更優秀,除了比別人更努力這個必要因素外,思惟方式,也是咱們必要關注的一個重點。好比在案例二中,不少同窗知道了bug以後,就認爲本身學到東西了,其實這個想法既正確,也不正確。

正確的地方在於,你知道了這個bug,後面遇到相同的問題,你會猜一下是否是一樣的緣由。

不正確的地方在於,你只知道了這個bug出現的某個場景,可是當咱們遇到這個問題,應對的排查套路有哪些你並不知道。也就是說,若是這個問題事後,你排查問題的套路並無增長,亦或者你沒有能從這個問題上,發散出本身的想法,繼續壓榨出更多的價值,本質上,你的編程能力,其實並無提高的。

然而,你一旦在公司時間長了,也就是咱們常說的老油條,對公司的某些坑熟悉,新人遇到問題時,就容易猜對多是某個坑。可是其實你的套路來來去去就那幾個,本質上你的編程能力並無提高,卻讓你產生了本身愈來愈牛逼,這下必需要加薪的錯覺。

一個公司老是有線上報障是有問題的,可是一直不出問題也有問題的。固然不少時候,排查的機會或許輪不到你。這個時候,就會有常見的幾種作法。

1.公司確實項目太簡單,基本沒有什麼拿得出手的bug,都是一些低級的漏掉配置的bug。

2.大佬們在排查,反正不是個人問題,那我就看羣吹吹水,下班美滋滋。

3.大佬們在排查,等他們有結論了,我就過去問一句是啥問題,而後暗自記下來,下次面試的時候就說是本身排查的,吹一波,美滋滋。

4.大佬們在排查,得知緣由後,深刻思考,大佬們爲啥會想到是這個緣由,他們是怎麼排查的?用了哪些排查工具?排查技巧?而後暗自總結一波,並把本身代入場景,腦補一下本身來排查問題,並把這個bug壓榨出更多價值!(怎麼壓榨出更多價值,能夠查看肥朝以前的源碼實戰文章,每一篇都有一個環節專門講拓展思考的)

你的思惟方式,你的行動,每每就決定你成爲何樣的人。肥朝也始終相信,時間在哪,行動在哪,成就就在哪。一塊兒共勉。



圖片

相關文章
相關標籤/搜索