跳转至

你好,我是陈皓,网名左耳朵耗子。

我们前面讲了那么多的弹力设计的设计模式,这里做个总结。

弹力设计总图

首先,我们的服务不能是单点,所以,我们需要在架构中冗余服务,也就是说有多个服务的副本。这需要使用到的具体技术有:

  • 负载均衡 + 服务健康检查–可以使用像Nginx或HAProxy这样的技术;
  • 服务发现 + 动态路由 + 服务健康检查,比如Consul或ZooKeeper;
  • 自动化运维,Kubernetes 服务调度、伸缩和故障迁移。

然后,我们需要隔离我们的业务,要隔离我们的服务我们就需要对服务进行解耦和拆分,这需要使用到以前的相关技术。

  • bulkheads模式:业务分片 、用户分片、数据库拆分。
  • 自包含系统:所谓自包含的系统是从单体到微服务的中间状态,其把一组密切相关的微服务给拆分出来,只需要做到没有外部依赖就行。
  • 异步通讯:服务发现、事件驱动、消息队列、业务工作流。
  • 自动化运维:需要一个服务调用链和性能监控的监控系统。

然后,接下来,我们就要进行能让整个架构接受失败的相关处理设计,也就是所谓的容错设计。这会用到下面的这些技术。

  • 错误方面:调用重试 + 熔断 + 服务的幂等性设计。
  • 一致性方面:强一致性使用两阶段提交、最终一致性使用异步通讯方式。
  • 流控方面:使用限流 + 降级技术。
  • 自动化运维方面:网关流量调度,服务监控。

我不敢保证上面这些技术可以解决所有的问题,但是,只要我们设计得当,绝大多数的问题应该是可以扛得住的了。

下面我画一个图来表示一下。


在上面这个图上,我们可以看到,有三大块的东西。

  • 冗余服务。通过冗余服务的复本数可以消除单点故障。这需要服务发现,负载均衡,动态路由和健康检查四个功能或组件。
  • 服务解耦。通过解耦可以做到把业务隔离开来,不让服务受影响,这样就可以有更好的稳定性。在水平层面上,需要把业务或用户分片分区(业分做隔离,用户做多租户)。在垂直层面上,需要异步通讯机制。因为应用被分解成了一个一个的服务,所以在服务的编排和聚合上,需要有工作流(像Spring的Stream或Akka的flow或是AWS的Simple Workflow)来把服务给串联起来。而一致性的问题又需要业务补偿机制来做反向交易。
  • 服务容错。服务容错方面,需要有重试机制,重试机制会带来幂等操作,对于服务保护来说,熔断,限流,降级都是为了保护整个系统的稳定性,并在可用性和一致性方面在出错的情况下做一部分的妥协。

当然,除了这一切的架构设计外,你还需要一个或多个自动运维的工具,否则,如果是人肉运维的话,那么在故障发生的时候,不能及时地做出运维决定,也就空有这些弹力设计了。比如:监控到服务性能不够了,就自动或半自动地开始进行限流或降级。

弹力设计开发和运维

对于运维工具来说,你至少需要两个系统:

  • 一个是像APM这样的服务监控;
  • 另一个是服务调度的系统,如:Docker + Kubernetes。

此外,如果你需要一个开发架构来让整个开发团队在同一个标准下开发上面的这些东西,这里,Spring Cloud就是不二之选了。

关于Spring Cloud和Kubernetes,它们都是为了微服务而生,但它们没有什么可比性,因为,前者偏开发,后者偏运维。我们来看一下它们的差别。


(图片来自:Deploying Microservices: Spring Cloud vs Kubernetes)

从上表我们可以得知:

  • Spring Cloud有一套丰富且集成良好的Java库,作为应用栈的一部分解决所有运行时问题。因此,微服务本身可以通过库和运行时代理解决客户端服务发现、负载均衡、配置更新、统计跟踪等。工作模式就像单实例服务集群。(译者注:集群中master节点工作:当master挂掉后,slave节点被选举顶替。)并且一批工作也是在JVM中被管理。
  • Kubernetes不是针对语言的,而是针对容器的,所以,它是以通用的方式为所有语言解决分布式计算问题。Kubernetes提供了配置管理、服务发现、负载均衡、跟踪、统计、单实例、平台级和应用栈之外的调度工作。该应用不需要任何客户端逻辑的库或代理程序,可以用任何语言编写。

下图是微服务所需的关键技术,以及这些技术中在Spring Cloud和Kubernetes的涵盖面。


(图片来自:Deploying Microservices: Spring Cloud vs Kubernetes)

