前言

时间的车轮一直向前不停,试图在时光洪流中碾碎一些久远的记忆。虽然记忆中的人离我越来越远,但是故事却越来越深刻。

当在博客园看到这次的正文题目是“最难忘的bug”,脑海里瞬间浮现起到2017年的11月8号那天。真的很快,已经过去四年了,这么多年,在Java开发、大数据开发中遇到过形形色色、自认为不可能发生的Bug,也曾伤过神、生过气,但最终只是成为了工作经验的给养。但惟有那次很小的一个bug,让我记忆犹新。

那次,改变了我对工作、责任的认知,让我有了团队归属感。那时候的我还是一个只会一点Java的实习生,现在已然成为三年经验的大数据从业者了。

问题

"测试","升级","割接"。2017年11月8日,这三个名词第一次出现在我的认知里,第一次实践在工作中。

从七月份进入公司实习以来,一直在整理各种文档,后来承担了大数据部分运维的工作。那时候的感觉就是,开发的理想真的离我越来越远。

升级目标

当时是做信令数据的接入,20多种信令,每种信令有50 ~ 100个字段。对端厂家根据规范将每个字段转换成二进制格式,例如unsigned int、int、double、byte、short各种数据类型。

这样的话,每种信令数据根据包含字段的数据类型,就可以计算出长度,然后放入byte[]或者byteBuffer中。例如byte类型就占1个字节,int类型占用4个字节。

根据定义的传输规范,我们将一个数据包分为包头和包体。根据包头可以区分出包体里面是响应数据还是应答数据,然后将包体内的二进制数据解析成对应类型明文即可。

此次升级除了字段个数增加,之前老版本中一个包体中只有一条数据,也修改成一个包体会有N条不同协议的数据。

问题

11月8日晚六点,组长对旁边的大佬说:“测试怎么样?"

大佬:“测试地没啥问题。”后来才知道和对端联调的时候没有测试充分。

那天的我本来是可以下班走的,然后我的第一任项目经理就叫住了我,让我积极参(chong)与(shu)一下。作为一个实习生,那时候正好在自学Java、大数据,加上也不敢拒绝,就留下陪他们加班。

然后晚上11点割接的时候,二进制数据解码后写入Kafka的数据先开始正常,接着就是齐刷刷的乱码,然后就大家就慌了,就开始找问题。

我们三个人都挤在一个工位上,大佬在中间找问题,我和组长就在一人一旁地看着。

乱码分析

那时候我连这个程序是干啥的都不知道,也准备躺平了。刚实习哪见过几千行的代码,就一愣一愣的看着他们在翻着程序。

凌晨五点的时候,我和组长就发现每个协议的解码方法中off变量都是作为形参进来的。

  1. 先解析包头内容,来确定包体中有多少条数据,这里对应的是totalContents

  2. 解析每条协议数据公共部分,一共占54个byte。

  3. 根据上面的lte_type来区分是哪个协议的数据,然后传入到对应的方法中对字段进行解码。下面是模拟之前老程序中一个协议数据的解析代码逻辑。

off变量的作用是记录每个字段在byte[]中的起始位置,这样才能正确的解析出每个字段。之前一个包体中只包含一条数据的时候,off传入到dataHander()后,将byte[]从off解析到数组尾部即完成了数据的解析,这时候的off是不要记录的。

但是当一个包体包含多条不同协议数据的时候,当第一条数据顺利解析完成后,因为传入解析方法的形参off虽然已经在方法内部进行了自增,但是未能作用于外部的实参off变量中,所以当解析第二条数据的时候off已经不再正确。

画个图加深理解:

在第三步传入协议方法的时候,虽然在方法内解析每个字段的时候off都自增了,但是却没有对外部的off进行修改,所以才会导致乱码。

为什么会乱码呢?

乱码说白了就是二进制无法转换成对应的字符。因为里面会有一些ascii码,而我们知道ascii是用一个byte表示,能够表示128(2的七次方)个字符,取值范围为0-127,即二进制范围为00000000 ~ 01111111,当off错位之后,这个byte表示的数字大于127的时候,就会因为找不到对应的字符,所以就会乱码。

结语

或许在很多人眼中,这就是个小错误。但对我来说,却是工作生涯的一个起点。经过这一次升级之后,后面也参与了这个程序的JVM调优、Kafka瓶颈测试的工作。对我后面的工作思维方式帮助了很多。

四年过去了,他们也在新的地方,成立了新的团队。而我,也慢慢成长为一名大数据工程师,也成为这个团队的负责人。或许有一天,我也会离开,或许会因为钱、或许会因为平台、亦或许会因为一个人。

这一次、很深刻,就像一份没带给你伤痛的感情一样。我也觉得初入社会,遇到这样的一群人、遇到这样的一件事很幸运。

最后,愿我们永远十八岁。

