研发员工指南-原则篇 研发人员工作职责
suiw9 2024-12-19 16:26 27 浏览 0 评论
这是一个新的产研团队、新研发员工加入我们的技术体系所应遵循的技术流程规范、工具、原则合集,也是我们花费了昂贵学费换来的……经验教训。
上一篇:研发员工指南-流程篇
5.原则篇
软件工程和IT技术领域里虽说法无定法,但也并非可以天马行空,否则稍不留意就可能墙倒屋塌,覆水难收。心中无原则,这样也行,那样也行,那就有一百万种死法。
You!Leaders!一定要通过层层嵌套的“Rules”建立起本能反应,一遇到类似的事情,应激般地就知道该怎么设计,怎么行动,怎么救火。而这些“Rules”一定是经历了血与火的洗礼铸造的,每一条都有来龙有去脉。
比如说,我们在2018年定义的DevOps新八荣八耻,每一条都是血肉长城:
1.以随时可扩容、可缩容、可重启、可切换机房流量为荣,以不能迁移为耻。
2.以可配置为荣,以硬编码为耻。
3.以系统互备为荣,以系统单点为耻。
4.以交付时有监控报警为荣,以交付裸奔系统为耻。
5.以无状态为荣,以有状态为耻。
6.以标准化为荣,以特殊化为耻。
7.以自动化工具为荣,以人肉操作为耻。
8.以无人值守为荣,以人工介入为耻。
法则从何而来?
瑞?达利欧曾经说过,每个人都会犯错,主要的区别在于,成功人士能从错误中吸取教训,而普通人不能。为了从自己和他人的错误中吸取教训,你必须坦诚、公开地承认错误,并努力避免再次犯错。在这个问题上,很多人会说:“不,谢谢,这不适合我,我宁愿不管这些事。”但这不符合公司和团队的最佳利益,并会阻碍我们达成目标。如果你回顾一年前的自己,而没有为自己所做的傻事感到震惊,就说明你还没有吸取足够多的教训。不要患得患失,要朝着目标努力前行。要自省自警,别人对你很到位的批评,是你能得到的最宝贵的建议。想想看,你的滑雪教练告诉你,你摔跟头是因为你滑行中的重心移动不对,此时你要是认为他在责骂你,那你是多么愚蠢和低效啊。
不要纠结于“埋怨”还是“赞美”,而要专注于“准确”还是“不准确”。在意他人的“埋怨”“赞美”或者“正面”“负面”评价,不利于你从反复的工作流程中学习。要记住,过去的事情就让它过去,除了作为未来的教训,不要再纠结。
记住:痛苦+反思=进步。
5.1运维原则
对我们这种量级的业务做保障,意味着高强度的神经紧绷,一出事儿就是大事儿,我们必须把下面的原则深深地烙印到脑海中。
5.1.1核心业务高级别故障处理口诀
口诀:遇事不乱,分头核查,群里同步,简单陈述,绝不恋战,恢复服务。
分头核查:质量控制部负责人要争取复现现象,确认问题是否存在;运维部负责人核查业务对应的机房、数据库、内外网流量、应用负载是否正常。
绝不恋战:如果迟迟定位不了问题(比如五分钟之内),就不可恋战,必须快速恢复业务,如利用异地双活系统切换流量。切记:第一,不要把生产环境当成测试环境,不要在线调试,第二,不要一直留着现场观察来观察去。
5.1.2严重BUG不过夜
严重BUG不过夜,这是我们的承诺。这时候,你不能说马上下班了,不能说明天再说吧,不能说已经半夜了。
实际例子:腾讯深夜改BUG
2013年3月24日晚上11点22分,陈皓想改QQ密码,不想触发了QQ安全中心的一个 BUG,如下图所示。
于是发微博吐槽。过了半个多小时,腾讯运营人员做了反馈:
又过了一个多小时,腾讯的人又来这条微博评论,说BUG已经改好了。
5.1.3永远的后备方案
我司的研发哲学里强调,所有技术方案都要有后备方案,不能做成一锤子买卖,行还是不行全靠运气。
如果必须上线成功,没有退路,那必死无疑。
如果只有一个机房,必死无疑。
如果只有一个支付通道,必死无疑。
如果只有一条线路,必死无疑。
……为什么这么说?
2017年1月,公有云 UCloud 公司正在开年会,结果在他们北京B可用区的数据中心外3公里处,架空光缆线杆因卡车撞倒导致光缆断裂,工程师们被迫在年会现场紧急处理。
2015年6月21日上午9点到10点之间,阿里云公告称由于运营商电力问题造成香港机房故障。因为供电系统故障导致数据中心大楼整体断电,并触发消防报警。根据当地的消防规定,必须彻底排查隐患并完全消除后,才能获准进场做电力抢修。直至当晚21点22分机房正式恢复稳定供电,阿里云立即执行既定预案逐项恢复服务,21点32分安全防护服务恢复正常,各项服务陆续恢复,截至23点39分全部服务恢复。
2015年9月1日,阿里云官方发布致歉公告,称“因云盾安骑士server组件的恶意文件查杀功能升级触发了bug,导致部分服务器的少量可执行文件被误隔离”,但造成的影响无法估量。
2018年6月27日,阿里云工程师团队在上线一个自动化运维新功能中,执行了一项变更验证操作。这一功能在测试环境验证中并未发生问题,上线到自动化运维系统后,触发了一个未知代码bug。错误代码禁用了部分内部IP,导致部分产品访问链路不通,进一步导致一些客户访问阿里云官网控制台和使用部分产品功能出现问题。
2019年3月3日,阿里云华北二机房停服三小时。
2019年3月23日,微信支付上海机房光缆被挖断。
2019年4月4日,114.114.114.114DNS服务全国停服。
2019年6月2日,亚马逊北京机房光缆被挖断,AWS云服务北京区服务中断。
2019年6月3日,谷歌云全球断线。
灾难,总是在你意料之外。所以,我们必须准备一个后备方案,比如在这些场景:
- 大版本上线和数据迁移
- 升级第三方服务
- 保护数据安全
(一)大版本上线和数据迁移
大版本上线,老系统向新系统迁移,肯定涉及到方方面面,甚至有可能是通宵上线,那么就需要提前制定回退方案,并且召集相关人等评估上线方案和回退方案。临时抱佛脚,必然出大事。
(二)升级第三方服务
升级开源系统,也会遇到不可预知事件,要想好退路。我在第二章讲过升级RabbitMQ集群失败的例子。敢于升级就是因为通过老集群后台的Exportdefinitions功能导出JSON数据,它包含了集群的关键信息(如各种配置、Topic和订阅关系),再通过新集群的Import definitions功能导入。新集群启用之后,老集群不要立即销毁,作为后备方案,遇到问题后还可以平滑回退。
(三)保护数据安全
但凡是物理介质,都可能会物理毁灭,数据和配置彻底遗失的后果想必没有人能承受得起。所以我们不仅仅要备份,还要异地备份,并且要检查备份的可恢复性。
哪些需要备份?不要只关注生产环境,线下环境也一样要重点关注:
- 代码仓库:三地备份
- CE:数据库两地备份
- Redmine和Mantis:数据库两地备份
- ……
一般说来,我们有这些后备措施:
- 代码和配置的灾难可恢复性:
- Docker镜像库:所有应用如果是基于Docker容器,那么它们的配置都在 Docker 容器镜像里,而镜像库线上线下都有;
- 我们有Harbor私有分布式镜像仓库,在混合云多机房各处都有自动同步的镜像库;
- 有异地双活,等于说异地备份了Nginx/Redis/ES/Consul/ZK等服务配置信息;
- 我们的CE里保存了各种工程的应用属性(也是配置信息),而CE的数据库是异地备份的;
- 数据的灾难可恢复性:
- 异地备份:我司的iDB能够做到数据库自动备份以及备份的可恢复性自动检查;备份文件会同步到云下的多个机房;
- 有异地双活,等于说异地实时同步了全量数据库,并且有活的应用随时在校验。
5.1.4竭尽可能消灭Exception和慢查
我们十年来一直奉行“Exception日清日结”原则。曾经线上日志里每天新增数万条异常,工程师们已经麻木不仁、视若无睹了。面对连续宕机,我终于再也忍不下去了,抽出两周时间,停工清Exception,并且引入ELK,在此基础上开发了每日异常分析汇总邮件。从那以后,每新增一种异常日志,我们就能立即发现,并在数分钟内决定要不要处理、归谁处理以及如何处理。
慢查也是同样道理。工程师们总喜欢说,稍等一下,等我把手头的活儿忙完,再改这个慢查。放纵慢查,就等于烧炭自杀,不用等“早晚”,“中午”你就会得到“回报”。
5.2设计原则
5.2.1设计原则先行
每一位设计师都需要知道这个常识:
当你开始构建或重构一个复杂系统的时候,请先把大的设计原则写下来,然后在这些设计原则的框架内做推演。
而不是这种常见的工作方式:
根据需求分析,天马行空,不设边界,想到哪儿是哪儿,自己做一番推演之后,自我感觉良好。
阿里巴巴资深技术专家毕玄这样总结自己的系统设计方法:回顾了自己做过的几个系统的设计,发现自己在做系统设计的时候确实是会按照一个套路去做,这个套路就是:
系统设计的目的->系统设计的目标->围绕目标的核心设计->围绕核心设计形成的设计原则->各子系统和模块的详细设计。
(一)系统设计的目的
指的是做这个系统设计的目的到底是什么。很多人在做系统设计时,搞不清为什么要做一个新系统的设计,或者为什么要做一个系统的重构/演进的设计。如果搞不清楚这个目的,后面的系统设计上很容易形成偏差,导致本来是为了解决一个问题,才去做的重构或升级,但最后完全脱离了初心。
另外,还有一点很重要,一个大架构师是需要给很多人讲解系统设计的,只有理解并讲清了系统设计的目的,团队才能更好地去实现。
(二)系统设计的目标
围绕上面的目的,能不能形成一些可衡量的目标,从而确保最终系统实现和最初的目的不要出现太大的偏差。相信很多人都经历过最终的系统实现和系统设计偏差极大的现象,主要的原因基本都是没有制定衡量系统设计的目标,并在系统设计上让系统能透出这些目标。
(三)围绕目标的核心设计
这一步最重要的就是通过设计如何去实现上面的目标。这个环节中技术的专业、视野、全面的考虑、权衡取舍的主观原则、解题的思路,是形成核心设计的关键。
在核心设计的这个阶段中,会产生一些新的目标,可以衡量设计的最后实现情况,这些也都要追加到系统设计中,确保最后的实现和设计的偏差度是可视的。
(四)围绕核心设计形成的设计原则
有了上面的核心设计后,可以真正地形成一些设计原则,确保后面的子系统和模块的详细设计中能够遵循,并在详细设计中体现出来,这样才能保证整个大的系统设计的一致性。
(五)各子系统和模块的详细设计
到了这个时候,难度不会太大,毕竟有了前面的铺垫,只是解好一个更小范围的题目而已,程序员群体在解题能力上通常是不错的。
5.2.2关键数据历史可追溯
历史不得直接篡改和历史可追溯是一对,一个问题的两面。
(一)历史不得直接篡改
互联网核心服务容易产生数据不一致,一旦出现数据不一致,一定要有旁证来修正。所以数据库中以下关键资源的记录,原则上不允许直接修改历史数据:
- 下单/支付
- 生码/验码/快递物流
- 退款/调换货
- 商户结算
- 用户注册和注销
这里的“直接修改”特指,没有把变更行为记录到日志表里,而是直接在原始记录上update甚至delete。这种“毁尸灭迹”是明文禁止的,即使留下了文件类型日志也是不允许的。我们应该这么做:
第一,要修改这些记录的关键字段时,必须在数据库相关日志表里保留变更日志,并记录操作人和发起人,一定要确保历史可回溯。
第二,严禁对核心关键记录做物理删除,只能是软删除。
(二)历史可追溯
系统对关键记录做了一系列修改,甚至有程序在某个时间段内误写引入了脏数据,我们必须能从各种操作日志表中随时倒推回历史某一个时刻的快照,一是确保随时能安全地把数据还原回去,二是管理平台可以清晰地展示出由谁引发、怎么变化的历史,三是便于排查问题。
比如,对于记录了订单信息的 order_info 表,会员如果点击使用账户余额支付了订单的应付金额,那么该订单操作日志表就会做如下记录,原订单记录的重要字段(what)由谁(who)因为什么(why)在什么时候(when)从什么变为了什么(how),都会详细记录。
5.2.3系统高可用原则
商业系统上线的时候,必须是监控告警配置到位,必须是高可用的,不允许引入单点风险。这是铁律,这是高压线,请不要挑战这个原则。
另外,核心业务要经常做设计评审和CodeReview。Leaders要多发起挑战,让大家一起来做脑筋体操,设计评审的目的是让大家一起来想想如果是我做这块工作,如何防并发、防重复提交、高可用、高性能、可伸缩,而不是闭门造车、测过就算。Web安全防范也要做在前面,不要等到用户财产受侵害才恍然大悟。我们组织设计评审时,提出的第一个问题是高可用性和可伸缩,第二个问题就是安全防范。
5.2.4不拿生产环境做试验
对于核心系统关键业务,第一不要盲目引入未经验证、尚不成熟的组件和服务,用时一时爽,出事火葬场;第二不要引入过多介质,增大维护难度和压力。
5.2.5数据补偿原则
我们能看到不管是哪一家的关键业务,都是围绕着一个核心系统,一层一层叠加各种自动化规则,叠加各种数据补偿定时任务,一层补丁摞一层补丁,以此确保服务的高可靠性。
举个例子,设计之初就要建立校验订单交易数据一致性的定时任务,比如以数据库操作日志为依据,挨个校验单个订单、交易流水的各项数据是否一致,如果发现不一致,第一要告警,第二尽量自动修复,比如说原路退返。这也是设计评审的一个重要考察环节。
5.2.6接入异地双活原则
凡是收银系统肯定是要接入我们的异地双活体系的,这是躲不过去的,别怕麻烦,因为单机房是不可靠的!
订单操作、资金账户划转、券操作等敏感业务的设计都需要提前考虑双活,免得回头还要推倒重做。
比如说订单号、券号、卡号等序列号的生成规则里,都应该有机房ID,能看出来这个订单是在哪一个机房生成的。
举例:我们的社餐团队利用TwitterSnowFlake算法生成如下规则的订单号:
25位 = 时间戳(13位)+机房ID(2位)+容器ID/IP(5位)+线程号(2位)+序列号(3位)
我们团餐团队的订单号规则为:
起始位固定2(1位)+日期(6位)+根据商户ID获取hashRoute(2位)+步长(7位)+机房ID(1位)
再比如说事先划定“多活表”(如订单表和退款表)、“非多活表”(如队列表)和全局表(如支付配置表)。
5.2.7谨慎使用updatetime作为更新依据
与钱、支付相关的重要配置的数据库设计,必须叫停以updatetime为更新判断依据的设计方式。
比如说,客户的支付配置、支付渠道、费率等重要信息是否有变更,不得以“设置了ON UPDATE CURRENT_TIMESTAMP 属性”的字段为准,如createtime,updatetime这种常见字段,否则非常容易在刷库时被自动更新,引发致命错误。
5.2.8数据库设计和变更提前与DBA沟通
工程师切勿自行其事。请提前与专业人士沟通。
举几个例子:
大表(如订单表)上需要预留足够多(如10个)扩展字段,后期复用时改字段名即可,不影响业务,无需停服。
大表真的被迫加字段的话,请提前一天加好,千万不要与上线动作绑在一起。大表加字段,请选择凌晨执行,因为以5G的数据量为例可能耗时10分钟左右,对业务有致命影响。
异地双活里,对于双活数据库而言,有主机房概念,如果先在主机房的双活数据库上做表结构变更,会导致otter同步中断,所以请先变更从机房的双活数据库的表结构,然后再变更主机房的。
5.2.9重构的两个“有利于”原则
如果你在繁忙的业务迭代中开始系统重构,恭喜你,说明你的业务已经完成了从0到1,正在从1走向10,或者从10走向60。至于重构后的技术栈是Spring MVC + Dubbo,还是Spring Boot + SpringCloud?是Vue + ElementUI,是React,还是Ant.design?是k8s,还是mesos+ marathon?是Thrift,还是Hessian,亦或 Protobuf?我并不在意。每个技术团队都可以有自己的技术选型思路。
我在意的是两个“是否有利于”:
一,是否有利于发布部署;
二,是否有利于排除故障(是否有利于快速定位线上问题和解决问题)。
随着业务规模越来越大,随着应用越来越多,随着容器化,随着前后端分离导致内部接口越来越多,随着 API 网关的引入,我们越来越难以在5分钟之内断定系统出了什么事儿。因此,我要求:
原则一:凡是中间件,不管是自主研发的,还是以开源软件为内核构建出来的,都必须自带监控报警,否则不允许上线。
原则二:本着 Don't make me think的哲学思路,所有对排除故障有帮助的信息,都必须一站式可视化展示。
举几个例子,定时任务管理与调度平台有运行情况展示,自带监控报警。
异步消息可靠推送系统有可视化的内部详情展示,自带监控报警。
分布式并行计算调度与管理平台一站式展示工作流下每一个任务在所有节点上的运行日志,并自带监控报警。
大数据协作平台魔盒上线伊始就自带监控报警。
我们甚至把所有 PC 客户端,所有智能设备都监管起来。
研发协作平台CE一站式展示应用部署的大事小情。
可以说我们打造的每一个系统都体现了这两个原则。
不需要东奔西走四处收集蛛丝马迹。
不需要一次性点开几百个指标页面,脑补推演。
不需要精通集群部署结构。
不需要熟知应用日志的路径。
一定要学会使用原则指导规则建立,用规则指导行事,形成团队肌肉记忆。遇到类似的事,大家的响应都应该如出一辙,而不是每个人各出怪招。
注:本文源自《CLOUDZ集团研发员工指南》,为禧云信息内部编著的技术交流资料。
相关推荐
- nginx的反向代理(Nginx的反向代理和负载均衡)
-
nginxProxy代理1、代理原理反向代理服务的实现:需要有一个负载均衡设备(即反向代理服务器)来分发用户请求,将用户请求分发到后端正真提供服务的服务器上。服务器返回自己的服务到负载均衡设备。负...
- Nginx UI: 更好用更现代化的Nginx 管理面板
-
各位铲屎官大家好,我是喵~...
- 性能测试之tomcat+nginx负载均衡(nginxtcp负载均衡)
-
nginxtomcat配置准备工作:两个tomcat执行命令cp-rapache-tomcat-8.5.56apache-tomcat-8.5.56_2修改被复制的tomcat2下con...
- nginx upstream节点健康检查(nginx tcp 健康检查)
-
1、前提条件编译nginx时增加nginx_upstream_check_module模板git地址:https://github.com/yaoweibin/nginx_upstream_check...
- Nginx 的高并发处理能力(nginx支持高并发原理)
-
为了实现Nginx的高并发处理能力,需要从**硬件资源**、**操作系统**、**Nginx配置**等多个方面进行优化。以下是详细的配置和示例:---...
- Nginx最全详解(万字图文总结)(nginxs)
-
大家好,我是mikechen。Nginx是非常重要的负载均衡中间件,被广泛应用于大型网站架构,下面我就全面来详解Nginx@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题...
- 如何用 Nginx 实现前端灰度发布(nginx 灰度测试规则)
-
前言在前端开发中,灰度发布是一种重要的策略,它允许我们在不影响所有用户的情况下,逐步推出新功能或更新。通过灰度发布,我们可以测试新版本的稳定性和性能,同时收集用户反馈。今天,我们将探讨如何使用Ngi...
- nginx配置优化场景-直接套用so happy!
-
前言(叠甲在先)Nginx是一款高性能的Web服务器,广泛应用于互联网领域。...
- Nginx配置前后端服务(nginx前后端分离部署)
-
nginx安装完成后,可以通过命令查看配置文件nginx-t配置文件nginx.conf,是总的配置,有的人会把配置全部配置到这个文件中,如果服务很多,这个文件变得非常庞大,我见过一个配置很大的,在...
- 使用Nginx配置TCP负载均衡(nginx如何配置负载均衡)
-
假设Kubernetes集群已经配置好,我们将基于CentOS为Nginx创建一个虚拟机。...
- Nginx服务器深度指南:安装、配置、优化指令超详解
-
在当今数字化时代,Web服务器是支撑互联网应用的关键基础设施。Nginx作为一款高性能的开源Web服务器,凭借卓越的性能、丰富的功能和出色的稳定性,在Web服务器领域占据了重要地位。无论是大型互联网公...
- Nginx的配置详解(附代码)(nginx基本配置)
-
本篇文章给大家带来的内容是关于Nginx的配置详解(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。常用配置项在工作中,我们与Nginx打交道更多的是通过其配置文件来进行。...
- Nginx配置文件详解(nginx配置文件详解带实例)
-
Nginx配置文件详解Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。...
- 从 0 到 1:构建高可用 Linux 负载均衡集群(基于 Nginx + Keepalived)
-
在高并发业务场景下,单台服务器往往无法支撑大量请求,因此需要使用**负载均衡(LoadBalancing)**技术来提升系统的稳定性和可用性。Nginx+Keepalived是常见的开源负载均...
- 配置Nginx TCP转发(nginx 接口转发)
-
Nginx一般用在HTTP的转发,TCP的转发大都会使用HAProxy。工作中遇到一个需求,用到了Nginx服务作为TCP转发。场景是这样,数据采集设备通过公网将数据推送到后端应用服务,服务部署在业主...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
tinymce 号称富文本编辑器世界第一,大家同意么?
-
- 最近发表
-
- nginx的反向代理(Nginx的反向代理和负载均衡)
- Nginx UI: 更好用更现代化的Nginx 管理面板
- 性能测试之tomcat+nginx负载均衡(nginxtcp负载均衡)
- nginx upstream节点健康检查(nginx tcp 健康检查)
- Nginx 的高并发处理能力(nginx支持高并发原理)
- Nginx最全详解(万字图文总结)(nginxs)
- 如何用 Nginx 实现前端灰度发布(nginx 灰度测试规则)
- nginx配置优化场景-直接套用so happy!
- Nginx配置前后端服务(nginx前后端分离部署)
- 使用Nginx配置TCP负载均衡(nginx如何配置负载均衡)
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)