首页前端开发HTML一次比较耗时的线上问题排查(线上问题排查与解决)

一次比较耗时的线上问题排查(线上问题排查与解决)

时间2023-03-24 17:26:57发布访客分类HTML浏览865
导读:一次比较耗时的线上问题排查前言大家好,我是逐日,现在成都阳的人太多了,今天趁着还阴着(现在谁也不知道哪天就阳了),又出了太阳,出去骑了一段天府绿道,几乎没有人,和之前人山人海的场景比起来,还有点不习惯。下午回来后,写一下最近的一次排查问题记...

一次比较耗时的线上问题排查

前言

大家好,我是逐日,现在成都阳的人太多了,今天趁着还阴着(现在谁也不知道哪天就阳了),又出了太阳,出去骑了一段天府绿道,几乎没有人,和之前人山人海的场景比起来,还有点不习惯。下午回来后,写一下最近的一次排查问题记录吧。

入职新公司几个月了,目前一切都好,和之前n年的程序员生涯不同的是,现在不再是只管自己干好手头那点活的大头兵了,变成了一小块业务的研发负责人,下边有几个初中级程序员。有的人或许会觉得还不错,是个小小leader了,我想说说感受,负责人这几个字,意味着什么呢?意味着这块业务的任何问题的最后责任人都是你,事情很多,基本涵盖了需求、开发、测试、上线、线上维护的全流程,开发阶段各种很小的事,比如持续集成、git仓库、服务器申请、架构搭建,都是你负责;需求如果涉及其他团队,给对方提需求,协调时间,那也是要操心的;这些其实也正常,小公司的话,没那么多人力。总之,业务的研发负责人,基本就是各种角色集于一身,之前腾讯的时候,就有一种虚拟的组织形式,叫xx业务包产到户团队,该团队包含了该业务相关的产品、开发、测试、运维等各种指责的同事。

我感觉我现在就有点包产到户的意思了。

先不扯那么多了,上周四上午,我正在写代码,然后就有两个其他业务组的同事找过来,说他们有个需求,同事A(比我入职早,算中级程序员吧,领导把他分给我这块业务了)做的,现在上线了,app端访问报错,同事A表示

搞不定,所以就找到我了。

我对这个需求也完全不了解,入职后一直在负责另一个系统的开发工作,但是,手下哥们搞不定,那只能我上了。

第一天排查

排查问题,第一步,拉进微信群。进群后,看到了问题截图,大概就是,app上有个h5应用列表,列表在后台可以维护,app端动态获取列表并渲染。用户点击某个应用,就能拿到该应用对应的h5 url,并加载进入。进入后,h5也就是一些html + js,这时候就会去调用后端接口,开始业务逻辑了。

我们的问题是,应用入口已经有了,但是,一点进去,就报错:

其实吧,对于这种由后端来开始排查的模式,我是有些看法的。我看到这个界面,我也不知道怎么报这个错啊,这应该得h5前端同事先查才能知道这个错误提示是啥问题。至于为啥是我们这边来排查,我当时没想太多,因为问题总要解决,其实,我猜测是因为,之前他们已经查过一两天了,前端h5那边甩到了同事A这边,说这个提示是,后端接口报错导致的,估计还给出了一点证据。然后呢,同事A这边也没证据证明不是自己问题,所以排查责任就到了同事A,然后到了我这里。另外,因为部门拆分,前端同事已经不属于我们部门了,估计问题排查估计对于他来说,可能优先级也不高。

因为当时同事A有其他比较急的事情要忙,我想着还是不耽误他那边时间,也就没有找他仔细问之前的情况,就开始独立介入了。

进群后,先认了下人,然后就去找前端同事线下沟通,大概问清楚了一点事情:

h5 url是https://h5.test.com.cn/(已隐去真实地址),h5里面会请求我方接口:http://1.1.1.1:8017/servlet/json, 我方接口由于是很老的框架,接口url都是一样的,只是参数里会携带真实的接口地址,假设为功能A,那么我方接口可能就是这样:http://1.1.1.1:8017/servlet/json?funcNo=A。

现在回想起来,当时也忘记问他,为什么确定是后端问题了,拿到上述信息后,就先回来了,拉运维同事进群,问1.1.1.1:8017是个什么服务,运维同事说,是这个机器是其他部门负责的,我又去加其他部门的运维同事微信,刚没问几句,前端那哥们说,地址给错了,线上没调1.1.1.1,而是另一个域名: https://app.test.com/servlet/json?funcNo=A。

