[云原生微服务架构](十)微服务架构的基础知识

今天我要和你分享的内容是微服务架构的基础知识。

单体服务架构有哪些问题
单体服务,相信大家都有所了解,在我们最初接触 Web 开发,写一些网站或者 App 的时候,大多使用的是单体服务这种后端技术架构。比如在 Web 2.0 时期,最常见的博客系统 WordPress,就是一个著名的单体服务。因为它所有的功能模块都在一个代码仓库,并且部署在同一个进程内,是一个典型的单体架构。

事实上,在不需要快速迭代的业务上,单体服务也可以运行得很好,比如一个小的团队维护一个变更速度没那么快的项目,就像 WordPress 和早期的门户网站。但面对如今移动互联网业务的快速迭代,单体服务就显得力不从心了,一个很大的问题就是,大量复杂的业务冗杂在一个单体应用中,造成了人员沟通成本和发布迭代成本的急剧上升。

为了让你更好地理解从单体服务转向微服务的原因,下面我来具体说说单体服务的问题。

  1. 人员协作问题
    所有人员都在一个代码仓库开发,当数量超过 10 人时,协作问题就开始凸显了。比如一个新成员,需要在一个庞大的代码仓库中,找到自己负责的模块部分,假如他在改动自己负责的部分的时候,代码组织并不是很好,就很容易涉及其他人写的代码,这个时候就产生了不必要的沟通成本。即便沟通顺利,也容易引起单体应用中其他部分的故障。

  2. 部署问题
    除了协作中的问题,还会产生上线部署效率的问题。当不同人员开发的不同模块,同时需要上线时,如果分别将分支代码合并到主干代码,再按照流程上线,就会产生先后顺序的等待时间;如果合并到一起上线,线上功能一旦出问题,就需要花费大量时间排查是哪个模块出现的问题。

  3. 架构演进问题
    当我们应用中的某个模块,遇到了性能瓶颈,我们希望以另外一种语言重新编写此模块,这个时候单体应用完全无法演进。如果我们要替换语言,就得重写整个应用,花费的成本可想而知。

  4. 程序稳定性问题
    在单体应用中,某个模块出现 Bug 时,比如因为疏忽造成了 OOM (程序内存不足),导致程序 panic,这会导致整个网站或者 App 不可用。一个模块的问题,导致了整个应用挂掉,这在生产环境中是无法接受的。

随着互联网业务的发展,整体业务越来越复杂,以上问题越来越明显,单体服务已经无法应对如此复杂的业务场景了。互联网行业也从架构上逐步开始了服务拆分,进入了 SOA (Service-Oriented Architecture 面向服务的架构)时代。

在 SOA 时代,比如淘宝网,采用了一种 ESB 总线的技术,就是所有服务的通信需要通过一个集中式的总线服务(可以理解为集中式网关),这大大降低了服务的通信效率并且增加了单点风险。但是随着业务进一步扩大, ESB 总线的弊端逐步凸显,比如每次服务变更节点都需要人工操作,这大大降低了互联网业务的迭代效率。

微服务和 SOA 一脉相承,而微服务则不再强调传统 SOA 架构里面比较重的 ESB 企业服务总线。

微服务有哪些优势
微服务是一种开发软件的架构和组织方法,其中软件由通过明确定义的 API 进行通信的小型独立服务组成,这些服务由各个小型独立团队负责。微服务架构使应用程序更易于扩展、更快开发,从而加速创新并缩短新功能的上市时间。与单体应用相比,微服务能够更好地满足互联网时代业务快速变化的需要。

接下来我们看一看微服务相对于单体服务都有哪些优势。

  1. 敏捷开发
    一个小的团队,甚至一个人,负责一个或者多个服务,当有新的需求出现,可以快速对这个小型服务做出修改并上线。但是当维护一个庞大的代码仓库构成的单体服务时,即使是一个简单的需求、只修改了一行代码,开发人员也会因为这行代码可能会影响整个应用,而降低部署的频率,从而累计多次代码提交再产生一次新的部署。

而我们知道两个版本的代码变动越多,产生问题的可能性就越大,甚至造成更严重的线上问题。相比之下,微服务可以让服务更敏捷地开发上线,这符合现在互联网业务快速迭代的特征。

  1. 技术自由
    微服务团队,可以选择自己喜欢的技术或者语言,并不需要局限在同一种语言上。当出现了一种新的语言更适合解决现在的问题,团队可以快速做出反应,用新的语言编写新的服务或者改写旧的服务,不必考虑采用新语言带来的不确定性和成本问题。

  2. 弹性扩缩容
    微服务可以灵活地应对服务的扩缩容问题。在单体服务中,假设某个接口在高峰期有较大的访问量,需要比平时增加一些机器应对,但我们很难根据 CPU 的水位做出准确的判断,因为所有接口都在一个应用中,而在微服务中做出这种判断要容易得多。

  3. 组织匹配
    在技术架构中,这是一个非常重要的概念。任何架构都应该和组织架构相匹配,在康威定律中已经明确地说明了这一点:如果技术架构和组织架构不匹配,会造成严重的跨部门沟通效率问题。随着业务的不断扩大,组织结构肯定会变得更复杂,而单体服务几乎无法配合这种变化。

