zoukankan      html  css  js  c++  java
  • 【疑难系列】 是程序卡住了还是怎么了?

    起因

    客户说:“今天的预报又没有发出去,帮忙看下怎么回事?”

    “...”

    经过

    登陆服务器,发现程序一直在打印

    running
    running
    running
    ...
    

    这是代码中写的

            public static void Main(string[] args)
            {
                Console.Title = string.Format("Grib2压码程序 请勿关闭");
                ActiveMq();
                while (hasMessage)
                {
                    Console.WriteLine("running");
                    Thread.Sleep(1000);
                }
            }
    

    程序通过启动ActiveMQ,然后判断是否仍有消息在处理,如果在处理就Sleep当前线程,等待处理完毕

    当接收到消息时的处理主逻辑:

    
            public static void OnMessage(IMessage message)
            {
                var msg = message as ITextMessage;
                if(msg != null)
                {
                   
                    hasMessage = true;
                    String date = msg.Text;
                    Compress(date);
                    mq.send(date);
                    hasMessage = false;
                }
            }
    

    那么问题应该是Compress或者 mq.send 一直在处理,卡住了??

    因为是.net程序,所以不能用jstack来分析线程了

    通过windows自带的任务管理器,把程序dump出来

    如何dump

    然后使用windbg分析一下线程,直接通过文件, "open dump file",打开导出的dmp文件。

    dump文件结果

    windbg第一次使用,不是很懂得使用,但是注意到右下角threads的线程信息,发现只有一个主线程在运行!!

    也就是说:我们的监听线程退出了!!!

    那么,什么情况下会退出呢?

    一般是线程运行过程中抛出异常没有处理

    检查源代码,发现程序没有对出现异常做任何处理

    所以,修改方案如下:

    		public static void OnMessage(IMessage message)
            {
                var msg = message as ITextMessage;
                if(msg != null)
                {
                   
                    hasMessage = true;
                    String date = msg.Text;
                    if(Compress(date, 3))
                    {
                        mq.send(date);
                    }
                    else
                    {
                        mq.fail(date);
                    }
                    hasMessage = false;
                }
            }
    
            public static bool Compress(string date, int retry)
            {
                if (retry == 0)
                {
                    return false;
                }
                try
                {
                    Compress(date);
                    return true;
                }
                catch (Exception ex)
                {
                    Log.writeException(ex);
                    return Compress(date, retry - 1);
                }
            }
    

    将监听消息部分的代码进行修改,增加重试,并进行try catch异常处理,出现异常时,在文件中记录日志

    当然mq.send 也有可能出现异常,将send方法也进行try catch异常处理

    替换程序,上线运行(这种问题看能否重现了,重现了就可以在error.log中找到了)

    总结分析

    windbg第一应用,表示很多信息都看不懂

    主线程中需要考虑子线程的异常,有些线程,你以为在运行,实际上它退出了

    其它

    面试的时候,面试官问我

    “你遇到过最难解决的问题,你是怎么解决的?”

    “我特么都是问题解决了就忘记了,所以没啥印象”

    不过,我是在心里说的

    所以,对于别人问我的问题,我决定记录下来,免得将来忘记了

  • 相关阅读:
    10 个深恶痛绝的 Java 异常。。
    为什么公司宁愿 25K 重新招人,也不给你加到 20K?原因太现实……
    推荐一款代码神器,代码量至少省一半!
    Spring Cloud Greenwich 正式发布,Hystrix 即将寿终正寝。。
    hdu 3853 LOOPS(概率 dp 期望)
    hdu 5245 Joyful(期望的计算,好题)
    hdu 4336 Card Collector(期望 dp 状态压缩)
    hdu 4405 Aeroplane chess(概率+dp)
    hdu 5036 Explosion(概率期望+bitset)
    hdu 5033 Building (单调栈 或 暴力枚举 )
  • 原文地址:https://www.cnblogs.com/binblog/p/11030812.html
Copyright © 2011-2022 走看看