那,app.test.com域名,确实是我们这边维护的,这个域名的情况,我到现在也不清楚,当时只知道,请求进来,会进入某个接入层机器,该机器上部署了接入层服务,后来才知道,上面还有ng,ng会转发给当前机器上的接入层服务,再后面的流程如下。

这个架构图其实我感觉也不完整,但运维同事太忙,经常找不到人,暂时也没法验证了。

按我猜测,后端这个域名,应该是会负载到两台nginx的(不管是dns做的,还是ng前面还有一层f5啥的),每台ng都会转发给本机的接入层服务,为啥会这么估计,后面就知道了。

为啥接入层服务之后,都是私有协议呢,又带啥加密之类的,因为这不是自研的东西,是买的,买的东西,卖家肯定是严防死守了,只教你怎么用,不教你原理,这给我们排查问题带来很大难度。

了解了这些之后,当天就去找运维同事,表示要在接入层机器上抓包,然后我把tcpdump的rpm发给他,他开始安装,结果就报错了,这个tcpdump版本依赖的libpcap,和本机上已经存在的libpcap冲突了,安装失败,我他么也是第一次见那个错,暂时也不知道怎么才能解决这个冲突,没办法,抓包计划直接失败了。这个在我上一篇文章里讲了。

于是,只能想想别的办法,我们又去看了nginx的日志文件,发现啥都没有,好吧,access日志也没开,甚至于在配置文件里配都没配access日志,然后,我意思是h5是放在https://h5.test.com.cn/域名的,那h5请求我们揭开,那https://h5.test.com.cn/对应的机器,应该有和我们之间的网络连接吧,netstat看了下,并没有。其实,这个是我对h5这种不够了解,h5的域名并不重要,h5被加载到app后,再请求后端,此时就是互联网访问了,就是用户和我们后端之间直接通信。此时,有点没思路了。运维同事开始和群里前端打语音,了解细节。

我拿着电脑在旁边找了一个nginx的access日志配置,但是由于没有验证,我们也不敢直接改。

没办法,nginx这层不行了,nginx本机的accept service也没有记录任何日志,然后呢,微服务那里,也没日志,都有点懵了,请求到底发哪里去了。

后边说,不行就去网关那层看下吧,为啥没想着先去看网关呢?因为我只是为了大家理解,把这个东西叫网关,其实,内部是把这个东西叫消息转发,叫router,认为就是个简单的转发的服务,没啥好看的。

当时也没办法,就去上面看了下,日志grep了一下,发现还真有,而且清楚地写了,请求转发给了微服务A那台机器,但是,没有请求体,没有响应体。

所以,都开始还是怀疑微服务A有问题了,此时已经排查了快一小时,运维同事也很忙,就只能先拿了微服务A这里的两个东西,一个是微服务A和网关间的抓包(后面发现是二进制的,艹),另一个是最近上线的那个业务jar包(微服务A,其实就是相当于被一个类似tomcat这样的容器启动起来的,容器会把请求转给你的jar包处理,就像tomcat把请求转给war包一样,所以每次上线都是丢个jar包上去升级。这是十年前的一个容器,第三方公司卖过来的,不知道有人听过思迪没有,就说这么垃圾,比tomcat垃圾多了,tomcat的startup.sh只是个脚本,最终还是用java命令启动的,jstack、jmap、jstat都可以用,但是,这个容器不是的,为了防止客户破解,专门搞了个二进制程序来启动容器,所以不能用jstack、jmap等各类工具)

这一天的排查就算是结束了,基本没什么成果,结束的时候,就说,要不先在测试环境再多试试,看看能不能重现问题。

第二天排查

今天的排查呢,就是我的独角戏了,我找测试同事,想要下服务器ssh密码。结果同事表示,这个按规则,不能给,使用的话,只能在固定位置的一台测试pc上去操作。于是同事在那台测试pc上登录了shell,然后我在那里坐了查了快一天。

因为是怀疑微服务有问题,我就把本次升级的那个业务jar,丢到测试环境,发现没问题;然后微服务这里,有很多配置文件,我各种改各种改,都没有复现问题。

然后呢,我还一边改,一边在测试环境的接入层机器抓包,最后呢,折腾了到下午4点多,也没复现,只发现一些结论。

比如,如果接口逻辑如果出错,那么报错是这样的:

image-20221217192402746

如果把这个接口删了,报错是这样的:

如果把服务停了,那么网关会报错,报错是这样的:

