加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 移动互联 > 正文

我从高级软件工程师身上学到的那些经验与教训

发布时间:2019-10-08 23:32:14 所属栏目:移动互联 来源:核子可乐译
导读:一年之前,我开始在彭博担任全职工作。从那时起,我就在构思这篇文章。我想象自己能够在时机成熟时,把自己的想法都倾诉于纸端。但刚刚过去一个月,我就意识到这并非易事:随着工作的推进,我忘掉了很多自己刚刚学到的东西。这些东西快速内化,使我的大脑

那么,为什么把保密信息引入生产环境可能引发问题?

  1. 我们不能将其直接添加到代码当中,否则任何人都能够直接查看。
  2. 是否应该将其作为环境变量,如同 12 因素应用所要求的那样?这确实是个好办法,但我们该如何实现?(在每次机器启动时都访问生产设备以填充环境变量,绝对是个痛苦的过程。)
  3. 将其部署为保密文件?那么该文件来自哪里?又该如何填充?

最后,整个过程当然不可能手动实现。

总而言之,我们使用了具有角色访问控制机制的数据库(只有我们的机器以及我们自己能够与该数据库通信)。我们的代码会在启动时从该数据库处获取保密信息。这部分信息能够在开发、beta 测试以及生产环境之间顺畅复制,且各自保留在对应的数据库当中。

这里要再提一句,AWS 等各家云服务供应商提供的具体方案可能有所区别。大家不用为保密信息费多少心。获取角色账户、在 UI 当中输入保密信息,而后即可确保代码在需要时获取其内容。这些服务能够显著简化整个流程,但之前的探索也并没有白费——我很高兴自己能够真正理解并欣赏这种简洁的解决方案。

在设计当中考虑维护要求

设计系统令人兴奋,但维护呢?恐怕就没什么成就感可言了。

在维护系统的过程中,我想到了这样一个问题:我们为什么要进行系统降级,又该如何实现系统降级?

第一部分的答案是,因为总有人不爱丢弃陈旧的部分,而是添加新的部分。厚古而薄今,至少我自己就有这样的毛病。

至于第二部分,答案是我们在进行系统设计时提出的终极目标,后续可能不再适用。在系统的发展当中,其很可能会以与设计假设相冲突的方式进行使用,这意味着我们当初做出的一切预期需求都不再有效。这时候我们就需要后退一步,层层剥离那些不再适用的部分。

目前,我至少知道三种能够降低降级率的办法。

  1. 保证业务逻辑与基础设施彼此分离:一般来说,需要降级的往往基础设施部分——例如使用量增加、框架过时、出现零日漏洞等等。
  2. 围绕维护需求设计流程。对新代码与旧代码采用同样的更新手段,从而防止新旧之间出现差异,确保代码整体保持“现代”特性。
  3. 始终坚持去掉一切不需要的 / 陈旧的代码。
部   署

我更倾向于把功能捆绑在一起,还是逐一进行部署?

这要取决于现有流程,但如果答案是捆绑部署,那么很可能会引发后续问题。

这里我们需要回答的问题是,我们为什么要把功能捆绑起来加以部署?

  • 是因为部署需要耗费太多时间吗?
  • 是因为代码审查比较困难吗?

无论是因为什么原因,我们都需要解决瓶颈本身,而不是在部署方法上做出迁就。捆绑方式至少会带来以下两大弊端。

  1. 如果其中一项功能出了错误,就会阻止另一功能的执行。
  2. 这会提高风险水平,或者说导致发生问题的机率上升。

接下来,无论大家选择哪一种部署流程,各位肯定是希望自己的机器能像耕牛一样勤勤恳恳,而不是像宠物那样动不动耍脾气。机器必须吃苦耐劳,我们知道每台机器上运行的是什么,在宕机时又该如何恢复。一旦发生宕机,我们不会感到沮丧——启动一台新的就行。这些设备应该像放养的牛羊,而不是需要精心呵护的小猫小狗。

出现问题时

一旦出了问题——而且早晚肯定会出问题——我们的黄金法则就是尽可能降低对客户造成的影响。

在出现问题时,我的第一反应就是解决问题。但事实证明,这并不是最高效的应对思路。相反,即使只是小小的问题,最高效的办法其实是选择回滚。返回之前能够正常工作的状态,这样才能缩短客户无法正常使用服务的时间窗口。

也只有这样,我们才能安心查找错误并动手加以修复。

正如集群中的“故障”机器一样,在尝试判断机器出了什么问题之前,我们首先应该将其下线并标记为不可用。

我发现这确实是种反直觉的办法,而且我的本能总会把自己带离最佳解决途径。

我觉得正是这样的本能,逼迫我走上解决 bug 的漫长道路。有时候,引发问题的根源就是我编写的代码出了问题,而我会深入研究自己写下的第一行代码。这有点像深度优先搜索的过程。

如果最后证明是配置发生了变化,而我没能及时调整功能本身,我就会非常生气。因为这个错误太低级了,本不该发生。

从那时起,我的心得就是在深度优先搜索之前先来一轮广度优先搜索,暂时不触及顶级节点。我能利用自己手头的资源确认哪些问题?

  • 机器还在运行吗?
  • 安装的代码是否正确?
  • 配置是否到位?
  • 代码是否使用到特定配置,例如代码中的路由是否正确?
  • 架构版本是否正确?
  • 最后,再看代码内容。
  • 我们原本以为是 nginx 在机器上没有正确安装。但事实证明,只是配置文件被设置为 false。*

当然,大多数情况下并不需要这么麻烦。有时候,单靠错误消息就足以帮我快速找到存在问题的代码。

当我找不出问题时,我会尝试分步对代码进行变更以查找可能的根源。变更的数量越少,找到真正问题的速度就越快。总之,请尽可能让推理过程变得有迹可循,太过跳跃只会错失线索。我现在还记得自己曾花了一个多小时解决几个 bug:问题在哪?一般都是我忘了检查的一些低级问题,例如设置路由、确保架构版本与服务版本匹配等等。这只能说明我对自己使用的技术堆栈还不够熟悉,因此需要通过犯错误的方式积累经验。最终,我可以单靠直觉就判断出为什么代码没能正常运行。

战争故事

一边是调整参数与查看统计数据,另一边是修复底层问题根源。

如果没有战争故事(war story,指一段令人难忘的经历,往往涉及危险、困难或者冒险因素),这篇文章又怎么会完整?我很喜欢回顾这类经历,分享环节马上开始。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读