两个平台依靠相似的第三方工具,如ELK和EFK stacks, tracing libraries等。Hystrix和Spring Boot等库,在两个环境中都表现良好。很多情况下,Spring Cloud和Kubernetes可以形成互补,组建出更强大的解决方案(例如KubeFlix和Spring Cloud Kubernetes)。

下图是在Kubernetes上使用Spring Cloud可以表现出来的整体特性。要做出一个可运维的分布式系统,除了在架构上的设计之外,还需要一整套的用来支撑分布式系统的管控系统,也就是所谓的运维系统。要做到这些,不是靠几个人几天就可以完成的。这需要我们根据自己的业务特点来规划相关的实施路径。


(图片来自:Deploying Microservices: Spring Cloud vs Kubernetes)

上面这张图中,对于所有的特性,都列举了一些相关的软件和一些设计的重点,其中红色的是运维层面的和Spring Cloud和Kubernetes不相关的,绿色的Spring Cloud提供的开发框架,蓝色的是Kubernetes相关的重要功能。

从今天看下来,微服务的最佳实践在未来有可能会成为SpringCloud和Kubernetes的天下了。这个让我们拭目以待。

我在本篇文章中总结了整个弹力设计,提供了一张总图,并介绍了开发运维的实践。希望对你有帮助。

也欢迎你分享一下你对弹力设计和弹力设计系列文章的感想。

文末给出了《分布式系统设计模式》系列文章的目录,希望你能在这个列表里找到自己感兴趣的内容。

精选留言(15)
  • 👍(12) 💬(1)

    求耗子叔的更新版程序员练级攻略

    2018-03-27

  • 昵称 👍(3) 💬(1)

    请问管理设计个性能设计篇是还没有出吗?

    2018-03-29

  • 奋斗 👍(2) 💬(1)

    你好,弹力设计部分可以给一份推荐书单吗?水平有点低,有些内容理解的不是很透彻,具体怎么做这方面不太清楚!

    2018-04-09

  • Freezer 👍(1) 💬(1)

    程序员练级攻略?是耗子叔写的书吗?怎么没搜到

    2018-03-28

  • slark 👍(8) 💬(0)

    java生态确实好,但整体一套的cloud下来,性能不高。而其他语言又还没有java的这一大套完善的微服务框架。k8s在运维云开发上目前看是覆盖更广,价值更大的。即使没有用或者很难搭建一整套微服务组件,只要把服务结合k8s,在运维方面还是能有很大收获

    2020-02-05

  • jack 👍(6) 💬(0)

    陈老师,能否讲讲系统容量规划方面的内容?

    2018-03-27

  • 业余爱好者 👍(3) 💬(1)

    重试,降级,熔断是调用方的职责,限流一般放在服务提供方。不知道这样理解对否。

    2020-05-29

  • inrtyx 👍(2) 💬(0)

    感觉有k8s可以不用spring cloud.用k8s➕spring boot

    2022-01-09

  • 👍(2) 💬(1)

    不太明白,作为消息驱动微服务应用的框架spring stream和workflow有啥子关系?

    2018-05-30

  • Penn 👍(2) 💬(0)

    订阅了8个,这个专栏是最系统深刻的,开阔了眼界,感觉有些系列可以拎出来单独扩展,期待老师更多的分享

    2018-05-16

  • 徐卫 👍(2) 💬(0)

    这两天又将分布式弹力设计的所有文章重新看了一遍,每次看都有不同的收获,系统性的学习真的很重要,感谢皓子叔。这个专栏越来越值了。

    2018-04-05

  • Geek_130e9e 👍(1) 💬(0)

    从今天看下来,微服务的最佳实践在未来有可能会成为 SpringCloud 和 Kubernetes 的天下了。拭目以待。

    2020-04-27

  • 文刂 氵共 超 👍(1) 💬(0)

    坚持学习,学习笔记 https://mubu.com/colla/1JtPpwr-rLM

    2019-12-26

  • edisonhuang 👍(1) 💬(0)

    弹力设计分为三大板块,服务冗余,服务容错和服务解耦,冗余避免了单点故障的发生,容错涉及到重试机制,服务降级等,服务解耦则把原来单点的应用按不同纬度拆分开来,保证其中某些模块坏掉不会影响全局。分布式系统的服务被拆开,还需要自动化运维和调度做保障

    2019-07-13

  • BitbIt 👍(1) 💬(0)

    MySQL是不是也可以叫write back,随机写变顺序写(redolog),然后写cache,后台刷脏页

    2019-05-14