我就发现,测试环境里,报错的时候,错误信息里,都有发生错误的那个服务的名字。而且,这里的错误提示,会原封不动地展示在app侧,

但是,线上那个错误,是没有展示报错的服务的名字的,此时,我陷入了怀疑,我怀疑请求到底是不是到了我们这边呢?之前网关的日志显示,请求确实是到了我们这边了,但是,万一,界面这个错误不是我们这边导致的呢?万一是请求了其他服务报的错呢?

所以,排查到这个时候,又走不下去了,当时因为还有别的会,就先停了;在那边开会的时候,和某个同事提起这个,同事帮忙联系了一个比较熟悉这一套东西的人(转去其他部门了),那个哥们就说,确定是微服务的问题,要不把线上整个容器的文件夹全拉下来。我本来也有这个想法,于是,我又去找了运维同事,把线上的这个容器的整个文件夹拖下来了。

当时拿到后,就开始检查线上的配置,发现某个配置文件里,有个地方需要配置接口,配了两次,重复了,然后,兴高采烈地以为就是这个问题,由于当时也是周五下班了,测试环境当时电脑巨卡,没法验证,就准备等到下周再一再验证。

次周-周一

周一一上班,其他我都暂时顾不上,先冲到测试机器那边,发现不卡了,正好。开始模拟重复配置的场景,结果发现,即使重复了,也没影响,功能正常。

然后抱着试一试的心态,去线上把重复配置改了。果然,还是报错。

周末的时候,在家研究了下,为啥之前在接入层机器上安装tcpdump的libpcap时会冲突,已经找到了解决的办法。于是周一的时候,给运维同事发了另一个版本的tcpdump,这次,顺利安装好了,等着去接入层机器再抓包看下。

周一下午3点多,运维同事才有时间。在接入层机器开了抓包后,抓nginx和接入层服务间的网络包;然后在手机app操作,复现下问题,抓包完成。

我开始对抓的包进行分析,由于不好区分哪个包是我们手机上发出去的,费了不少时间,根据我在测试环境抓包分析的情况,点击那个h5应用,肯定会调用埋点统计接口1、埋点统计接口2后,才会调用另一个业务接口。

我在抓包文件里,只找到了埋点统计接口1、埋点统计接口2的两个包,没发现有调用业务接口。但不确定,这两个包就是我们触发的。

后面经过userid比较,发现对不上,不是我们点的。这就奇怪了,怎么没抓到我们的包呢?

这也就是我怀疑,肯定是存在另一台nginx,我们当时的包,肯定走到另一台nginx去了。

我坐在座位上有点泄气,找了运维同事n次,同事又很忙,这下确实有点难搞的感觉。

我开始想,有没有其他什么办法?

想啊想,想到了另一个app端负责人,我就想,看看他们之前遇到这种问题都是怎么办的。我现在就是后端抓包,但有些问题,一是不知道包到底是不是按照我们预想的路径在走,如果是的话,怎么抓不到;二是,看看app端有没有什么日志啊,啥的。

就去app负责人那边请教,他给我指了一条路,说手机连接电脑的charles,电脑代理访问,就可以看到网络包了。于是在他那边,现场试了下,看到的请求包有:埋点统计接口1、埋点统计接口2,然后,就没再调用我们那个业务接口了。

这下,证据在手,我就开始在群里艾特前端了,说你们这个都没调用我们接口啊,麻烦你们先排查一下吧

image-20221217195812793

这时候,感觉问题已经不在我方了,心情好了不少。然后业务方同事也准备周二去找前端"麻烦"了。

还没到周二,晚上的时候,前端发了个请求日志那种,认为接口还是有问题。

看起来也有模有样的,这是马上又把问题丢回来了?那刚刚charles代理抓包怎么没抓到啊,奇怪?

不过我看了下charles的抓包,里面埋点的接口,会带h5应用的appId,我们查了下,这appid确实是我们那个h5.

然后我拿着这个id,去和运维同事帮忙在接入层机器抓包里的对比,发现对不上,也就证实了,接入层机器抓的包是有问题的,里面确实没有我们当时的操作,肯定是存在另一台nginx。

次周-周二

排查了好几天了,头绪不多,我也有点累了。请求估计还是到了微服务的(之前网关也显示转发给了微服务),而且,如果正常处理的话,日志里会打印请求体,既然没打印,估计确实是容器的框架层报错了。

这时候,我觉得可能要硬啃这个微服务的类似tomcat的那个黑盒了,我把这个黑盒的框架层lib的jar包,全部反编译成java,搜索“无法载入业务组件”,没找到;我又细致地翻看了好久,确实没找到这几个字。

