一、日常问题
1)遗留项目
经常在工作时被人小窗,这里的计算有问题,那里的表格没内容了等等,一开始肯定是懵逼状态,然后是根据症状一步步的摸索代码逻辑。
对于正在维护的项目,很容易定位问题,但对于那些已经无人维护的项目,定位起来就比较困难了。
必须先确定数据源来自哪个组,可能是服务端,也可能是大数据端,还可能是以前的 Node 端(公司之前的后端采用的是Node.js,后面在慢慢迁移成 Go 语言)。
然后根据数据库表在几个项目中搜索,没有的话再提给隔壁组,这样一来一回异常费时费力。
后面自己思考了一下,其实自己可以主动出击,既然都需要借助数据库来反推,那何不将自己组维护的表罗列出来,并且标注影响的业务。
让大数据组也配合罗列出他们在维护的表,这样就能很快的缩小范围,准确定位出由谁来修复该问题。
除了补充数据库表之外,还可以主动将那几个没人管的 Node 服务拉到本地,为了节约时间,可以只阅读那几个正在跑的定时任务。
只要知道了定时任务的功能,那么也可以快速定位问题源,只不过修改的话成本会比较高,一般都只是重启服务而已。
2)梳理痛点
此处的痛点是指业务部门的痛点,这些问题不解决很影响他们日常工作的用户体验。
与各个业务组的负责人一对一的当面谈,归纳出几个他们当前迫切想要改善的点。
交谈下来有些比较好改,花点时间就能修复。但有些就比较吃力,要改的代价会比较大。
首先是文档缺乏,当前的使用方式可能之前就是这么设计的,若要修改,就得补全相关文档,既能提升开发质量,也能让测试人员更有针对性地工作。
其次是这些功能的使用频率并不高,但要完善就得投入较多的人力资源,而当前的人力资源非常紧张。
后面认真思考下来,在理解了他们的核心诉求后,发现这类功能也并不一定要通过重构的方式来完善,其实开放个小按钮可能就能满足他们的要求。
例如有个活动模板功能的优化,运营人员希望他们能在增加或修改模块内容的时候就能实时看到页面效果,那加个预览按钮就能解决他们的诉求,也不必花大力气来完善文档。
3)定时任务的迁移
线上的定时任务还在原先的一台服务器上,而现在我们这边所有的服务都迁移到了阿里云的容器服务中。
在原先的服务器上无法通过 SVC 的方式调用内部接口,只能通过域名转发来调用,很不方便。并且发布系统也是单独的一套。
为了统一环境和发布系统,同时降低服务器成本,需要将定时任务迁移出来。
但是定时任务在运行时只能有一套在线上,所以要非常谨慎的迁移,尤其是一些重要的定时任务,保证不能出错。
第一步是罗列定时任务的功能和影响的缓存与数据库,以及触发的时间点,这些也是给测试参考的。
第二步是将废弃的定时任务单独标注,这些任务就可略过不必测试。
第三步是补全重要的定时任务的业务逻辑,以及数据库SQL查询语句,方便测试。
在做好这些准备后,就开始与测试人员对接,期间碰到最多的是缺乏数据的问题。
要么查到相关表,从线上数据库中拉取一些,或者按照对逻辑的理解自己构造,亦或者忽略一些不重要的定时任务直接放到线上观察结果。
4)密码定期更新
后台管理系统对密码做了80天有效期的设置,一周会有个一人因为没有更新密码而使得自己无法进入到后台,需要我们手动介入为其更新。
平时工作日还能及时响应,万一是休息日,那就要影响工作。
如果一次两次也就算了,经常性的话就得想个办法,让他们主动去更新。后面发现是提示不够醒目,而且提示会在几秒后自动消失。
为此,更新了后台逻辑,在密码失效还有5天的时候,开始弹警告,并且延迟 6 分钟后再消失,然后再自动出现修改密码的弹出。
5)争议区域
这边的前端和后端的界线比较模糊,因为前端也会通过 Node.js 来操作数据库和缓存,例如微信服务、管理后台的接口等都是前端自己完成的。
赋予前端这些权限有利也有弊,有利的地方就是更加自由,可以不依赖后端,要做什么自己动手,例如做些前端的基础支撑服务,可以有效避免沟通成本,自己设计自己编写,一条龙。
有弊的地方就是工作量上去了,并且和后端扯皮的频次也高了,因为大家都会站在各自的角度来维护各自的利益。
之前就有个需求,后端觉得我们直接调用他们的 redis 缓存自己计算就能得出结果,但我觉得我们这边不应该过多的介入他们的业务。
就这样争论不休,最后各自退一步,他们给到我们需要的数据状态,然后我们自己来计算。
为了避免这种不必要的争论,每次需求评审完后,就要与后端划分好各自负责的功能。
6)redis
在上线监控系统后,redis占的内存稳步飙升,使用 info 命令查看内存情况,发现 used_memory_human 已经达到了 20.65G,一个月内扩容了两次。
运维找到我,要我排查一下这个异常,于是我先在连接redis服务器中,带上 --bigkeys 参数。
redis-cli -h ***.rds.aliyuncs.com -p 6379 --bigkeys
在控制台会扫描出成员比较多和占内存比较大的 key,挑选了几个与监控系统的任务队列有关的 key,例如 q:jobs:failed 占了 450462588 字节,大约 430M。
memory usage q:jobs:failed
(integer) 450462588
主要是 q:job:* 中的任务信息比较占内存,其中有很多状态是 failed 和 complete 的任务,对于我来说这些已经不需要了,开始编写代码去除。
由于 q:job:* 大概有500多W个任务,所以不能直接用 keys 命令,得改成 scan 扫描,5000个一扫。
每次 scan 得到的返回值是个数组,数组的第一个值是下一个位置,当为字符串 0 时,说明扫描完成,第二个值是个由 key 组成的数组。例如:
[ "1732", [ "q:job:123", "q:job:876", "q:job:768:log", "q:job:34569", "q:job:23454" ] ]
在将这些数据删除后,一下子就瘦身了,减到了 3.95G,效果显著。但是 mem_fragmentation_ratio(内存碎片率)指标却达到了 4.25,大于 1.5 就属于不合理范畴了。
把 activedefrag 配置项设置为 yes(命令如下),redis 就会在最合适(例如CPU较为空闲时)的时间自动清理内存碎片。
config set activedefrag yes
7)一个坑
后台管理系统有一个推送公众号通知的功能,但是经常不稳定,后面做了次更新,并上传到线上,观察下来还是有问题。
并且在项目中还看不到设的日志,非常奇怪,请求好像凭空消失了。
后面经过排查发现是任务队列的问题,任务队列是在api项目中,而api项目又分离出了一个支付服务。
在支付服务中也包含任务队列的接收逻辑,当推送任务被支付服务接收后,由于代码还是老的,所以就会仍然运行错误逻辑。
这是一个非常老的服务,已经有几年没动过了,出现这个问题让人猝不及防。
二、工作优化
1)团队规范
在查看之前的代码时,有些命名很耐人询问,并且缺少注释,这就导致在定位问题时困难重重,前人给后人设置了重重阻碍。
像之前遇到个问题,就是数据库表中有个字段,它的值是1、2、3等数字,由于没有注释,根本无法知其含义。
于是反推代码,希望代码中有合适的注释,但很遗憾,也没有,询问服务端,得到的回答也很让人失望,他们也没有注释。
这样来来回回的查甚是繁琐,于是根据网上的资料,整理出了一套适合自己团队的《前端代码规范》。
着重规范了注释的书写(包括代码和数据库),以及命名的方式(包括 JavaScript 的变量和 CSS 的类),图像的尺寸等。
平时自己也会关注组员的效率问题,发现经常在与其他组协作时发生一些不必要的时间开销,降低了开发效率。
例如拿到的设计稿和产品的原型图有差异,组员在未经确认的情况下就直接开发,在给产品验收时就被退了回来,重新修改。
很多其实都是些小事情,只不过日积月累之后,消耗的时间是非常可观的。
为了避免这种场景的发生,编写了《团队协作流程规范》,规范了与设计、产品、测试、服务端等各个组的协作流程。
这些规范随着时间的推移会一直做更新,做到与时俱进。
2)时间预估
我们公司在预估时间方面还是比较充足的,不过有时候还是会出现误差的情况,这样就不得不加班来弥补了。
虽然这种情况并不是很多,但还是觉得可以优化一下预估时间的计算方式。
后面思考了一下,影响开发进度的因素,除了不断的加需求之外,就是救火时间。
所谓救火其实是指计划外的工作,也许是一个难缠的 BUG,也许是已上线项目的功能修改等等。
这些工作就像泥潭一样,有时候就会让自己深陷其中,不能自拔。
因此,在周会的时候,就要求组员统计一下每周的救火时长,以小时作单位。
统计几周后,计算平均值,以后估时间时可将该时间也加上,从而能更科学的为自己预估开发时间。
当然,能这么做的前提条件是项目工期并不紧,需求也并不是很急切的要上。
3)浏览日志
Node的项目都会将日志上传到阿里云上,妥善利用好日志功能,可以起到意想不到的作用。
例如之前公司小程序的运营说打开评论会莫名其妙的弹出一个错误提示,但是页面上面又没有发现任何异常,说是偶现的,丢给我们之后。
我们也没有立刻查找,而是先完成紧急的需求。接下来的一天在查看日志中记录的 500 的通信时,发现有个请求出现的频率特别多。
于是在项目中查找,没有发现这个接口的代码,反查调用该接口的项目,发现正是公司的小程序。
恍然大悟,原来报错是因为请求了这个不存在的接口导致的。所以的话,经常浏览后台日志,会有很多新发现。
之前还发现有个错误发生的频率特别多,一查原来是因为变量的值是 undefined,还用其调用某个方法导致的隐蔽的BUG,立刻将其修复,提升代码健壮性。
针对H5的监控系统也在后面陆续上线,对前端有了一个更加立体化的监控体系。
4)项目无死角
线上的页面出问题时,发现问题的人首先找的人都会是我,因为我是前端 leader,所以我需要对目前的所有项目都得有所了解。
在必要时,得自己动手修改代码,最小化公司的损失。
工作日白天一旦出现 BUG,找到相关开发人员,都能做到及时响应,但麻烦的就是下班后和周末。
大家都不能做到马上响应,当我看到后,我会想办法自己解决,不是很喜欢在休息时间麻烦自己的团队成员修改代码。
一是因为第一时间不一定能联系上,避免时间的浪费,二是因为在还没弄清楚问题缘由的时候就去打扰团队成员会有点让人摸不着头脑,更显得不够专业。
为了能做到第二点,那么对项目就得很熟悉,尽量做到无死角。
像前几天晚上 21 点,发现了一个在iOS上的比较严重的问题(安卓正常),我马上打开那个项目,查看了问题模块,并且定位到了错误位置,分析问题最后做了修复。
在发布代码时有些不明确的地方(以免代码发布发生新的问题),联系自己团队的成员,但没有快速响应。
好在平时积累的说明文档发挥了重要作用,说明文档中详细记载了发布的几个重要步骤。
有不明确的地方,就说明自己在项目中还有很明显的死角,那么接下来就得想方设法的避免,消灭所有的明显死角,当然,是无法避免所有的。
5)Node服务升级
一开始将Node服务直接升级到版本12,马上就报各种错误,容器也无法启动,后面根据错误去查找,有个黑人老伙说可以降级到10.14.2来避开这个错误。
于是马上降级到10.14.2,测试环境的代码发布成功,然后发布到预发环境,邀请业务人员也进来体验,观察使用情况。
当都稳定后,最后上正式环境完成升级。
虽然没有出现明显的报错和页面奔溃,但是却发生了隐蔽的错误,时区发生了问题,在使用 moment.js 库的时候有些操作会自动加 8 小时,而有些却会减 8 小时。
有点无厘头,由于公司的测试资源有限,没有做完整的回归测试(也很难做,几百个页面了),直接上线无疑会有巨大的风险,综合考虑后,暂时放弃升级,换一种方式做技术升级。
6)技术分享
为了提升团队技术氛围,在参考了网上的资料后,整理并制订了一套技术分享机制。(目前已进行了3期)
准则:所有的分享都有意义。
目的
- 提供一个团队内部沟通、交流、学习、分享的平台。
- 技术资料的沉淀,形成公司技术价值。
- 技术落地到实际项目中,让大家热爱技术,工作中充满主动。
形式:演讲和茶话会两种,可在会上准备零食、饮料、瓜子、水果。
时间:每次 40分钟-60分钟,两周一次,周三下午18:00-19:00时间段,一般周三比较空闲,参与度能更高点。
主题
- 新增一个话题圈,了解当前大家感兴趣的点,包含技术或非技术两种。
- 每季度做次规划,从团队管理、技术弱点、希望提高的方面、产品下一步的技术和框架等,从中选出素材。
讲师(分享人)
- 技术团队各组别轮流做分享。
- 每次分享会需决定下一个分享人。
- 讲师需要有一到两周的准备时间,提前预告,分享大纲或PPT内容,让听众有所准备。
- 在结尾可预留几分钟答疑时间(可有奖竞答),调动大家的积极性,让听众参与进来。
- 每位分享人可获得一份小礼物~
内容
建议不要分享XXX的安装、XXX入门实战等营养价值比较低的主题。分享可以由浅入深,分多期,但要保证全面和深入,能让大家真正得到提升。
要分享的内容最好从搜集的主题中选取,因为这些是大家比较感兴趣的,参与度会高点。包括但不局限于下面这些:
- 项目的技术产出、工作经验等总结,例如疑难杂症的调试、阅读笔记。
- 行业最新技术、流行框架 ,例如 Flutter。
- 跨团队交流,例如 QA 可分享一些测试方法、自动化自测框架等。
- 对某一个技术点的深入分析,能引入到实际项目中就最好了。
收尾
- 所有分享的资料都要在 WIKI 进行沉淀,保存位置:该页面下建立子页面。
- 每个季度让大家投票,评选出对自己最有价值的分享,评选出“初生星球季度技术部最佳讲师“,奖励200元天猫卡or京东卡一张。
误区:懂得不多或讲得不好,担心被人嘲讽。
- 如果别人不懂,但是感兴趣,那你的分享可以帮助他入门。
- 如果别人也懂,那你的分享可互相促进,共同进步。
- 如果别人的理解更加深刻,那你可借此机会好好讨教。