最难忘的一次bug:谢谢实习时候爱学习的自己的更多相关文章

  1. 【反思】一个价值两天的BUG,无论工作还是学习C语言的朋友都看看吧!

    博文原创,转载请联系博主! 使用C语言也有两个年头了,BUG写出来过不少,也改过不少BUG.但是偏偏就是有这么一个BUG让我手头的项目停工了两天,原因从百度找到谷歌,资料从MAN手册找到RFC也没有找 ...

  2. 开源敏捷测试管理& 开源BUG跟踪管理软件itest(爱测试) V3.3.0隆重发布

    v3.3.0 下载地址 :itest下载 码云源码地址 https://gitee.com/itestwork/itest 开源中国  itest项目地址   https://www.oschina. ...

  3. 开源敏捷测试管理& 开源BUG跟踪管理软件itest(爱测试) V3.3.1小改紧急发布及正实现功能预告

    v3.3.1 下载地址 :itest下载 码云源码地址 https://gitee.com/itestwork/itest 开源中国  itest项目地址   https://www.oschina. ...

  4. 二本非科班,秋招,实习,面试,offer之路

    不知不觉已经工作一年多的,我是2019年7月毕业的,但是如果算上实习就工作差不多两年了的吧. 最近不是刚刚过了圣诞节吗?然后又准备到元旦了,迎来2021年!在微信公众号上看到小部分公众号在总结2020 ...

  5. AI要被祭天了!删Bug,删着删着把全部代码都删了

    近日,美国版的“大众点评”,本想训练 AI 来消除 bug,结果它把所有内容删除了... Yelp 在其最新更新的 App 中写道: “我们为本周使用该app遇到问题的用户致歉.我们训练了一个神经网络 ...

  6. [中英对照]The Art Of Reporting Bugs | 报bug的艺术

    前言:因为最近要给兄弟Team分享一下如何有效地报告bug, 故多做一做功课.下面给出一篇博客的中英文对照翻译. The Art Of Reporting Bugs | 报bug的艺术 My init ...

  7. 数学口袋精灵感受与BUG

    232朱杰 http://www.cnblogs.com/alfredzhu https://github.com/alfredzhu/ 组长,团队 230蔡京航 http://www.cnblogs ...

  8. [Mac A]为什么国外程序员爱用 Mac?

    from http://www.vpsee.com/2009/06/why-programmers-love-mac/ Mac 在国外很受欢迎,尤其是在 设计/web开发/IT 人员圈子里.普通用户喜 ...

  9. CSS3学习总结

    (写在前边~)过了这么长时间,才写博客,最近实在是太忙了,做了两个项目,一个项目用于练手,自我感觉做的很漂亮,一个项目是一套完整的页面体系,答辩时候老师给了100分和99分,并让我打包上传,我很是感动 ...

随机推荐

  1. Golang通脉之方法

    方法和接收者 Go语言中的方法(Method)是一种作用于特定类型变量的函数.这种特定类型变量叫做接收者(Receiver).接收者的概念就类似于其他语言中的this或者 self. Go 语言中同时 ...

  2. 编程题:X星人的金币

    X星人的金币 时问限制:3000MS 内存限制:589824KB 题目描述: X是人在一艘海底沉船上发现了很多很多很多金币.可爱的X星人决定用这些金币来玩一个填格子的游戏.其规则如下:第1个格子放2枚 ...

  3. 【UE4 C++ 基础知识】<8> Delegate 委托

    概念 定义 UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系. 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到 ...

  4. Windows10使用技巧

    Windows10配置技巧 新机配置 "我的电脑"图标设置 在桌面右击鼠标=>个性化=>点击左侧"主题"=>点击相关的设置中的"桌面 ...

  5. airtest常用指令

    airtest 操作adb命令   常用adb 1)对特定设备执行adb指令 dev = connect_device("Android:///device1") dev.shel ...

  6. [no_code][Alpha]发布声明报告

    项目 内容 2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 发布声明 我们在这个课程的目标是 设计出一个OCR表单处理软件 这个作业在哪个具体方面 ...

  7. 使用Mybatis的TypeHandler加解密数据

    使用Mybatis的TypeHandler加解密数据 一.背景 二.解决方案 三.需求 四.实现思路 1.编写一个实体类,凡是此实体类的数据都表示需要加解密的 2.编写一个加解密的`TypeHandl ...

  8. redis5集群搭建步骤

    通常情况下为了redis的高可用,我们一般不会使用redis的单实例去运行,一般都会搭建一个 redis 的集群去运行.此处记录一下 redis5 以后 cluster 集群的搭建. 一.需求 red ...

  9. SpringCloud+RocketMQ实现分布式事务

    随着互联网公司的微服务越来越多,分布式事务已经成为了我们的经常使用的.所以我们来一步一步的实现基于RocketMQ的分布式事务.接下来,我们将要做的主题写出来. RocketMQ的分布式事务结构和说明 ...

  10. numpy.zeros()的作用和实操

    numpy.zeros()的作用: 通常是把数组转换成想要的矩阵 numpy.zeros()的使用方法: zeros(shape, dtype=float, order='C') shape:数据尺寸 ...