无异常日志,就不能排查问题了???
小声逼逼
众所周知,日志是排查问题的重要手段。关于日志设计,以及怎么根据从【用户报障】环节开始到秒级定位问题这个我们下一期说(绝非套路),这一期,主要讲一下,在没有异常日志的情况下
,如何定位问题。没有日志当真能排查问题,不会是标题党吧!
案例一
从最大的同性交友网站中拉取【dubbo-spring-boot-project】的代码。
然后把demo跑起来。
本场景是由真实案例改编,因为公司代码比较复杂也不方便透露,而这个demo在github上大家都能找到,既保证了原汁原味,又能让大家方便自己体验排查过程。
好了,我们先设置owner = "feichao"
,然后看一下控制台
一切正常
那么,当我设置成owner = "feichaozhenshuai!"
,再启动
看似一切都正常,那么,我们到控制台一看。
什么情况,怎么就没owner
了?
这是在哪个环节出问题了?其实肥朝当初在公司遇到这个问题的时候,场景比这个复杂得多。因为公司的业务里没有owner的话,在运行时会出现一些其他异常,涉及公司业务这里就不展开了,我们言归正传,为毛我设置成feichaozhenshuai!
就不行了,那我设置成肥朝大帅比
电脑会不会爆炸啊???
常见的错误做法
是,把这个问题截图往群里一丢,问“你们有没有遇到过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); } } } }
再啰嗦一句,其实日志输出不了,除了这个异步日志的案例外,还有很多情况的,比如日志冲突之类的,排查套路还很多,因此,建议持续关注,每一个套路,都想和你分享!
另外准备了一份资料,链接: https://pan.baidu.com/s/1M5-1RDL5FgVtC3fOHGhuBg 提取码: wcdq
内含RocketMQ4.x文档(市面上找到的多为过时的3.x版本)

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
从零做网站开发:基于Flask和JQuery,实现表格管理平台
摘要:本文将为大家带来基于Flask框架和JQuery实现管理平台网站的开发功能。 【写在前面】 你要开发网站? 嗯。。 会Flask吗? 什么东西,没听过。。。 会JQuery吗? 是python的库吗 ? 那你会什么? 我会F12打开网站 好吧,那我们来写个简单的表格管理平台。 基于Flask框架和JQuery实现管理平台网站的开发功能,我代码编写用了2天的时间 ,从零开始写;又对具体实现流程,自己断断续续地整理总结了近半个月。从自我感觉来说,整个过程和结果的实现都让我很满意。 【效果如下】 【第一步】了解Flask框架 1、了解python 主流的web框架 (1)Django:简单来说就是重武器,是最全能的开发框架,你想要的功能它都有;但是比较繁重,适合企业级的web开发; (2)Flask:属于web开发微框架,小巧灵活,相关的第三方库丰富,适合开发小型web; (3)Tornado:天生异步,性能强悍,但是框架提供的功能少,需要开发者自己实现; 因此,本文代码实现主要是基于Flask实现的。 2、了解Flask框架 (1)HelloWorld实现: 几乎所有的编程都是基于“...
- 下一篇
网骗欺诈?网络裸奔?都是因为 HTTP?
先跟大家讲个故事,我初恋是在初中时谈的,我的后桌的后桌。那个时候没有手机这类的沟通工具,上课交流有三宝,脚踢屁股、笔戳后背以及传纸条,当然我只能是那个屁股和后背,还不是能让初恋踢到的后背。 但是说实话传纸条真的很危险,尤其是这种早恋的纸条,被抓到就是一首《凉凉》。 特别我和初恋中间还隔着一个搞事的狗蛋,常年使用神乎其技的笔迹模仿技术篡改小纸条的内容,往往我写的是“放学一起去逛逛吧”,到了我初恋手里就变成了“放学一起写作业吧”。以至于我常年满怀期待的放学,然后痛苦的畅游作业的海洋。 不过好汉不提当年,我现在已经是一名出色的互联网人了,再也不用传纸条了,也不用再接受狗蛋的支配了。 这样想的我,猝不及防的就发现自己拍摄的美女图片,居然全部变成了如花!这到底是怎么回事? 美女变如花,数据在裸奔!聊聊什么是网络劫持。 在浏览器中输入相同的 URL,有的时候并不会出现同样的内容,比如想我今天遇到的美女变如花一样。 左边是正确响应会出现的图片,而右边则是莫名其妙出现的如花。这是因为 HTTP 被劫持了。 当 HTTP 被劫持时,虽然DNS 解析域名 IP 地址不变,但是在和网站交互过程中劫持了用户的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7设置SWAP分区,小内存服务器的救世主
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS关闭SELinux安全模块