微服务架构可以非常好地与组织架构相匹配,比如一个短视频业务,在业务发展到一定阶段,很自然地会拆分出用户增长部门和内容部门。而我们的微服务架构,也可以将不同的服务拆分到相应的部门中,降低维护和沟通的成本。

没有银弹
与其他现存的架构和解决方案一样,微服务架构也不是银弹。当然它解决了单体服务很多问题,但同时也带来了单体服务中一些没有的问题,比如负载均衡、服务治理、服务注册发现、如何拆分服务等,当然其中的大部分问题,都可以通过技术手段解决,但也增加了系统的复杂性。

下面,我们来进一步了解一下 Service Mesh 架构的演进。

Service Mesh,中文名叫作服务网格,简单来说就是将可以配置的代理层和服务部署在一起,作为微服务基础设施层接管服务间的流量,并提供通用的服务注册发现、负载均衡、身份验证、精准路由、服务鉴权等基础功能。

Service Mesh 的演进历程
sidecar 时代
实际上早在2013年,作为微服务架构的大规模应用方 Netflix, 就发现了微服务架构在跨语言上的问题。Netflix 大量使用 Java 技术栈,但因为公司的业务发展,使用单一技术栈是不现实的。语言总是有特定的应用场景,这个时候 Netflix 发现开发多语言的 SDK 要耗费大量的人力,毕竟 Spring Cloud 里的组件可不是一般的多,为每个语言开发一套,显然得不偿失,所以就想到了 sidecar 模式,把 SDK 里的功能转移到 sidecar 中。

所谓 sidecar, 其实就是一个部署在本地的代理服务器,它既接管了入口流量,也接管了出口流量。其实这种模式要追溯到 Web Server 的时代,比如 Nginx + Php-fpm 这种模式,实际上 Nginx 也是充当了 sidecar 的角色,只是通信协议由比较常见的 HTTP ,变成了 FastCGI ,另外 Nginx 只是代理了入口流量,并未代理出口流量。

初代 Service Mesh
在 sidecar 模式中,就像 Netflix 的初衷一样,它更多的是为了解决公司非主力语言的 SDK 开发问题,非主力语言通过 sidecar 连接,而主力语言还是通过 SDK 的方式。

技术不断发展,人们慢慢意识到统一流量处理模型的重要性,于是诞生了第一代 Service Mesh,其中比较出名的是 Linkerd 和 Envoy。在这一代 Service Mesh 中,已经不再依赖特定的基础设施,最重要的是它的出发点已经不是解决多语言的问题,而是从统一流量处理模型的角度,形成了一套统一的流量控制的解决方案。

但是初代 Service Mesh 有一个致命的问题(其实也一直存在于微服务架构中),就是缺乏统一的管控手段,比如 sidecar 的服务治理相关配置文件的维护,可能需要运维手动维护、无法集中管理,因为这个原因,控制面诞生了。

新一代 Service Mesh
新一代 Service Mesh,就是大家熟知的 Istio 了。它引入了控制面的概念,让 Service Mesh 成为完全体。

Istio 使用 Envoy 作为数据面,控制面和 Kubernetes 深度绑定,早期版本将流量治理的功能放在 mixer 中,形成了一套完整的 Service Mesh 解决方案。控制面负责了资源管理、配置下发、证书管理等功能,解决了数据面配置难以管理的问题。

讲完了 Service Mesh 的发展史,现在你应该对 Service Mesh 的有了初步的了解。下面我们就来看一下 Service Mesh 到底解决了传统微服务架构中的哪些痛点吧。

Service Mesh 的优势
1.语言无关
提到 Service Mesh 的优点,或许你最容易想到的就是业务语言无关性了,实际上我们在微服务架构也经常提到这个优点。但是对于传统的微服务架构,Service Mesh 做到了真正的语言无关:传统的微服务架构要为各种语言开发 SDK ,而 Service Mesh 将 SDK 的功能集成到 sidecar 中,实现了真正的语言无关性。

2.基础设施独立演进
传统微服务架构中,业务代码和框架/SDK 混合在一起,框架想要升级就会变得非常困难而且被动,当微服务的数量变多时,想要在公司内推动框架的全量升级可谓是“天方夜谭”。而Service Mesh 架构将框架中和业务无关的通用功能放在 sidecar 中,升级时只要升级 sidecar 就可以了,这样做到了基础设施的独立演进。

实际上这种做法也带来了另外一个好处:写框架的时候不用再考虑太多的向后兼容性,降低了编写代码的心智负担。

