步入2020年,正好是三十周岁。之前想的五年规划,成为一名架构师或技术专家,我看还是有一段路要走,有些不足的地方需要提升。虽然两年半前入职这边是资深后台开发工程师,希望能在成长的时候多成长些。
下半年参与新项目的机会不是很多,主要是老项目在运营,而其他几个版本的需求调整,以及线上的问题,各种偶现难查bug分析解决,都要跟进。老项目的一些活动需要进行跨服化,之前是只在本服进行,后面要改造一些代码,这样带来的工作量是多一些,这其中要考虑的较多,不可能为了加跨服功能而又要把原来已经测试过线上没问题的功能再测试一遍。以及一些适合本业务上的方案思考。新项目中写了个基础系统后来因需求调整被废弃了,这可能在游戏中经常这样;对一些移植老项目的代码进行了优化和重构,比如其中的定时器,整体性能提升15%~22%。
再说说自己的成长,相比去年,通过之前的博客记录,在非工作领域,通过开源,学到一些新的知识和更深入的思考。工作上,抛开业务部分,分析和解决问题的能力有一定的提升;框架设计会考虑更多;更有责任心,更想把一件事情或项目做好。
对于工作上,还是之前的话,通过一个完整的项目是成长很多,包括一些设计方案,复杂性和性能等权衡。因为业务逻辑不是很难,需求理解清楚,别总是出bug和不稳定,但是怎么选择合理的设计却是需要经验积攒。当项目越来越大,代码越来越多,怎么重构,耦合性等需要考虑到。另外,如果仅仅把自己局限于工作范围内,不去看下其他优秀的开源项目和设计方法,可能提升不那么大或者本来有不错的实现,自己搞一个很复杂且难维护的实现,虽然功能性上也满足需求,但是后面的性能和扩展性呢?线上出现的问题,不管是需求还是框架,怎么去定位和复现,然后修复和回归测试,带着问题再次review早期代码,这儿是否是合理设计,会不会出现什么问题等,而不是写完功能就好了,这样的成长其实也不多,换个人也可以写。
虽然多个版本的游戏已运营一年多,但还是有些基础功能设计不合理的,比如之前线上经常出bug的邮件系统,比如之前碰到过的有造成系统OOM挂掉;凌晨的时候大批玩家邮件领不了;只领取了一半奖励;有些超时的邮件本应该删除而却发给玩家,导致玩家删除不了等。后来再次review邮件系统的实现,比如根据邮件唯一id和角色id获取对应的某一个邮件,实现中是先从数据库中获取这个人的所有邮件,然后再返回对应id的邮件,这样会带来什么问题?一方面邮件功能并未作相关数据缓存,再者框架是协程,一个异步请求一个阻塞挂起,若一次性发十个这样的命令,那么所有请求都透传到数据库那边。一般个人邮件数量最大上限有几千,这样一次性从DB中获取非常多的数据,肯定是有问题的,之前因为OOM就是这样的情况。根据邮件id删除对应的邮件,也是使用对应的接口。所有跟邮件接口功能相关的,都是使用有问题的实现,都会造成问题。另外也包括在DB中的邮件内容,有些字节是不必要存的造成一定的冗余。
这仅是服务器这边的实现,有些好的设计,关于客户端与服务器之间的交互,如何减少流量及CPU等,都是需要考虑的。比如加上缓存,需要考虑缓存的失效时间,缓存与DB数据的一致性,缓存的容量,缓存中的数据同一时间大量失效造成的问题等。哪些邮件要存DB,哪些不存。如何防止重复领取一封邮件奖励等。一个小小的邮件系统,会包含很多的设计,实现一个无bug的稳定及可维护性的邮件系统不是那么简单的,需要踩坑,测试及线上验证。还有其他的基础系统,可能早期只是赶进度,只是实现需求即可,线上测试机会不多等因素,后期都可能为重构带来“机会”。
不过后面在新的项目中由其他同事重新写了邮件系统,不知道又出现哪些问题,大概看了下。虽然之前的邮件系统一堆已知问题,只要一个个修复并重新优化实现,也是都可以解决的,虽然目前的邮件系统已有bug也就三个四且都不复杂好修复。有些系统功能和代码为什么这么设计,总是出于当时一定的业务需求及考虑,且经过线上长时间的验证,而不是全盘否定,重新来再,自己写成怎么样又很难说,不停的测试再回归。那样可能后面再次踩各种各样的坑。或许根本问题并不在这些地方,但又不知道哪儿出问题,所以感觉这里复杂隐藏问题,先推倒这里,说不定是这么个情况。很多时候,解决问题,需要先确定哪儿有问题,抓住问题的本质,然后再做各方面的取舍和平衡。
最后想再说说项目管理这块。因为一个需求涉及到策划,客户端和服务端程序,以及测试四方面同学,如何准确理解需求是需要四方都合在一起开会讨论需求,哪些能实现,哪些不能实现,以及可能有的问题,短期目标是什么,考虑后续需求的调整还需要落实到文档可跟踪目标,不然工作交到其他同学手里,文档好久没更新也不知道什么样了后期随便提个新需求,可能改动就很大,怕只有先熟悉这块实现的才能作些改动和重复的测试多次。而且一个版本也还好,若同时有五六个版本,每个版本的有些地方需求不一样,而又只在同一份代码使用if/else写不同版本的功能,不知道是出于简单考虑或者管理方便还是其他情况。因为之前做了好多这方面的需求调整,虽然改动有时大有时小,但改了某个版本的代码处,又要担心是否会影响其他版本的,需要同时测试几个版本,虽然没出过事情。代码和配置分版本的好处是相互隔离不影响,改了这个版本的不影响其他版本,后期如果这份代码其他版本需要,同步下即可,现在的方式是比较尴尬,而且某个配置中某项被莫明其妙的删除,导致线上出问题再次热更,幸亏能热更但似乎更依赖于热更,而不是写更有健壮性的代码和少做的删除配置文件,有些存在即合理。
由之前博客记录的一些工作总结,抛开配置引起的问题,这一年大概发现和解决偶现bug问题30+个,大部分跟服务端的基础框架代码相关,并对存在的隐患调整相关的设计实现。通过这些分析思考问题,差不多再次把整个项目业务代码和基础代码翻一遍,上一次还是在2018年1月份,优化一大部分基础代码。自己把相关的工作负责好,也去看些其他的基础功能,虽然这些不是很难实现,可以学习下和发现潜在的问题。主要是想多成长些。
今年主要的事情是,分析brpc相关部分不错的设计源码及框架;再次阅读《深度探索C++对象模型》和《Effective C++》,以及《STL源码剖析》的前五章,csapp某些章节,这些主要是利用前三季度的早晨和晚上的两小时左右,冬季就很少早起看书~。dpdk相关的部分;游戏中的A星寻路以及视野相关的实现及优化;还有些C++11智能指针的源码相关;bfs相关的实现(后来没再分析),多线程相关的优化;和之前的libco和phxrpc,skynet相关源码细节再次翻阅了下...
回过头来,这些事情并不多,关键是没有集中的时间去做,可能周末断断续续的进行效果不是很好。平时工作也挺忙,九点下班到家十点,洗洗差不多十一点就可以睡觉了。关键还是长期的坚持下,早期可能很难,对有些复杂的开源项目很难把控,但是合理的分解,一个模块一个去攻克和调试,最后回过头来,发现在慢慢的收获和掌握。另外,对于开源的这些项目,并没有参与到实际业务中,可能并不能够深入层次领悟设计者为何这么设计,是否有其他方案来达到或比它更好?各方案间的权衡是如何考虑的等?比如同样的定时器实现,为何这种实现会在该业务需求背景下就有不错的性能?在分析的时候多思考些。有时在工作中,遇到相似的业务场景,可能会从之前学到过的设计思想,分析和评估下能否使用到当前项目中来。
今年暂定计划,在有空闲时间时,继续brpc剩余重要的模块,另外可能准备braft,虽然早些时候分析过raft的floyd实现,但后者实现是有些方面没有考虑到,可能并不适合于实际项目,前者有更多的可以学习下,需要深入源码以及设计思想。若有更多的精力,可能再回头关注下redis/jemalloc/leveldb。redis和leveldb在四五年前分析过一些实现后来因为工作太忙给中断掉,后来也偶尔看看并未作任何记录,希望以后保持下。感觉总体的计划不会太多,我认为不一定要给自己列很多,把这些都好好弄清和一些实现原理能理解下,对于工业级的代码,到时候在项目中能使用到类似的可以直接查看下,应该是可以的。
回顾这几年的工作经历,总结大概如下:从事游戏后台开发四年多,大半年抗DDoS防火墙开发,一年大数据开发,其中负责后台框架,性能优化,重构及业务需求的实现,线上问题的解决;平时使用到的语言是C/C++,lua,开发环境linux,扎实的计算机基础知识,对技术比较热爱;能独立负责一块业务,能站在产品或项目需求的角度去理解技术,良好的系统设计和代码质量,以及分析和解决问题的能力等。个人这块擅长的地方是性能优化,框架设计,解决一些技术难题等。不擅长的还是写ppt,讲ppt。
再说说自己的顾虑,因为这两年半多的时间工作中主要开发语言是lua,少量C/C++,那么带来的一个问题是,有些之前熟悉掌握的知识和工具可能会慢慢生疏。我明白,工作中需要什么去学,都说语言工具,对于工作多年的来说,关键在于学习能力和快速解决问题的能力,用的时候去查一下即可。只要基础不太差,愿意花时间和保持个较好的心态去接触不熟悉的一面也是有很大可能解决的。至于以后可能的换工作和面试什么的,技术是一方面,还有运气和缘分吧。毕竟面试充满不确定性,并不是所有问题都会,而且面试官和候选人对一个问题的理解层次也有不同,以及过往的经验积累和知识掌握程度。纠结谁对谁错已经没有意义。
若以后换工作,我希望的面试官,如果懂某一方面,可以一起聊聊,可以往深入提问,这样至少有些反馈我回答的理解的对不对?而不是你不懂,然后给我可能,好像,有点这样的不确定性,你至少要确保自己清楚这个方面,或者你听完不说话也行,可以查一下资料再判断是否正确和合理(如果愿意的话)。面试本来是相互的过程,是需要(可能)一起共事的,而不是随便面面,可能你会的我不会,也可能你会的或许理解的有点偏差。有些业务场景,目前的方案是合适的,有出于一些因素考虑,可能有更好的方案而需要经过leader评估和验证,而不是为什么不是B的情况?设计之初其他方案也考虑到但没有选择,这本是作为一个工程师该做的,站在全局,而不是按照个人意愿或者之前的技术经验来套用现在的项目。有的面试官根本不大会面试或者技术有待提高,可能是运气不大好,可能浪费彼此时间(尴尬)。
当然我是喜欢看到面试后的评价,这里并不是去判断面试过程是否有出入,因为能站在面试官角度去看候选人哪里不足。如果面试过程能有足够的相互交流是挺好的,不过貌似只遇到一问一答,问题接着问的那种情况,听不到面试官对这个问题的理解,有时候选人的回答跟面试官理解的不一样,并不是错的。比如面试官的知识可能停留在某个标准中,而新标准中已经可以这么实现。因为经历过的项目架构可能不适合别的项目,也没有机会考查下候选人如何应对一个未接触过的需求场景,和怎么选择出合理的方案,提出类似“如果让你来设计一个系统,会怎么做,需要考虑到哪些方面,是否存在可以优化的地方,以及稳定性,容灾单点等大的方面”,所以这个过程挺尴尬的。像阿里面试就会全方面的考查候选人,而不是仅仅因为他当前做了什么。面试本来是个不断匹配的过程,不光看候选人当前会的,还应该看潜力是否有能力解决问题和承担更大的责任。
这里摘一下知乎[如何进行一场高质量的游戏技术面试(原则篇)]中的一段比较赞同的话,当然这里不是仅指游戏行业:
“其次是要善于发现面试者的优点。技术是多维度的,在一方面有短板,可能在另一方面却是专家,需要综合评价。有的面试官不知从哪里来的优越感,一副居高临下的态度,以问倒对方为乐,这样是不可取的。正确的心态应该是两人合作探讨问题,就如同工作中的同事。如果面试者思考一个难题卡壳了,面试官应该给予提示,引导思路;反过来,面试者也可以顺着面试官的话题展开,主动展现自己的优点。在英文中interview不仅有面试的意思,也有面谈、采访之意,所以一个好的面试官要能让面试者打开话匣子,全面展现自己;面试者也不要唯唯诺诺,必要时刻也可以主动出击。”
要总结的大概如上,其实还有很多事想写,但有些事情大概是看破不说破的情况,尽最大能力和责任去把每一件事情好。还是这一句:做个靠谱的合作伙伴,凡事有交代,件件有着落,事事有回音。以后的路还很长,做个懂感恩的人。
希望2020~2022年能再提升一下,可能自己在这几年完成两件人生大事。另外,希望大家都健健康康的。