带团队后的日常思考(十四)

一、日常问题

1)页面卡死

QA 将一个页面放在客户端中访问,进行功能测试的时候,发现运行在 iOS 16.7 系统中时,网页会卡死。

将页面地址复制到 Safari 浏览器中,访问也会卡死。而据 QA 描述,测试环境没有问题,其他 iOS 版本的系统以及安卓手机也没有问题。

有问题的手机,其测试和线上的客户端版本都是相同的,初步断定和 iOS 系统有关。

摇上 iOS 的人,让他们帮忙调试,发现卡在接口通信,接口通信中的响应一直在 loading,没有显示。

让客户端排查,他们什么头绪也没有,说可能页面渲染被阻塞了。

将接口换个路径,响应内容相同,但依然会被卡死。以为是接口请求时机的问题,那就加个延迟,依然有问题。

将接口响应置空,这时,页面不会卡死,看来与响应内容有关。

接下来将响应内容中的数组只返回一个,页面仍然不会卡死,尝试二分查找的思路,再返回 10 个,依旧正常,返回 15 个,出现卡死。

那看来问题出在这 5 条记录中,一个一个排查,发现一个 emoji 的蘑菇表情会让页面异常,过滤后就正常了。

又去摇客户端的人,他们排查半天也没发现问题,因为不是所有的 emoji 表情都异常,目前就一个,也找不出规律。

此时,一名客户端的人说用相同系统的手机访问管理后台,可以正常显示这个表情,活动页面和后台的区别就是用了不同的框架。

前者是 React 后者是 Vue,既然如此,那就查一下这个表情在 Vue 中输出的写法。

使用的是模板语法,将其替换成 v-html 的写法后,一切恢复了正常,特地查了这个属性的原理。

它会将变量内容赋给元素的 innerHTML 属性,而模板语法会经过很多复杂步骤,可能是某一步操作发生了死循环导致了卡死。

遇到此类难以马上解决的问题,需要抽丝剥茧的分析自己获取到的线索,然后一步一步推导,最后得出结论,这有点像探案推理。

总结上述这套过程就是寻线索,找差异,缩范围,给结论,如此递归反复,直到解决问题为止。

2)协作问题

我们组的重点是活动和管理后台,版本涉及的都是比较边缘的需求,有时候都没有直接需求。

最近就遇到,QA 在测版本需求时,临时找我们修改 BUG,这让我们很被动,安排的计划也被打乱了。

剖析了下这个问题,发现来源于两个方面。第一是产品在设计文档时,缺失了我们要修改的那部分业务。

但是人总归有盲区,漏掉点需求很正常。第二是技术评审不够详细,现在的评审流于形式,其他组我也控制不了。

目前就是比较粗的过,然后经常在开发时,遇到问题再和产品测试等人讨论,这个流程目前破不了。

想来想去,想到了 QA,是他们告诉我们有 BUG,那只需要求他们在设计测试用例时,涉及到我们这块的,就提前通知。

即使在版本中,我们没有要修改的需求,也要同步给我们,这样就不至于在测试过程中那么被动,被赶着改 BUG。

最近在做一个 Electron 客户端的项目,也遇到了两个协作问题。第一个就是协作团队的文档缺失,让我们吃了不少苦头。

我们的任务是将客户端的一个功能,搬到 Electron 项目中,但是在开发过程中,没有技术文档,遇到问题只能口头讨论,很费时间。

第二个就是第三方服务文档缺失,虽然他们会提供示例,但是每次都要过一点时间才能给到,无法第一时间拿到。

这就会延缓我们的开发进度,很多时候只能干等。总结下来,就是不同团队的技术文档缺失影响了我们的开发。

这也提醒我们自己组,技术文档要补充完善,以免影响他人。

二、工作优化

1)缺失的性能测试

最近上了一个大活动,其中会调用服务端的一个内部接口,这个接口是这次活动新写的。

