实践之术
术是局部层面,它是实践经验,牵扯方方面面,难以尽数枚举 。
如果以文章写作类比软件开发,谋篇布局相当于设计层面,设计层面要致广远,遣词造句相当于实现层面,实现层面要尽精微 。
所谓千里之堤溃于蚁穴,防微杜渐尤其重要 。
1. 冗余设计
冗余设计指留出安全余量,冗余包括数据冗余、计算冗余、带宽冗余 。
数据冗余指一份数据多个副本,一主多备 。
计算冗余,比如服务实例的QPS极限是10K,但实际上我们会按5K跑,这样,即使出现流量超速增长,我们依然有反应时间 。
2. 快速恢复设计(无状态设计)
互联网服务很多都是无状态设计,服务实例只是逻辑的盒子,后面跟着分布式一致性数据库,这样能极大简化设计,即使实例挂了,客户可以很容易迁移到其他服务实例执行,而有状态设计则要复杂难搞得多 。
3. 容错、灾备
容错指我们的系统要有一定的错误容忍能力,这意味错误发生,我们要能查错、检错、避错、甚至改错,只要可能,我们就要吞咽错误 。
灾备这个大家耳熟能详,主从设计,异地备灾,目标都是为了应对各种极限情况 。
4. 熔断、隔离
熔断机制不止软件设计独有,股市也有,我甚至怀疑软件的熔断机制是从股市学来的 。
隔离本质上就是说如果故障发生了,如果故障发生,而又不能吞咽,那也应该隔离避免错误传播扩散,千方百计缩小影响范围,相当于感染新冠要被隔离起来 。容器化等技术为隔离提供良好能力支撑 。
5. 限流
系统设计要做好资源耗尽、资源不够用的情况,如果服务请求超过服务能力,那就应该限流,这应该作为一种配置,或者自动执行的策略 。
这个跟地铁限流差不多,处理不了,那就排队 。
6. 有损服务
有损服务我印象中最先是腾讯提出来的,指如果出现服务能力不够,不能为所有客户提供服务的异常情况,那系统应该确保已有客户的服务请求得到满足,而不能让新增客户拉已有客户一起死 。
有损的意义就是有损失,有损伤的意思,已有客户不受干扰,新增客户沦为代价,这不也是没办法的办法嘛 。
7. 错误重试策略,避免流量风暴
如果设计一个ToC服务,在客户大规模断连的情况下,客户会重连,重连失败再连,如果重连尝试的频率不控制好,正常客户端重连有可能演变成对服务器的大规模攻击,打爆一台服务器,又去灭另一台,这太吓人了 。
可以参考kernel TCP的重连策略,有最大尝试次数,而且重试间隔是逐渐拉大的 。
8. 去关键路径、去中心化、避免单点故障
企业不要关键先生,关键先生会成为瓶颈,软件也不能把宝压到一个地方,去中心化去集中式,没什么难理解的 。
9. 负载均衡
load balance其实就是分担压力,LB要避免倾斜,有多种LB算法,比如RR,比如一致性hash,各有利弊,有兴趣可以研究下 。
LB不仅限于服务,进程内的多线程可能也会需要考虑这个问题 。
10. 避免惊群效应
一只鸟被惊扰起飞,然后一群鸟全部受惊起飞,画面感是不是很强?有点破窗效应的味道,可以参考Nginx对惊群效应的处理策略 。
11. 看门狗和心跳机制
可以参考kernel的watch dog,其实就是看护机制,检测错误并努力掰过来 。
12. 安全编码
安全编码是一个职业程序员的基本要求,安全编码规则很多,很细节的一些规矩 。这个可能跟语言相关,如果是C++相关的可以参考:C++的门门道道
C相关的规则要少一些,我顺手列举一些 。
- 比如要注意初始化 。
- 比如全局变量不要有构造顺序的依赖 。
- 比如慎用强转,强转等于接管了编译帮你做的类型检查 。
- 比如理解线程安全函数,理解可重入的概念,理解信号机制 。
- 比如要避免死锁,理解ABBA锁理解自死锁 。
- 比如要谨防资源泄漏 。
- 比如处理好内存分配失败的情况,理解野/悬垂指针 。
- 比如要处理好边界,防止越界,溢出 。
- 比如内存拷贝要避免内存重叠,理解memmove的用途 。
- 比如理解递归的低效和栈的大小限制,避免爆栈 。
- 比如建议使用STD安全版本函数(_s+n)版本 。
- 比如了解unsigned < 0导致死循环的情况 。
- 比如了解浮点数跟0比较的问题 。
- 比如理解整型数据溢出和反转 。
- 比如不要返回临时变量的引用或者指针,理解栈帧动态伸缩的原理 。
推荐阅读
- 系统架构设计的原则
- 观光农业规划设计理念解析
- 网易云信流媒体服务端架构设计与实现
- 淘宝首页怎么设计 手机如何制作淘宝详情页
- 谈谈开发框架的稳定性
- 纯CSS 精美按钮UI设计、实现及实例
- 设计名片要注意哪些方面 如何设计淘宝店标
- 茶席设计五要素的介绍,旧物茶席中的古朴风景
- 茶包的实用美观设计,包装设计的要素和要求
- 茶叶包装的材料设计,祥源易武藏锋喜获第二届中国农产品包装设计大赛等,祥源易武