1.需求分析
1.重视需求评审,多想、多问,做到:
a.研发完全理解产品意图,并在大脑中转化为系统原型,
b.针对各种边界条件、产品细节与产品进行反复沟通确认,直到研发脑海中有完整的系统设计路线,
c.务必在评审阶段消除研发和产品之间的二义性。
2.需求阶段评估好自身以及依赖组件需要支持的数据量,并发数,延迟以及访问量的指标。
3.明确好所有依赖,不确定的外部因数最高优先级去确定时间节点。
4.需要对接开发的接口,以文档形式明确接口字段类型,查询接口注意是否支持批量以及批量多少的问题。
5.需要同产品测沟通灾备方案。
2.设计阶段
业务系统设计原则:健壮性(柔性可用)、可扩展(去中心化)、轻量高效(解耦、低延迟)
一 . 设计方案
- 涉及接口的,需要给出接口设计文档
- 涉及数据库的,需要给出数据库设计文档,并明确字段以及字段大小。数据库的字段变更必须能做到向前兼容。
- 原则上需要按照模块图,交互流程图给出设计文档。
- 接口的更改必须能做到向前兼容,必须通知到对应调用方,并给出影响范围以及初步上线时间。
- 设计前要评估出系统的容量要求,根据容量需求,设计系统的数据模型、缓存模型、并发模型等,并对大流量场景正式运营前要进行容量要求压测。
- 设计期间,根据业务场景,考虑数据安全(鉴权、防刷)、业务容错、降级兜底、日志、监控和报警等设计。
- KISS原则(Keep it Simple and Stupid),追求简单,避免复杂。
二 . 设计方案review
- 所有大于1天工作量或者涉及对外接口数据新增或者内部框架的更改,原则上需要review设计。Review设计需要找到同级别或者更高级一级的工程师进行。采取轮动方式,不能每次都找同一人review。
- 所有大于1周工作量或者涉及接对外口数据格式更改或者整体框架的调整以及新的工程,原则上需要整个组集体review,时间紧急情况下,具体执行上可先由组长进行安排高级别的工程师进行一起review,然后再周会上进行全组告知。
三. 数据库设计
- 不同业务数据源做物理隔离。
- 尽量在设计初期考虑到分库分区的需求,设计table 时对大表进行拆分(建议临界值为1000万 超过千万 考虑分区分表),尽量使用分区不使用分表。数据库表设计都要经过开发以及运维的review。同时评估好数据规模。
- 禁止使用sql delete删除数据,一般使用delete字段表明数据已经被删除。(可以mysql用户权限级别进行限制,新业务可以考虑使用)
- 为了防止误操作,可开启sql_safe_updates。SQL_SAFE_UPDATES=1时,不带where和limit条件的update和delete操作语句无法执行,即使有where和limit条件但不带key column的update和delete也不能执行。同时可以通过添加limit,并判定操作返回的变更行数是否符合预期,不符合预期回滚来避免一次执行可能的误杀影响。
- 数据库表都需要2个时间字段,创建时间和修改时间。如果是关键数据表,需要记录具体操作流水表。
- 不推荐使用数据库unique限制来满足不同名的需求,后期有隐患。
- 数据库插入前,先检查大小,如果大于设计的表项,返回错误。
- 注意sql注入。
- 在数据库设计阶段,考虑好数据读写特点,添加索引。
- 所有cms系统,都需要记录详细操作日志。
- 主键建议使用int unsigned。
- 不建议针对过长字符串做索引,如果存在,建议使用前置索引。
- DDL 语句需和DBA 评估 影响范围,大表DDL 容易长时间锁表(DDL 建议使用合理算法,online,replace 等)
- 系统运行SQL 可自行 explain 下语句 看下执行计划,是否有索引等,确保sql效率。
- 对于频繁变更,操作等数据库表,建议合理使用事务。
- 一定要清楚数据库在 master-slave 模式下 采取的同步方式,并且 同步的报警机制(目前已知在半同步数据同步方式下 1MIN 后会有 同步异常报警)
- 建议使用mysql 时 找DBA 描述清楚应用场景 申请合理的数据库资源,链接方式 不建议使用IP 直连(域名链接,可以在几分钟内 完成数据库升级切换,不需要SOA发布重启)。
- 读写分离的情况下,如果出现写入数据后,然后另外模块读取的时候有可能失败。这种场景考虑参数传递时候数据完整携带。
- 注意随着部署规模增大带来的数据库连接数过多问题,可以采取通过数据层代理服务的方式来解决。
四. 接口设计
- 更改接口只能增加字段(json向前兼容),不能修改字段(随时可能引发客户端异常),如果功能有较大变动,建议另外新建一个接口提供数据。
- 列表以及返回大量数据组,提供分页支持。
- 应尽量避免实时读数据库的接口设计,可通过主动刷新数据到缓存解决一致性问题。
- 实时数据读取接口 考虑数据源隔离性,不应一个接口 影响到底层公用存储。
- 客户端接口下发格式有变更时做好版本控制。
- 主要入口页做好容错设计,包括异常时的自动兜底和人为介入下的降级。
- 对于不能降级的关键路径,通过多路存活机制确保更高的系统可用性。
3.开发阶段
- 开发IDE安装类似find bugs等检测插件,避免类似NPE等初级错误。
- 代码规范参考google java规范。https://jervyshi.gitbooks.io/google-java-styleguide-zh/content/
- 代码开发,按照先开发兜底代码,后逐步添加逻辑代码过程进行,兜底逻辑要足够强健确保可以无异常中断执行。
- 兜底代码要分3个层次,客户端兜底、服务端本地兜底、缓存兜底。降级优先级为缓存兜底>服务端本地兜底>客户端兜底。
- 所有需要访问外部资源的(包括外部存储,外部接口等),都需要做容错处理。并监控延时以及错误数统计。
- 大流量接口开发调用建议压缩流传输(HTTP:GZIP,JSF:自带的压缩算法)。
- 对于热资源做好隔离(包括线程池隔离,缓存隔离,数据库隔离等)。
- 参数最好支持配置化 或者使用配置中心,配置要具备实时升效能力。
- 对于数据库强依赖业务,如果不能使用其他中间件 如 jimdb,ES 等替代,开发阶段需考虑防刷、限流、熔断机制(有条件同时考虑点单和集群)。
- 记录日志,日志级别应能够在线切换
- 对于一些不常见且不好自动处理的极端异常场景,需做异常捕获同时及时通过消息告警到研发。
- 重要接口代码y以及复杂逻辑,或者大于50行的代码,原则上需要提供代码注释。
- git提交的commet,必须详细标注提交人,review人,提交所涉及的需求或者bug。
-
CMS的URL需要按照规范设计,方便做统一事务代理及权限配置
例如:
image.png
- 依赖的外部JSF jar 按需求放入 manager,和service层pom文件中,不允许放入父类的pom文件
- 增加maven依赖时,先搜索下是否为已有依赖,不要重复依赖
- 增加maven依赖时,检索下是否有传递依赖日志组件和项目本身组件冲突,冲突时exclusion掉冲突日志组件,避免日志打印异常
- 调用外部接口的时候,把接口文档地址写在相关注释里面,便于今后维护。
4.调试测试阶段
1.原则上开发应该对程序负责,开发完成后需要对接口需要进行完整的一轮测试。特别是各种边界情况,以及空值情况。
2.模拟自动容错、降级等各种异常场景的测试。
3.将重要功能测试逻辑积累到自动验证脚本,进行日常常备线上接口验证和上线前的基础功能点覆盖测试。
4.目前单元测试框架还未确定,待单元测试选定以后,如果没有特别的困难,开发需要对每个接口编写必要的单元测试代码。
5.上线阶段
原则:灰度!灰度!灰度!
一. 数据库变更上线
- 线上数据库更改字段,需要找DBA一起评估影响。读写频率较高的表,无法完成新加字段,考虑新加表,然后复制旧数据的模式
- 数据库线上变更务必制定可回滚流程
二. 代码上线
- 上线代码要经过功能测试通过。
- 上线代码要经过至少另外一名同事review通过,重点关注:
a. 异常处理(异常捕获、容错、降级)
b. 并发控制
c. 执行效率
d. 避免打印过多不必要日志上下文 - 全新逻辑代码进行压测验证,减少因为真实高流量带来的问题。
- 上线前做好关联团队周知
- 上线严格按照灰度流程执行
- 验证机灰度,验证本次改动接口逻辑,以及该业务所有核心接口是否正常
- 灰度1%机器,观察灰度机器接入上线流量之后日志是否正常
- 灰度10%机器,观察日志是否正常,观察本次修改设计到的接口,以及该业务所有核心接口监控知否正常(性能,可用率),并从业务前端体验业务是否正常
- 涉及db读写操作的发布,发布时候也看下db的qps和cpu负载,注意观察需要持续一段时间,重点观测指标是否持续上升。
- 发布前确认所有依赖上游、静态资源、数据库及表项已经发布。
- 发布过程中发现问题,第一时间做回滚操作,已发布的异常实例采取全量回滚的方式快速回滚
- 上线完成后,必须自己把基本功能都验证一遍,同时观测半小时以上接口的返回延时,机器运行指标,数据库负载以及报警情况,以及日志情况。涉及调用方,也需要观测调用房的数据情况。
6.运维流程
- 定期从运维方面获取慢查询日志,并由整个组一起分析原因,并优化逻辑或者索引
- 定期对整个接口的稳定性进行评估,并分析原因进行调整
- 每天花5分钟关注系统各项指标 (cpu ,调用量,存储等峰值操作数,是否出现大面积锁等)
- 定期关注线上实时日志,对异常日志需要追查到底,并做异常情况做修复和优化
- 每个业务小组做好轮流值班安排,确保任何时候有人可以随时支持线上问题。尤其关注上下班时间、节假日、吃饭等时间点的交叉互备。
- 业务小组安排周值班人员,重点关注值班群异常反馈,如和业务相关则及时跟进反馈。
7.监控报警
- 每个接口都需要记录接口调用频率,延迟,错误率。
- 关键外部调用以及数据库访问需要记录延迟,错误率。
- 对线上各种指标(调用量、性能、错误率)的异常波动需要做监控和短信报警。
- 对于一些需要研发第一时间关注的异常场景触发,需要在代码中直接植入实时异常短信报警。
- 如果有短时间的流量上升到达系统处理容量,对部分业务进行熔断处理。
8.异常响应
- 错误需要及时响应,每个小组按公休时间轮流分配第一负责人,第二负责人分配,负责人负责定时检查系统状况以及业务运行情况,出问题后联系相应人员进行响应。
- 可以建个 异常反馈群,新功能 上线 及时通知产品和业务检查现有功能是否OK。
- 所有人一旦发现异常,不管是否是自己负责的业务,都要第一时间反馈给该业务负责人。
- 各业务小组安排好在线值班,确保随时有人可以支持在线业务。
9.事后总结
- 事故发生以后,需要召开事故学习会议。分析具体事故原因以及改进意见。将容易出错的地方整理成文档,供后人借鉴。
10.大促备战
备战启动
流量预估
系统梳理(上下游依赖、数据库、缓存、降级策略、异常容错)
单机压测评估性能
扩容
全机房压测
故障应急演练
战备值班
网友评论