刚上线的时候,发现了少量的慢响应,当时并没在意。正好赶上双休日,这两天慢响应一下子就上升了。

周末在家排查,发现是服务端的那个新接口问题,但想到页面还能打开,只是响应慢点,也就没有组织人力去修复了。

毕竟周末时间找人也比较困难,就这么拖到周一,他埋了日志,周二才做了一版修复,上线。

结果周三零点,整个活动页面的接口都超时,被电话打醒,赶紧排查,马上摇人服务端。

他说有个服务一直在告警,那你们居然没点反应,我真是醉了,运维我也摇了,过了半小时才来。

他说那个服务的 CPU 一直居高不下,服务端也没找出问题,还是我点醒他重启下服务,才恢复,额。

这么一折腾,运营都要跳起来了,在群里狂抱怨,我也很无奈。

其实我这边的日志显示从周二的 21 点开始,慢响应持续上升,我也大意了。

改了接口居然没关注,以为一切顺利,其实不然,今晚的日志一定要仔细关注了。

服务器的配置也会让运维升级,其实这个接口也是让 QA 测试过的,并没有功能问题。

但是却存在严重的性能问题,QA 之前自己也说以后得增加这块,这次的问题是三方都有责任,既有客观也有主观原因。

公司在经历裁员之后,服务端有经验的员工都离职了,这个留下的小伙来了才 1 年,模块也刚接手,开发经验也缺乏。

以后得完善测试流程,以及自己要多留心眼,就好像常说的不要完全信任用户的输入,协作时也有这点意思。

2)OKR

公司要求我们每个双月要制订自己的 OKR,然后还要对齐上级的 OKR。

我对齐了上级的双月高等级业务需求,不过我总觉得这个并不算 OKR,因为这些都是我们本月排进日程的任务。

第二个 O 是质量相关,将线上因代码问题导致的高等级 BUG 或事故降低至 0,之前写的 KR 不够具体,无法明确 KR 与 O 之间的联系。

那么这次又修改了一下,分析以往发生重大线上事故的原因,发现很多时候是因为慢 SQL 和数据库表太大撑满了整个数据库的容量。

由此就马上将其作为一个 KR,组织排查与优化,保持数据库健康。还真找到不少潜在问题,例如已没有记录的一张表,还占用 29.12GB 容量,立刻释放掉。

然后通过下面的 SQL 语句找到排名靠前的数据库表,清理不再需要的数据库表。

复制代码
select
        table_schema as '数据库',
        table_name as '表名',
        table_rows as '记录数',
        truncate(data_length/1024/1024, 2) as '数据容量(MB)',
        truncate(index_length/1024/1024, 2) as '索引容量(MB)'
from information_schema.tables
where table_schema='backend'
order by data_length desc, index_length desc;

另一个在使用的数据库是 MongoDB,用代码列出容量占用比较高的集合,发现可以释放掉 100G,每个月能减少 50 元的费用。

第二个 KR 是定期 Code Review,包含细节、安全、边界等内容,保障代码健壮性。Code Review 在执行时,安全性往往会被忽略,仅仅是复查逻辑的合理性是不够的。

还有些细节也应该放上台面,隔壁组服务端前段时间出现了非常严重的线上紧急 BUG,发生在 2 月 29 日那天,他们有段计算年龄的代码。

会将当天推算到 18 年前的当天,但是 18 年前的 2 月没有 29 号,导致计算异常发生了 BUG。但其实算年龄,完全不必如此计算,若在 Code Review 中就将此问题抛出。

那么就不会发生此类线上问题,关键发生在凌晨,都很难及时修正。

对三个 KR 分析飞书告警,修复会对业务造成影响的潜在问题。我们会将线上的页面错误和接口错误实时通过飞书发出告警。

这些告警可能不是最为紧急严重的,可能就是偶尔发生的,但是将它们修复,有助于避免潜在的风险。