3.可观测性
可观测性一般包含两个部分:监控报警和链路追踪。

监控报警可以通过数据面的 Metrics 集成,无感知地做到系统监控报警,减少了业务和框架的重复工作。

至于链路追踪,因为需要通过 header 将 traceid 传递下去,所以还是需要客户端的 SDK 将 traceid 通过 header 传递。不过这个做法也简化了 Trace SDK 的封装。

4.边缘网关统一
实际上 sidecar 本身就是一个网关/反向代理,自然可以将以前 Nginx/Kong 之类的系统网关迁移到 sidecar 上来,这样就可以维护一套统一的代码。

更进一步,可以将以前边缘网关的工作,比如鉴权、 trace 初始化等工作下沉到 sidecar 上,进一步简化系统网关的功能。

Service Mesh 的基础组件及常见名词
Service Mesh 一个最重要的变革,就是引入了数据面和控制面的概念,这个概念也并非 Service Mesh 新创的概念,实际上在 SDN (软件定义网络)中就有了控制面和数据面的概念。在课程正式开始前,我们先简单了解一下控制面和数据面。

数据面(Data Plane)

负责数据的转发,一般我们常见的通用网关、Web Server,比如 Nginx、Traefik 都可以认为是数据面的一种。在 Service Mesh 的开源世界中,Envoy 可以说是最知名的数据面了。

另外数据面并非局限于网关类产品,实际上某些 RPC 框架也可以充当数据面,比如 gRPC 就已经支持完整的 xDS(数据面和控制面的交互协议),也可以当作数据面使用。一般我们把负责数据转发的数据面称为 sidecar(边车)。

控制面(Control Plane)

通过 xDS 协议对数据面进行配置下发,以控制数据面的行为,比如路由转发、负载均衡、服务治理等配置下发。控制面的出现解决了无论是框架还是数据面、sidecar 都缺乏控制能力的弊端,而且之前只能通过运维批量修改 CONF 来控制数据面、导致规模上升时纯人工维护成本以及大幅度上升的错误概率等问题也得到了很好的解决。

实际上 Service Mesh 需要的基础组件和传统的微服务没有太大的差别,很多公司选择自研控制面就是为了兼容老版本微服务的基础组件。

下面我们一起看一下 Service Mesh 的基础组件。

服务注册中心:服务间通信的基础组件。服务通过注册自身节点,让调用方服务发现被调方服务节点,以达到服务间点对点通信的目的。

配置中心:用于服务的基础配置更新,以达到代码和配置分离的目的。减少服务的发布次数,配置发布可以更快更及时地变更服务。

API 网关:通过统一的网关层,收敛服务的统一鉴权层、链路 ID 生成等基础服务,并聚合后端服务为客户端提供 RESTful 接口。另外 API 网关也负责南北向流量(外网入口流量)的流量治理。

服务治理:通过限流、熔断等基础组件,杜绝微服务架构出现雪崩的隐患。

链路追踪:通过 trace 将整个微服务链路清晰地绘制出来,并进行精准的故障排查,极大地降低了故障排查的难度。

监控告警:通过 Prometheus 和 Grafana 这样的基础组件,绘制服务状态监控大盘,针对资源、服务、业务各项指标,做精准的监控报警。

说完了基础组件,再说一下一些常见的名词解释,便于你理解 Service Mesh。

Upstream: 上游服务,如果 A 服务调用 B 服务,在 A 服务的视角来看,B 服务就是上游服务,但是在中文的语境中,经常被叫作“下游服务”。所以在整个课程中,为了避免语言上的歧义,我会直接使用upstream,而不是中文翻译。在中文的语境中,我更喜欢称它为服务端或者被调用方。

Downstream: 下游服务,如果 A 服务调用 B 服务,在 B 服务的视角中,A 服务就是下游服务。在中文的语境中,我更喜欢叫客户端或者调用方。

Endpoint:指的是服务节点,比如 A 服务有 192.168.2.11 和 192.168.2.12 两个服务节点。

Cluster:指的是服务集群,比如 A 服务有 192.168.2.11 和 92.168.2.12 两个服务节点,那么A服务就是 Cluster,也可以直接理解为 Service。

Node:在 Kubernetes 语境中,指的是承载 pod 的服务器,但在微服务的语境中,更多的等同于Endpoint。

Route:指的是 Service Mesh 中的路由配置,比如 A 服务访问 B 服务,要匹配到一定的规则,比如 header 中要带有服务名(-H servicename:B),才能够拿到 B 服务的访问方式,通过服务发现或者静态列表访问到 B 服务的节点。

Listener:指的是 Service Mesh 的监听端口,通常我们访问 Service Mesh 的数据面,需要知道数据面的监听端口。

本作品采用《CC 协议》,转载必须注明作者和本文链接
你还差得远呐!
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!