下午的时候,我想着,既然线上的整个包都拉下来了,那就在开发环境启动起来,看看会不会复现吧(之前一直为啥没弄这个,因为我第一次接触这个东西,连怎么启动微服务都不知道;之前想的是,先看看到底是哪个地方有问题,所以是到处抓包)。线上那一堆配置,也没怎么改,改了些ip端口,以让其连接开发网关,竟然在本地启动起来了(这个容器是国内公司搞的,自然都是什么gbk编码,我的shell那是各种乱码,也不知道启动成功了没),虽然看着报错不少,乱码一堆,但看监听端口,确实启动起来了。

然后请求了一下业务接口,复现了!问题复现了!

此时,我大概知道了,容器本身有个日志文件,我去检查了下,发现如下字样:

类没找到?由于同事A这个代码里,确实用了jackson做json解析,所以,我感觉估计就是这个问题了。

线上为啥没有去看这个文件?我第一次知道这个容器,不知道有这个日志文件,同事A可能也不清楚吧,说白了,还是对这个容器太不了解了。

由于这个是内部类,估计是会第一时间去加载,发现没有,就

我看了下,容器的lib目录下,确实没有jackson的json相关jar包,也就是说,线上不存在这些jar包,但是,我们的业务代码又用到了,上线的时候,又只上线了业务jar包,那自然有问题。

我说实话 ,这样的上线模式,就是有问题的。由于部门拆分的关系,其他一些部门接手了一些系统的开发,但是运维在我们这边,所以,他们上线的时候就要来找我们部门,领导让我把关,之前我就看到,升级包里就是几个class文件,就要去上线的,一问原因,说线上和本地差异太大了,没人敢全量上线。

我也对比了我们本地,开发业务代码那个工程的pom依赖,和线上的差异他么也太大了吧,要是不注意的话,以后,这样的问题看来还少不了

解决办法

解决也很简单,线上没有jackson,那么我们传上去就行了;或者,改下代码,别用线上没有的,用线上有的啊,线上有fastjson,用它的TypeReference类吧,反正功能差不多。

容器代码研究

我不是在本地开发环境启动起来了嘛,我尝试着用阿里arthas连接了下,没曾想,连上了,简直可以说是,天大的喜讯。

我想起来,没有jmap、没有jstack,容器又是二进制的,找入口都很为难,然后我不是看到了这个报错嘛?

image-20221217203846368

这个Dispatcher.java,我怎么没看到过呢,在框架的jar包里,找来找去都没发现,没办法了,该不会是二进制程序里,动态生成的java类吧?我用arthas连上,找到了这个类,反编译了下这个类,发现了如下代码:

image-20221217204214124

这里就是根据classname去加载class,得到对应的实例,加载失败,就会抛错,返回-1011,这就和前端小伙说的那个报错对上了:

{
"error_no":"-1011","error_info":"无法载入业务组件"}
    

总结

有几个点,感觉想说下。

  • 排查问题,还是应该从前到后,这叫按图索骥,哪里报错找哪里嘛;要不你有完整监控也行啊,那倒是简单了
  • 没有监控的情况下,这个系统就这么运行了这么多年,这说明了较为传统的中小公司,还是业务为先,稳定为先,业务级别的监控这种东西,可能过于奢侈了;不过现在也慢慢在升级老架构了,监控这些,慢慢都会有的
  • app端请求出错,这块的监控没有的话,其实很被动,因为app在用户手里,日志也在人家手里;你要么就上报日志,要么接入层服务器,至少要把日志搞好,不然排查起来很费劲
  • 这次也温习了下技能吧,n年前,搞过app这种,那时候还是会在电脑端charles抓https包的;这么多年没搞这种(近几年都是web端,或者pc客户端那种),忘记了可以这么抓了,也挺好,排查手段又增加了
  • 还有些和人打交道相关的,前端说后端有问题,最好要有证据;我们排查的时候,也记得先看看这些证据,可以避免怀疑这里,怀疑那里,一些证据就可以排除掉一些可能,更能聚焦问题所在,直捣黄龙

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

html5运维微服务容器

若转载请注明出处: 一次比较耗时的线上问题排查(线上问题排查与解决)
本文地址: https://pptw.com/jishu/183.html
优秀设计师都在用的h5设计工具(优秀设计师都在用的h5设计工具有哪些) 元宇宙,离中小企业有多远?(元宇宙公司是什么公司)

游客 回复需填写必要信息