我从高级软件工程师身上学到的那些经验与教训
那么,为什么把保密信息引入生产环境可能引发问题?
最后,整个过程当然不可能手动实现。 总而言之,我们使用了具有角色访问控制机制的数据库(只有我们的机器以及我们自己能够与该数据库通信)。我们的代码会在启动时从该数据库处获取保密信息。这部分信息能够在开发、beta 测试以及生产环境之间顺畅复制,且各自保留在对应的数据库当中。 这里要再提一句,AWS 等各家云服务供应商提供的具体方案可能有所区别。大家不用为保密信息费多少心。获取角色账户、在 UI 当中输入保密信息,而后即可确保代码在需要时获取其内容。这些服务能够显著简化整个流程,但之前的探索也并没有白费——我很高兴自己能够真正理解并欣赏这种简洁的解决方案。 在设计当中考虑维护要求 设计系统令人兴奋,但维护呢?恐怕就没什么成就感可言了。 在维护系统的过程中,我想到了这样一个问题:我们为什么要进行系统降级,又该如何实现系统降级? 第一部分的答案是,因为总有人不爱丢弃陈旧的部分,而是添加新的部分。厚古而薄今,至少我自己就有这样的毛病。 至于第二部分,答案是我们在进行系统设计时提出的终极目标,后续可能不再适用。在系统的发展当中,其很可能会以与设计假设相冲突的方式进行使用,这意味着我们当初做出的一切预期需求都不再有效。这时候我们就需要后退一步,层层剥离那些不再适用的部分。 目前,我至少知道三种能够降低降级率的办法。
我更倾向于把功能捆绑在一起,还是逐一进行部署? 这要取决于现有流程,但如果答案是捆绑部署,那么很可能会引发后续问题。 这里我们需要回答的问题是,我们为什么要把功能捆绑起来加以部署?
无论是因为什么原因,我们都需要解决瓶颈本身,而不是在部署方法上做出迁就。捆绑方式至少会带来以下两大弊端。
接下来,无论大家选择哪一种部署流程,各位肯定是希望自己的机器能像耕牛一样勤勤恳恳,而不是像宠物那样动不动耍脾气。机器必须吃苦耐劳,我们知道每台机器上运行的是什么,在宕机时又该如何恢复。一旦发生宕机,我们不会感到沮丧——启动一台新的就行。这些设备应该像放养的牛羊,而不是需要精心呵护的小猫小狗。 出现问题时一旦出了问题——而且早晚肯定会出问题——我们的黄金法则就是尽可能降低对客户造成的影响。 在出现问题时,我的第一反应就是解决问题。但事实证明,这并不是最高效的应对思路。相反,即使只是小小的问题,最高效的办法其实是选择回滚。返回之前能够正常工作的状态,这样才能缩短客户无法正常使用服务的时间窗口。 也只有这样,我们才能安心查找错误并动手加以修复。 正如集群中的“故障”机器一样,在尝试判断机器出了什么问题之前,我们首先应该将其下线并标记为不可用。 我发现这确实是种反直觉的办法,而且我的本能总会把自己带离最佳解决途径。 我觉得正是这样的本能,逼迫我走上解决 bug 的漫长道路。有时候,引发问题的根源就是我编写的代码出了问题,而我会深入研究自己写下的第一行代码。这有点像深度优先搜索的过程。 如果最后证明是配置发生了变化,而我没能及时调整功能本身,我就会非常生气。因为这个错误太低级了,本不该发生。 从那时起,我的心得就是在深度优先搜索之前先来一轮广度优先搜索,暂时不触及顶级节点。我能利用自己手头的资源确认哪些问题?
当然,大多数情况下并不需要这么麻烦。有时候,单靠错误消息就足以帮我快速找到存在问题的代码。 当我找不出问题时,我会尝试分步对代码进行变更以查找可能的根源。变更的数量越少,找到真正问题的速度就越快。总之,请尽可能让推理过程变得有迹可循,太过跳跃只会错失线索。我现在还记得自己曾花了一个多小时解决几个 bug:问题在哪?一般都是我忘了检查的一些低级问题,例如设置路由、确保架构版本与服务版本匹配等等。这只能说明我对自己使用的技术堆栈还不够熟悉,因此需要通过犯错误的方式积累经验。最终,我可以单靠直觉就判断出为什么代码没能正常运行。 战争故事 一边是调整参数与查看统计数据,另一边是修复底层问题根源。 如果没有战争故事(war story,指一段令人难忘的经历,往往涉及危险、困难或者冒险因素),这篇文章又怎么会完整?我很喜欢回顾这类经历,分享环节马上开始。 (编辑:云计算网_泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |