在设计高可用的互联网架构要注意什么?

本文最后更新于2018年9月15日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢!

=Start=

缘由:

在答辩的时候被问到的一个问题,当时想的太少,回答的比较磕绊,虽然重点好像都有提到,但是感觉不够系统,觉得可以简单整理一下,常读常新,也方便之后添加更多的内容。

正文:

参考解答:
1、设计层面
如果可能的话,在最初设计层面就应该根据实际并发/响应时间要求来考虑,即便初始的流量比较小(避免后期切换/重做成本高,但是也要考虑前期快速上线的需求)。
# 处理流程设计
简单可依赖
# 底层框架使用(也需要考虑团队的熟悉程度、学习成本)
Redis/Tair
MQ
Thrift/RPC/…
SpringBoot/Netty/…
2、实现层面
重点代码交叉review
上线前性能测试
3、部署层面
异地、多机房、分布式部署
最好能有一键流量切换功能
4、监控层面
日志打点要满足需求(异步&不落盘)
相关监控要到位(请求量、服务器监控、存储监控、业务健康性监控)
5、操作层面
常规操作SOP
异常处理SOP(扩容、降级、回滚)
参考链接:

=END=

声明: 除非注明,ixyzero.com文章均为原创,转载请以链接形式标明本文地址,谢谢!
https://ixyzero.com/blog/archives/4082.html

《在设计高可用的互联网架构要注意什么?》上有31条评论

  1. 小团队互联网项目开发之备忘
    https://blog.devopszen.com/development_notes

    近期Web项目的开发和运营的经验,以下几条适合小型团队在资源和时间都有限的情况下做高效开发:

    1. 快速开发和迭代
    应该在最短时间内验证一个feature或者一个想法行得通还是不容易实现。这样还有时间进行系统的重新设计。最先验证feature中的关键点是否可行,再将所有关键点进行串联,和系统整合。

    2. 提早进入运营和市场
    我们都工作在互联网时间,每天互联网都在发生翻天覆地的变化,不进则退。同样的创意,世界上有很多团队在把它变成产品。

    3. 高效运行
    将现有系统尽可能的做得快速运行,减少数据冗余。以备以后需求增长中执行速度变慢。

    4. 容错和并行化
    每个请求,数据返回都可能失败或成功,需要不定的时间长度。所以系统要尽可能做到并行,容错。互联网项目尤其是这样,网络环境不是可信环境。

    5. 易于维护和管理
    项目中期应该做到容易监控和维护。

    有关开发效率和协作的几点
    https://blog.devopszen.com/team_performance

  2. 互联网系统可靠性基础:正确的异常处理
    https://blog.devopszen.com/exception

    Try catch 的内部实现
    异常必然发生
    异常处理的性能考虑
    几个理念:Fail fast vs Retry vs Let it crash
    异常和错误的类型
    守门员:全局异常处理
    异常处理总结和一些原则
    一些有用的资料

  3. 07 | 准备Plan B:如何设计兜底方案?
    https://time.geekbang.org/column/article/40744

    高可用建设应该从哪里着手?
    具体来说,系统的高可用建设涉及架构阶段、编码阶段、测试阶段、发布阶段、运行阶段,以及故障发生时。接下来,我们分别看一下。
    1、架构阶段:架构阶段主要考虑系统的可扩展性和容错性,要避免系统出现单点问题。例如多机房单元化部署,即使某个城市的某个机房出现整体故障,仍然不会影响整体网站的运转。
    2、编码阶段:编码最重要的是保证代码的健壮性,例如涉及远程调用问题时,要设置合理的超时退出机制,防止被其他系统拖垮,也要对调用的返回结果集有预期,防止返回的结果超出程序处理范围,最常见的做法就是对错误异常进行捕获,对无法预料的错误要有默认处理结果。
    3、测试阶段:测试主要是保证测试用例的覆盖度,保证最坏情况发生时,我们也有相应的处理流程。
    4、发布阶段:发布时也有一些地方需要注意,因为发布时最容易出现错误,因此要有紧急的回滚机制。
    5、运行阶段:运行时是系统的常态,系统大部分时间都会处于运行态,运行态最重要的是对系统的监控要准确及时,发现问题能够准确报警并且报警数据要准确详细,以便于排查问题。
    6、故障发生:故障发生时首先最重要的就是及时止损,例如由于程序问题导致商品价格错误,那就要及时下架商品或者关闭购买链接,防止造成重大资产损失。然后就是要能够及时恢复服务,并定位原因解决问题。

    为什么系统的高可用建设要放到整个生命周期中全面考虑?因为我们在每个环节中都可能犯错,而有些环节犯的错,你在后面是无法弥补的。例如在架构阶段,你没有消除单点问题,那么系统上线后,遇到突发流量把单点给挂了,你就只能干瞪眼,有时候想加机器都加不进去。所以高可用建设是一个系统工程,必须在每个环节都做好。

  4. 从拼多多系统漏洞, 阿里专家谈码农如何防背锅
    https://mp.weixin.qq.com/s/vx61KfZhkiKXHYSsJ52J_w

    处理故障三板斧
    1-止血,止血,止血
    2-复盘
    3-改进

    避免故障三板斧
    1. 发布前,确保有效的数字化监控
    2. 发布时,逐步灰度
    3. 发布后,一键回滚的能力

    理解产品周期与线上故障
    技术故障,在产品的初期,到发展期,到成熟期,到半衰期,是有着不一样的影响效力和重视程度。
    1、产品初期:一切为了快速试错+反馈
    2、产品发展期:故障的快速处理开始被要求
    3、产品成熟期:线上故障几乎是0容忍态度
    4、产品半衰期:既要业务创新,又要技术稳定

    敬畏每一次线上操作变更的风险,落实发布能够灰度、数据大盘监控、业务数据指标是否符合预期。

    加强有效报警,从对敬畏故障的思想做起,在基础能力建设完善的基础基础上,未来实现“无人盯守,发现问题,自动告警,风险预测,自动回滚”,让devOps从经常要搞到凌晨发布,无法安心入睡的困境中解救出来,减少一线拧螺丝人员的背锅次数,减少系统释放处来的背锅HC机会,最终实现已知领域内的线上功能服务的高可用。

  5. 分布式架构知识体系
    https://mp.weixin.qq.com/s/9xINMH9tJlmsjH6QdUPFxQ

    1、何为分布式何为微服务?
    2、为什么需要分布式?
    3、分布式核心理论基础,节点、网络、时间、顺序,一致性?
    4、分布式是系统有哪些设计模式?
    5、分布式有哪些类型?
    6、如何实现分布式?

  6. 互联网架构三板斧之并发
    https://mp.weixin.qq.com/s/87JWlUoc03UZy2ar3p4NlA

    对大流量系统的数据做分层校验也是最重要的设计原则,所谓分层校验就是对大量的请求做成“漏斗”式设计,在不同层次尽可能把无效的请求过滤,“漏斗”的最末端才是有效的请求,要达到这个效果必须对数据做分层的校验,下面是一些原则:
    1、先做数据的动静分离
    2、将90%的数据缓存在客户端浏览器
    3、将动态请求的读数据Cache在Web端
    4、对读数据不做强一致性校验
    5、对写数据进行基于时间的合理分片
    6、对写请求做限流保护
    7、对写数据进行强一致性校验

  7. 如果20万用户同时访问一个热点缓存,如何优化你的缓存架构?【石杉的架构笔记】
    https://mp.weixin.qq.com/s/RqBla4rg8ut3zEBKhyBo1w

    (1)为什么要用缓存集群
    (2)20万用户同时访问一个热点缓存的问题
    (3)基于流式计算技术的缓存热点自动发现
    (4)热点缓存自动加载为JVM本地缓存
    (5)限流熔断保护
    (6)总结

  8. 四种软件架构:Serverless架构、微服务架构、分布式架构、单体架构
    https://mp.weixin.qq.com/s/5CUm44VjXRCoxagYpMRQBQ

    一、单体架构
    单体架构比较初级,典型的三级架构,前端(Web/手机端)+中间业务逻辑层+数据库层。这是一种典型的Java Spring mvc或者Python Django框架的应用。

    单体架构的应用比较容易部署、测试, 在项目的初期,单体应用可以很好地运行。然而,随着需求的不断增加, 越来越多的人加入开发团队,代码库也在飞速地膨胀。慢慢地,单体应用变得越来越臃肿,可维护性、灵活性逐渐降低,维护成本越来越高。下面是单体架构应用的一些缺点:

    复杂性高: 以一个百万行级别的单体应用为例,整个项目包含的模块非常多、模块的边界模糊、 依赖关系不清晰、 代码质量参差不齐、 混乱地堆砌在一起。可想而知整个项目非常复杂。 每次修改代码都心惊胆战, 甚至添加一个简单的功能, 或者修改一个Bug都会带来隐含的缺陷。

    技术债务: 随着时间推移、需求变更和人员更迭,会逐渐形成应用程序的技术债务, 并且越积 越多。“ 不坏不修”, 这在软件开发中非常常见, 在单体应用中这种思想更甚。 已使用的系统设计或代码难以被修改,因为应用程序中的其他模块可能会以意料之外的方式使用它。

    部署频率低: 随着代码的增多,构建和部署的时间也会增加。而在单体应用中, 每次功能的变更或缺陷的修复都会导致需要重新部署整个应用。全量部署的方式耗时长、 影响范围大、 风险高, 这使得单体应用项目上线部署的频率较低。 而部署频率低又导致两次发布之间会有大量的功能变更和缺陷修复,出错率比较高。

    可靠性差: 某个应用Bug,例如死循环、内存溢出等, 可能会导致整个应用的崩溃。

    扩展能力受限: 单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。例如,应用中有的模块是计算密集型的,它需要强劲的CPU; 有的模块则是IO密集型的,需要更大的内存。 由于这些模块部署在一起,不得不在硬件的选择上做出妥协。

    阻碍技术创新: 单体应用往往使用统一的技术平台或方案解决所有的问题, 团队中的每个成员 都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。

    二、分布式应用
    该架构相对于单体架构来说,这种架构提供了负载均衡的能力,大大提高了系统负载能力,解决了网站高并发的需求。另外还有以下特点:
    降低了耦合度:把模块拆分,使用接口通信,降低模块之间的耦合度。
    责任清晰:把项目拆分成若干个子项目,不同的团队负责不同的子项目。
    扩展方便:增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。
    部署方便:可以灵活的进行分布式部署。
    提高代码的复用性:比如service层,如果不采用分布式rest服务方式架构就会在手机wap商城,微信商城,pc,android,ios每个端都要写一个service层逻辑,开发量大,难以维护一起升级,这时候就可以采用分布式rest服务方式,公用一个service层。

    缺点 : 系统之间的交互要使用远程通信,接口开发增大工作量,但是利大于弊。

    三、微服务架构
    微服务架构,主要是中间层分解,将系统拆分成很多小应用(微服务),微服务可以部署在不同的服务器上,也可以部署在相同的服务器不同的容器上。当应用的故障不会影响到其他应用,单应用的负载也不会影响到其他应用,其代表框架有Spring cloud、Dubbo等。

    四、Serverless架构
    Serverless架构能够让开发者在构建应用的过程中无需关注计算资源的获取和运维,由平台来按需分配计算资源并保证应用执行的SLA(服务等级协议),按照调用次数进行计费,有效的节省应用成本。

    目前微服务架构在四种架构中处于主流地位,很多应用第一、第二种架构的企业也开始慢慢转向微服务架构。到目前为止微服务的技术相对于二三年前已经比较成熟,第四种架构将是未来发展的一种趋势。如果你喜欢我的文章,欢迎关注我的简书,后续我将教会大家利用spring cloud和docker轻松愉快的构建微服务。

  9. 高并发编程知识体系
    https://mp.weixin.qq.com/s/qaj37YYxz7afD-WfAZeN8Q

    1.问题
    1、什么是线程的交互方式?
    2、如何区分线程的同步/异步,阻塞/非阻塞?
    3、什么是线程安全,如何做到线程安全?
    4、如何区分并发模型?
    5、何谓响应式编程?
    6、操作系统如何调度多线程?

    2.关键词
    同步,异步,阻塞,非阻塞,并行,并发,临界区,竞争条件,指令重排,锁,amdahl,gustafson

    3.全文概要
    上一篇我们介绍分布式系统的知识体系,由于单机的性能上限原因我们才不得不发展分布式技术。那么话说回来,如果单机的性能没能最大限度的榨取出来,就盲目的就建设分布式系统,那就有点本末倒置了。而且上一篇我们给的忠告是如果有可能的话,不要用分布式,意思是说如果单机性能满足的话,就不要折腾复杂的分布式架构。如果说分布式架构是宏观上的性能扩展,那么高并发则是微观上的性能调优,这也是上一篇性能部分拆出来的大专题。本文将从线程的基础理论谈起,逐步探究线程的内存模型,线程的交互,线程工具和并发模型的发展。扫除关于并发编程的诸多模糊概念,从新构建并发编程的层次结构。

  10. 朱晔的互联网架构实践心得S1E9:架构评审一百问和设计文档五要素
    https://mp.weixin.qq.com/s/iRU4NLK9DEHacix1qNX8Yw

    组件选型
    · 为什么选A不选B呢?
    · A不是开源的,出了问题怎么办?
    · B虽然是开源的,但是是Erlang写的,公司没人能看懂怎么办?
    · C我看待解决的Issues还有很多,有没有去了解过?
    · 这个组件在性能方面你是否了解过?
    · 开源的免费版本不支持集群怎么办?
    · 如果彻底要自己写这个组件有没有可能性?

    性能
    · 我们需求的TPS、QPS和RT是多少?
    · 整体设计上会做到的TPS、QPS和RT是多少?
    · 随着数据量的增大系统性能会不会出现明显问题?
    · 系统哪个环节会是最大的瓶颈?
    · 是否打算做压力测试,压力测试方案是怎么样的?
    · 怎么提高前端用户的访问流畅性?

    可伸缩性
    · 每一个环节是否都是可以横向扩展的?
    · 扩容需要怎么做手动还是自动?
    · 数据库不能横向扩展怎么办?
    · 纵向扩展有多少效果?
    · 横向扩展是否是线性的?
    · 扩展后是否可以提高响应速度?

    灵活性
    · 是否有了解过产品层面以后会怎么发展?
    · 模块A是否能拆分出去独立为其它业务服务?
    · 模块B是否可以替换为另一种第三方数据源?
    · 如果流程有变,需要多大的工作量来适应?
    · 业务是否可以做到可配?

    可扩展性
    · 为什么A和B都有差不多的逻辑?
    · 是否考虑到了A业务的实现以后还有B的可能性?
    · 如果现在有两种策略以后扩展到了八种策略怎么做?
    · 以后是否可以把这个业务的H5前端适配到PC?

    可靠性
    · 是否架构中有单点?
    · 故障转移是怎么实现的?
    · 集群内部故障转移需要多久?
    · MQ或存储出现问题的时候系统会怎么样?
    · MQ或存储出现问题又恢复了系统是否会自己恢复?
    · 是否考虑过异地故障转移的方案?
    · 是否考虑过多活的方案?
    · 是否有数据丢失的可能性?
    · 数据丢失后是否可以恢复?
    · 系统彻底挂了对其它业务的影响是什么?
    · 系统彻底挂了是否可以有线下的方式走业务?

    安全性
    · 是否彻底避免SQL注入和XSS?
    · 是否做了风控策略?
    · 是否有防刷保护机制?
    · 数据库拖库了会怎么样?
    · 是否有数据泄露的可能性?
    · 数据的权限怎么控制的?
    · 功能的权限是怎么控制的?
    · 是否做了日志审计?
    · 受到了DDOS攻击怎么办?
    · 数据传输是否加密验签?

    兼容性
    · 老的系统打算怎么办?
    · 怎么进行新老系统替换?
    · 新老系统能否来回切换?
    · 别的系统怎么连接你这套新服务?
    · 上下游依赖是否梳理过,影响范围多大?
    · 上下游改造的难度怎么样?
    · 上下游改造有排期吗?
    · 上下游改造的计划和通知时间确定了吗?
    · 使用了新的数据源数据怎么迁移?
    · 使用了新的技术老项目开发能否适应?

    弹性处理
    · 这个数据重复消费会怎么样?
    · 这个接口重复调用会怎么样?
    · 是否考虑了服务降级?哪些业务支持降级?
    · 是否考虑了服务熔断?熔断后怎么处理?
    · 是否考虑了服务限流?限流后客户端表现怎么样?
    · 队列爆仓会怎么样?
    · 是否考虑了隔离性?

    事务性
    · 这段业务由谁保证事务性?
    · 数据库事务回滚后会怎么样?
    · 服务调用了失败怎么办?
    · 队列补偿怎么做的?
    · 服务调用补偿怎么做的?
    · 数据补偿实现最终一致需要多久?
    · 在数据不完整的时候用户会感知到吗?

    可测试性
    · 测试环境和线上的差异多大?
    · 是否支持部署多套隔离的测试环境?
    · 是否打算做单元测试,覆盖率目标是多少?
    · 测试黑盒白盒工作量的比例是怎么样的?
    · 是否支持接口层面的自动化测试?
    · 是否有可能做UI自动化测试?
    · 压测怎么造数据?
    · 是否可以在线上做压测?
    · 线上压测怎么隔离测试数据?
    · 是否有测试白名单功能?

    可运维性
    · 每一个组件对服务器哪方面的压力会最大?
    · 重新搭建整套系统最快需要多少时间?
    · 系统是否可以完全基于源代码构建?
    · 系统是否有初始化或预热的环节?
    · 系统里哪些环节需要人工参与?
    · 数据是否需要定期归档处理?
    · 会不会有突发的数据量业务量增大?
    · 随着时间的推移如果压力保持不变的话系统需要怎么来巡检和维护?
    · 怎么在容器里进行部署?

    监控
    · 业务层面哪些指标需要监控和报警?
    · 应用层面系统内部是否有暴露了一些指标作监控和报警?
    · 系统层面使用的中间件和存储是否有监控报警?
    · 是否所有环节都接入了全链路跟踪?
    · 出现报警的时候应该由谁来处理?
    · 每一个模块是否有固定的主要和次要负责人?
    · 有没有可能系统出了问题无法通过监控指标体现?
    · 哪些指标需要上大屏由监控进行7*24监控?

  11. 朱晔的互联网架构实践心得S2E6:浅谈高并发架构设计的16招
    https://mp.weixin.qq.com/s/mts-LDlhjACDkvqTU9u9Zw

    标题中的高并发架构设计是指设计一套比较合适的架构来应对请求、并发量很大的系统,使系统的稳定性、响应时间符合预期并且能在极端的情况下自动调整为相对合理的服务水平。一般而言我们很难用通用的架构设计的手段来解决所有问题,在处理高并发架构的时候也需要根据系统的业务形态有针对性设计架构方案,本文只是列出了大概可以想到一些点,在设计各种方案的时候无非是拿着这些点组合考虑和应用。 有很多高并发架构相关的文章都是在介绍具体的技术点,本文尝试从根源来总结一些基本的方法,然后再引申出具体的实现方式或例子。下面是本文会介绍的16个方面的大纲:

    减少请求数量:
      合并请求
      边缘加速
    提升处理性能:
      空间换时间
      任务并行化
      处理异步化
      合适的存储
      更快的网络
    增加处理能力:
      模块拆分
      负载均衡
      分区处理
      纵向扩展
    稳定性和弹性:
      压测
      隔离
      限流
      熔断
      降级

    总结一下,对于高并发应用如何去考虑性能优化,说白了就这么几个思路:

    1、要么是尽可能通过让并发别这么大,有的时候真没必要一拥而上造成人为的大并发。
    2、要么是尽可能优化代码、存储、网络,越简单,操作需要的CPU、IO、内存、网络资源越少在一定的服务器资源下就越可能应对更多的并发。
    3、要么就是通过扩展资源,扩展服务器来提高处理能力。
    4、最后一招就是在因为并发过大不稳定的时候系统需要启用一定的应急手段开启自保,别人工系统被流量压垮彻底挂了。

  12. 混沌工程 – 软件系统高可用、弹性化的必由之路
    https://tech.youzan.com/chaosmonkey/

    混沌工程的定义:
    通过观察分布式系统在受控的故障注入测试中的行为变化发掘系统弱点,并针对性的改进,从而提高系统可靠性,建立系统抵御失控条件的能力的信心。所以,混沌工程并不是一个新概念,常见的异地容灾测试也是混沌工程的一种应用。

    混沌工程的一般实施步骤:
    寻找一些系统正常运行状态下的可度量指标,作为基准的“稳定状态”
    假设实验组和对照组都能继续保持这个“稳定状态”
    对实验组进行事件注入,如服务器崩溃、硬盘故障、网络连接断开等等
    比较实验组和对照组“稳定状态”的差异,推翻上述第2条的假设
    如果混沌工程实施下来两者的“稳定状态”一致,则可以认为系统应对这种故障是弹性的,从而对系统建立更多信心。相反的,如果两者的稳定状态不一致,那我们就找到了一个系统弱点,从而可以修复它,提高系统可靠性。

    混沌工程的理想原则:
    1)根据“稳定状态下系统的特征”做一个假设
    2)事件是现实世界真的可能发生的
    3)在生产环境跑
    4)持续集成
    5)最小化影响范围

    上面是最理想情况下的混沌工程,现实中我们需要根据现有软件成熟度有阶段的实施混沌:
    阶段一:分布式系统弹性化一般
    阶段二:分布式系统弹性化成熟

  13. 这样的高可用,我不要!
    https://mp.weixin.qq.com/s/UQS5Pd6Dvcvm5lVuzsIorQ

    前不久,朋友的公司,出现了比较大的故障。故障引起的原因也比较好解释,因为使用了ActiveMQ的高可用级别(M-S架构,双写完成ACK),结果在高峰期间,造成了生产端消息拥堵,诸多请求无法落地,数据错乱。

    据他说,他们的应用,级别比电信应用还要高(牛皮一定要吹),所以消息系统要求一条消息都不能丢。他做到了,但是服务不能用了。

    高可用是个伪命题,虽然有CAP等耳熟能详的理论支持,还是有很多人陷入了这个误区,包括技术决策人。架构作为全局把控人,能出现这样的错误,纯属低级。下面,是我自己对高可用的一点思考。

    高可用不是组件高可用,是业务高可用
    业务先能用,然后讲可靠
    主要流程不能阻断,可靠性降级
    主要流程不能阻断,可靠性降级
    数据不能丢,我还能找回来

    别把高可用挂在嘴上,那很sb
    分布式系统是个复杂的整体,不要以偏概全,搞定了某个组件并不等于搞定真个系统。领导会认为这样,你不能。

  14. 没有预热,不叫高并发,叫并发高
    https://mp.weixin.qq.com/s/IVFf2B7UPY2XaJUgAM3sjg

    大家都知道,高并发系统有三把斧子:缓存、熔断和限流。但还有一把斧子,经常被遗忘在角落里,郁郁不得志,那就是预热。

    一、DB重启后,瞬间死亡
    一个高并发环境下的DB,进程死亡后进行重启。由于业务处在高峰期间,上游的负载均衡策略发生了重分配。刚刚启动的DB瞬间接受了1/3的流量,然后load疯狂飙升,直至再无响应。

    原因就是:新启动的DB,各种Cache并没有准备完毕,系统状态与正常运行时截然不同。可能平常1/10的量,就能够把它带入死亡。

    二、服务重启后,访问异常
    另外一个常见的问题是:我的一台服务器发生了问题,由于负载均衡的作用,剩下的机器立马承载了这些请求,运行的很好。当服务重新加入集群时,却发生了大量高耗时的请求,在请求量高的情况下,甚至大批大批的失败。

    引起的原因大概可以归结于:

    1、服务启动后,jvm并未完全准备完毕,JIT未编译等。
    2、应用程序使用的各种资源未准备就绪。
    3、负载均衡发生了rebalance。

    这两个问题,都是没有做好预热

    Warm Up,即冷启动/预热的方式。当系统长期处于低水位的情况下,流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过”冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。

    通过比较,我们发现,最靠谱的方式还是进行编码,将warmup逻辑集成在客户端。这个工作可能是痛苦的、漫长的,但结局是美好的。
    当然也可以通过“摘除nginx->修改权重->reload nginx”的方式。有时很有效但不总是有效,通常很放心但不总是放心。
    一切随你。毕竟没有前戏直奔主题,那叫鲁莽。

  15. 开发更高质量的服务
    http://vearne.cc/archives/39164

    1.引言
    产品要求的功能都都开发完了,但这并不是终结。怎么样做才能让我们的服务具有更好的质量。
笔者结合自己的遇到的问题和工作中的经验,并以提问的方式,给读者一点点建议
    2. 提问
    重要性不分先后
    2.1 如果服务器重启,服务是否能自动拉起?
    2.2 如果程序异常退出,服务是否能够自动拉起?
    2.3 如果程序异常退出,能够自动拉起,那么你怎么知道服务是否发生了重启?
    2.4 如果是web服务,QPS是多少?每个URL的QPS是多少?
    峰值是多少?一般在什么时间点触发?
每种URL的请求量是否合理?
    2.5 如果是web服务,每个请求的响应时间是多少?TP90?TP99分别是多少?
    2.6 异常请求(比如HTTP非200的比例是多少?)什么样的比例是合理的?为什么?
    2.7 如果是多实例部署,那么整个系统的承载极限是多少?如果达到了极限,瓶颈在哪儿(木桶原理中所谓的短板)
    2.8 服务都有哪些依赖项(微服务/数据库/文件系统)
    其中哪些是无状态的,哪些是弱状态的,哪些是强状态的。这些外部服务和系统,是否已经做到高可用?能否做到快速扩容?
    2.9 服务消耗的带宽多少?是否有可能达到带宽上限
    如果是面向公网的服务,请求是否已经进行了压缩?
    2.10 服务在部署上,是否已经做到了二地三机房
    每个地区的网络线路,是否能做到2套或2套以上
(防止光纤被挖断的情况)
    2.11 DNS服务是否能够对后端服务进行探活,自动修改域名的解析列表
    2.12 部署是否实现了自动化
    如果服务需要紧急扩容,该怎么做?
基于docker的容器化方案,还是ansible脚本?
    2.13 文档是否完整,文档是否能与代码保持一致
    2.14 如果是比较复杂的业务系统,是否有完整的自动化测试脚本
    2.15 如果使用了数据库,比如用到了Redis/MySQL
    Redis连接池和MySQL连接池,是否已经打满(达到最大的poolSize)
打满之后,程序是会等待,还是报错?
    2.16 如果使用了Redis,每次Redis操作的耗时是多少?TP90?TP99?
    有没有慢查询?这些慢查询是否合理?
    2.17 如果使用了MySQL,SQL是否做过审核
    哪些表的操作频率最高?那种类型的操作最多?
有没有慢查询?这些慢查询是否合理?
有没有联表过多的查询?
    2.18 如果使用了cache,cache的命中率是多少?
    cache会不会与数据库存储不一致,不一致是否可以容许
    2.19 如果使用了负载均衡,负载均衡与服务之间是长连接吗?
    如果服务和其它服务有交互,他们之间是长连接吗?
    2.20 服务所在机器CPU负载怎么样?连接数高吗?
    是否有大量的TIME_WAIT和CLOSE_WAIT
    2.21 是否做了tracing
    2.22 是否记录了access log
    2.23 服务是否能够优雅退出?
    2.24 服务如果是异常退出,是否会造成数据不一致?
    如果有可能造成不一致,那么如何发现这种不一致?有没有对应修复的策略
比如在交易系统中的定期对账
    2.25 这个服务中,哪些部分是最核心的,是否能做熔断降级处理
    比如一个新闻客户端,如果出现服务出现故障,可以降级为新闻只读,但是无法评论
    2.26 如果是API服务,有没有对请求做超时处理
    防止请求一直阻塞。
    2.27 如果调用方是APP,那么是否在APP中,埋有探针,以便日后分析排障
    2.28 数据库有没有定期备份?
    如果已经做了备份,是否是备份在异构的数据库中
    2.29 如果是API服务,是否有请求频率限制
    如果有是按照用户维度,还是按照IP维度来限制?

  16. 如何健壮你的后端服务?
    https://www.cnblogs.com/LBSer/p/4753112.html

    “怀疑第三方,防备使用方,做好自己”

    对每一个程序员而言,故障都是悬在头上的达摩克利斯之剑,都唯恐避之不及,如何避免故障是每一个程序员都在苦苦追寻希望解决的问题。对于这一问题,大家都可以从需求分析、架构设计 、代码编写、测试、code review、上线、线上服务运维等各个视角给出自己的答案。本人结合自己两年有限的互联网后端工作经验,从某几个视角谈谈自己对这一问题的理解,不足之处,望大家多多指出。

    我们大部分服务都是如下的结构,既要给使用方使用,又依赖于他人提供的第三方服务,中间又穿插了各种业务、算法、数据等逻辑,这里面每一块都可能是故障的来源。如何避免故障?我用一句话概括,“怀疑第三方,防备使用方,做好自己”。

    1 怀疑第三方
    1.1 有兜底,制定好业务降级方案
    1.2 遵循快速失败原则,一定要设置超时时间
    1.3 适当保护第三方,慎重选择重试机制

    2 防备使用方
    2.1 设计一个好的api(RPC、Restful),避免误用
    2.2 流量控制,按服务分配流量,避免滥用

    3 做好自己
    3.1 单一职责原则
    3.2 控制资源的使用
    3.2.1 CPU资源怎么限制?
    3.2.2 内存资源怎么限制?
    3.2.3 网络资源怎么限制?
    3.2.4 磁盘资源怎么限制?
    3.3 避免单点

  17. 【前端词典】输入 URL 到展现涉及的缓存环节
    https://mp.weixin.qq.com/s/zmUYi1IL_ZJy3t8brHtI-A

    # 不一定都对,但可以当做思路扩展的一种方式方法:

    地址栏网址缓存
    检查 HSTS 预加载列表
    DNS 缓存
    ARP(地址解析协议)缓存
    TCP 发送缓冲区 & 接收缓冲区
    HTTP 请求缓存( CDN 节点缓存、代理服务器缓存、浏览器缓存、后端动态计算结果缓存等 )

  18. 【最佳实践】如何优雅的进行重试
    https://mp.weixin.qq.com/s/GNdCB7QzAtjSKm0-8K1v-w

    本文由浅入深的对多种重试的姿势进行了360度无死角教学,从最简单的手动重试,到使用静态代理,再到JDK动态代理和CGLib动态代理,再到Spring AOP,都是手工造轮子的过程,最后介绍了两种目前比较好用的轮子,一个是Spring Retry,使用起来简单粗暴,与Spring框架天生搭配,一个注解搞定所有事情,另一个便是Guava Retry,不依赖于Spring框架,自成体系,使用起来更加灵活强大。

    个人认为,大部分场景下,Spring Retry提供的重试机制已经足够强大,如果不需要Guava Retry提供的额外灵活性,使用Spring Retry就很棒了。当然,具体情况具体分析,但没有必要的情况下,不鼓励重复造轮子,先把别人的轮子研究清楚再想想还用不用自己动手。

    本文到此就告一段落了,又用了一天的时间完成了完成了一篇文章,写作的目的在于总结和分享,我相信最佳实践是可以总结和积累下来的,在大多数场景下都是适用的,这些最佳实践会在逐渐的积累过程中,成为比经验更为重要的东西。因为经验不总结就会忘记,而总结出来的内容却不会被丢失。

  19. 互联网架构三板斧之并发
    https://mp.weixin.qq.com/s/UFy_FWypcOS_szHTmgsChg

    第一板斧:活下来 [Stability]
    稳定性实践笔者印象比较深的有2篇内容,一是由淘宝小邪在2011年分享的[淘宝稳定性实践]。

    第二板斧:简单可扩展(scalability)
    啥叫可扩展,就是可以不断加资源以达成更大容量,支撑更高的并发、迎接更多用户。这里的资源可以是应用服务器,也可以是数据库服务器,或者是缓存服务器。

    第三板斧:拦河大坝、去并发
    为啥要拦?很简单,用户很热情(感性),但系统必须得理性!就3个苹果手机,凭啥让几十万人都涌入柜台!

    对大流量系统的数据做分层校验也是最重要的设计原则,所谓分层校验就是对大量的请求做成“漏斗”式设计,如上图所示:在不同层次尽可能把无效的请求过滤,“漏斗”的最末端才是有效的请求,要达到这个效果必须对数据做分层的校验,下面是一些原则:
    1、先做数据的动静分离
    2、将90%的数据缓存在客户端浏览器
    3、将动态请求的读数据Cache在Web端
    4、对读数据不做强一致性校验
    5、对写数据进行基于时间的合理分片
    6、对写请求做限流保护
    7、对写数据进行强一致性校验

    将90%的数据缓存在客户端浏览器,将动态请求的读数据cache在web端,还是不够的。在大秒的过程中,存在极端情况,就是请求超过单key所在server的QPS能力。

    解决并发有1种基本办法: 分拆!而分拆有两种拆法,
    1、拆资源
    一是把资源(resource)拆了,著名的比如ConcurrentHashMap,拆成了16个桶,并发能力大大提高。
    2、拆基础数据
    在红包应用中,如果还依赖一个共同的基础数据,也可以把这个基础数据拆成多个cell。

    在第三板斧中又有分层拦截、多级缓存、数据近端、分拆锁、预处理、异步化及队列等pattern。学习原则:灵活运用,不尽信经验。

  20. 18个最可能限制系统扩展能力的瓶颈,警惕!!!
    https://mp.weixin.qq.com/s/YqP07IxeM2K8BEeT76JzmA

    1. 二阶提交
    2. 串行处理
    3. 内存不足
    4. 监控和指标不足
    5. 日志不足
    6. 数据库单点
    7. 把数据库当作队列
    8. 使用数据库全文检索
    9. ORM
    10. 没有仪表盘
    11. 没有代码仓库或者版本控制
    12. 单点问题
    13. 预览模式缺失
    14. 缺少沟通
    15. 缺乏文档
    16. 缺少故障演练
    17. 鲁莽行为
    18. 日益增长的技术债

    http://highscalability.com/blog/2013/8/28/sean-hulls-20-biggest-bottlenecks-that-reduce-and-slow-down.html

  21. 注意!开发可伸缩系统必须遵守这11个软件设计原则
    https://mp.weixin.qq.com/s/jhruPpGCdT5VYx-ZHCPrpg

    01简单
    02低耦合
    03DRY-不要重复自己
    04基于约定的编程
    05画架构图
    06单一职责
    07开闭原则
    08依赖注入
    09控制反转
    10为伸缩而设计
    11自愈设计

    # 总结
    不管你是软件工程师、开发组长、技术经理、架构师等,软件设计原则对你都是非常重要的!
    本文简要讲述了:简单、低耦合、不要重复自己DRY、基于约定编程、画架构图、单一职责、开闭原则、依赖注入、控制反转、为伸缩而设计、自愈设计等11个软件设计原则。
    以上11个软件设计原则,会帮助你更好的开发出一个可伸缩的系统。

  22. 容错,高可用和灾备
    http://www.ruanyifeng.com/blog/2019/11/fault-tolerance.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

    # 容错(fault tolerance)指的是, 发生故障时,系统还能继续运行。
    容错的目的是,发生故障时,系统的运行水平可能有所下降,但是依然可用,不会完全失败。

    # 高可用(high availability)指的是, 系统能够比正常时间更久地保持一定的运行水平。
    汽车的备胎就是一个高可用的例子。如果没有备胎,轮胎坏了,车就开不久了。备胎延长了汽车行驶的可用时间。
    注意,高可用不是指系统不中断(那是容错能力),而是指一旦中断能够快速恢复,即中断必须是短暂的。如果需要很长时间才能恢复可用性,就不叫高可用了。上面例子中,更换备胎就必须停车,但只要装上去,就能回到行驶状态。

    # 灾备(又称灾难恢复,disaster recovery)指的是, 发生灾难时恢复业务的能力。
    灾备的目的就是,保存系统的核心部分。一个好的灾备方案,就是从失败的基础设施中获取企业最宝贵的数据,然后在新的基础设施上恢复它们。注意,灾备不是为了挽救基础设置,而是为了挽救业务。

    容错:发生故障时,如何让系统继续运行。
    高可用:系统中断时,如何尽快恢复。
    灾备:系统毁灭时,如何抢救数据。

发表评论

电子邮件地址不会被公开。 必填项已用*标注