聊聊云原生和微服务架构

摘要:
之前写过两篇关于微服务架构的文章,发现阅读量挺高的,所以打算再聊聊云原生和微服务架构,过去的文章如下:扩展阅读:一文了解基于NetflixOSS的微服务架构什么是微服务?为什么要用云原生架构?这就是云原生架构想要解决的第一个问题:应用系统挂掉后,无需人工的介入,可以自动在最短的时间恢复来保证系统的健壮性。

文章配图-秘鲁彩虹山

之前写过两篇关于微服务架构的文章,发现阅读量挺高的,所以打算再聊聊云原生和微服务架构,过去的文章如下:

扩展阅读:

本篇分享主要围绕以下 4 个主题进行:

  • 什么是云原生 ?
  • 为什么要用云原生架构 ?
  • 微服务的概念
  • 微服务的技术选型

什么是云原生 ?

云计算和云原生

云计算不同于传统的自建机房,云计算就是将计算的抽象为基础设施然后通过网络分发,得益于云计算的无限扩展能力,使得“云计算”就像自来水厂一样,我们可以随时接水,并且不限量,按照自己家的用水量,付费给自来水厂就可以。以下云计算的五个基本特征。

云计算的五大特征

以下是一些目前比较主流的公有云厂商:

目前主流的公有云厂商

云原生顾名思义,就是基于云计算特性所设计的应用服务,得益于云计算快速发展,基于云计算特性所设计的云原生应用相比传统的单体应用在安全性,扩展性,快速迭代,运维等各方便都有巨大的领先优势。云原生并不是指某一种技术,它是一种架构设计理念,只要符合这种架构设计理念的应用,都可以称为 云原生应用, 看看 CNCF 官方对于云原生的定义:

Cloud Native

容器云技术的发展

虚拟化技术的发展历史

云原生是依赖容器作为技术技术来实现的,但是容器并不是什么新潮技术,以下是容器云技术的发展历史,其中有几个关键的历史节点

  • 早在 06 年的时候 Amazon 基于容器技术构建的 IaaS 平台 AWS,成为所有云计算厂商的鼻祖,由于技术领先的优势 AWS 现在依然也是云计算行业老大
  • 13 年 Docker 的诞生进一步简化容器技术的使用门槛,Docker 公司自以为掌握云时代的核心技术,开始野心勃勃的有意挑战传统的云计算大厂例如 RedHat,Google 的江湖地位,公司股价也是一骑绝尘,却不料被 RedHat 联合 Google 发布的 Kubernetes 击溃,Kubernetes 的成功让大家以为容器技术并非云时代的核心技术,容器编排 才是核心技术。(备注:2020 年 K8S 官方宣布只要满足 K8S CRI 接口的容器均可以被 K8S 进行编排,Docker 被时代抛弃)
  • 2015 年借助 Kubernetes 的成功,Google 宣布成立 CNCF 基金会,这是云原生时代的代表性的组织。致力于完善云时代的基础设施,帮助开发者构建更出色的产品

下图是 CNCF 的全景图:

CNCF landscape

为什么用云原生架构 ?

主要从 4 个方面来聊聊:

  • 自动恢复
  • 服务安全
  • 弹性扩展
  • 快速发布

自动恢复

早期刚参加工作的时候接手过一个年久失修的遗留系统,这个系统又一个很神奇的 Bug 每天晚上会自动宕机,谁也不知道什么原因。只要重启就能恢复正常,当时为了保证业务系统的正常使用,我总是在半夜爬起来重启服务器,我当时就在想:要是有一种工具可以检测到系统宕机后,就自动重启恢复就好了,这样我就可以睡一个好觉了

这就是云原生架构想要解决的第一个问题:应用系统挂掉后,无需人工的介入,可以自动在最短的时间恢复来保证系统的健壮性

当然除了未知的 BUG,还有诡异的异常会导致服务崩溃了,例如:

  • 代码没写好,系统发生 OOM
  • 服务器本身的资源不足
  • 死锁,磁盘,网络等问题
  • 等等……

Kubernetes Pod 应用自动恢复的三种策略:

spec: 
  restartPolicy: Always # 当容器终止退出后,总是重启容器,默认策略
  containers: 
  - image: nginx
    name: web 
  • Always:当容器终止退出后,总是重启容器,默认策略
  • OnFailure:当容器异常退出(退出状态码非 0)时,才重启容器
  • Never:当容器终止退出,从不重启容器

安全性

在微服务架构的大型分布式系统,服务和服务之间是通过熔断建立安全的保护隔离机制

云原生架构保障系统的安全性主要体现 2 个方面:

  • 服务隔离
  • 资源隔离

服务隔离

先来看看服务调用的安全隔离,如图:

微服务治理:熔断、降级和限流

假如服务 A 和服务 B 之间存在依赖的调用关系,它的处理逻辑如下:

  1. 如果服务 B 宕机或者异常下线,注册中心会发送服务 B 的状态给服务 A,服务 A 就会启动熔断保护机制
  2. 服务 A 采用降级策略或者不再发送向服务 B 发送请求,避免产生调用链雪崩,同时也保护服务 A 的可用性
  3. 服务 B 再次被拉起的时候,服务 A 收到注册中心对服务 B 的健康检查,恢复对服务 B 的调用或者移除降级策略

资源隔离

云原生架构对于服务的保护机制也体现在对资源的使用上,以前多套系统共享一台主机的资源,总是容易出现木桶的短板效应,就是只要有一个系统把主机资源占满,那么其他的系统都会因为资源不足受到影响。进而产生连锁反应,同主机上的所有系统都会崩溃。

资源隔离

现在基于容器部署的微服务系统,你的系统在生产环境的真实部署情况就像被关进一个个小房间里面,预先安排的资源设置就是这个服务房间的大小,它只能在指定的大小范围内活动,就算程序内部异常导致把资源全部占用,也不会影响其他房间的小伙伴的正常活动,从而保证整个系统的可用性

通过 Kubernetes 指定内存请求和限制的 Pod 配置文件:

spec:
  containers:
  - name: memory-demo-ctr
    image: polinux/stress
    resources:
      limits:
        memory: "200Mi"		# 内存会被限制在 200 MiB 以内
      requests:
        memory: "100Mi"		# 容器将会请求 100 MiB 内存

通过服务隔离,资源隔离的方式为云原生系统提供安全和可用性,这里仅仅做一个入门的介绍,如果展开来讲的话,内容还有很多,有兴趣的同学可以自行去研究和探索。

弹性扩展

传统的单体的应用,往往部署在机房的服务器主机内,那么自购的服务器难以应对业务快速增长,存在以下问题:

  • 时间成本:采购服务器需要事先填好配置清单,走各种流程,等物流,等机器送到接上电源,估计 1~2 周都过去了
  • 空间成本:要腾出很大的空间来放置这些大家伙
  • 其他成本:24 小时开空调,专人轮班值守,机器的维护,服务下线后服务器容易闲置,闲鱼不好出手等等。。

在基于云计算的基本特征所设计的云原生系统,则不存在以上这些问题,在主流的公有云厂商提供 ECS 主机基本可以任意扩展和伸缩配置,在资源使用上也提供 按量付费 的运行模式,有效避免对于计算资源的限制和浪费。如下:

ESS 弹性伸缩

快速发布

随着类似 Kubernetes 等云原生基础设置的完善,现代应用的部署方式也跟以前大不相同。相比传统低效的停机发布,云原生服务提供的 Rolling Update 滚动升级帮我们实现不停机升级系统的目标,对于需要快速响应市场需求的企业,快速迭代的业务系统的功能对于企业取得市场竞争力显得来说尤为重要。

KubernetesRollingUpdate 策略用于解决不停机发布的问题:

Deployment in Kubernetes

另外,我们可以通过kubectl rollout undo 将 deployment 回滚到指定的版本,来解决微服务的快速回滚的问题。

以上就是云原生架构相比传统系统所带来的巨大优势,我们目前也是处于云时代架构演进的早期。我个人认为,我们程序员作为知识工作者非常值得投入时间去学习下一代的主流架构设计。这将为我们带来巨大的技术优势和技术领先。

微服务的概念

微服务的理论基础

微服务并不特指某一种具体的技术,它是一个抽象的概念,只要满足它的所有规范,那么就可以理解为你的系统实现了微服务。

微服务的公共关注点

何时用微服务 ?

关于你的项目何时应该引入微服务架构,行业一直有两种声音:

  • 方案 A 单体优先:随着架构的演进逐渐替换为微服务架构
  • 方案 B 微服务优先:避免后期的大范围架构重构

其实,早在 2015 年技术大牛 Martin Fowler 在博客文章 MicroservicePremium 中就给出了具备参考性答案:

MicroservicePremuim

早期(2015 年左右)微服务使用成本和上手门槛很高,生产效率不如单体应用,但是伴随系统的业务复杂度逐渐上升,单体应用的生产效率逐渐降低,在到达临界点的时候微服务的优势逐渐出现,微服务的生产效率开始超过单体应用。

所以在 2015 年的时候结合成本和收益的权衡,大多数人会选择 单体优先 的架构方案,后续再逐步演化成为微服务。

Netflix OSS 的诞生

早在 2015 年的 CNCF 基金会刚诞生,社区的微服务基础设置非常不完善,Netflix + Pivotal 公司作为微服务的实践的探索者,通过应用层面提供许多微服务的基础组件来实现微服务架构。关于 Netflix 提供的微服务全家桶解决方案称作 Netflix OSS(Open Source Software Center)

关于组件的详细介绍,我在 一文了解基于 Netflix OSS 的微服务架构 中也有介绍,这里就不再赘述了。

Netflix OSS 全景图如下:

image-20211119145635363

微服务优先

Martin Fowler 在 2015 年提出的观点,显然已经不再适用 2021 的现代系统架构,这几年随着 CNCF 的快速发展,云原生的基础设施逐渐的完善和成熟,微服务的使用成本逐年降低,微服务的实现成本已经趋向于单体,甚至未来会优于单体,我的个人看法是,微服务如果能够解决使用和学习成本的问题,那么未来微服务也将完全取代单体应用。从长期主义来说,任何新项目都应该优先选择微服务架构,不仅可以保证业务系统的生产效率、扩展性,还可以避免未来产生大规模的重构。

微服务的技术选型

微服务框架选择

市面上微服务框架很多,目前行业的大公司基本都会有自己的微服务框架,我们只看几款主流并且具备代表性微服务框架:

  • Dubbo (阿里巴巴)
  • Spring Cloud (Netflix)
  • Kubernetes (Google)

我们通过功能对比,看看都是如何根据自己的理解实现微服务的基本理论概念

我们将主流框架从微服务的基础关注点,运维架构,产品背景进行三方面维度的比较:

基本功能对比部署和运维image-20211119164256958

通过横向对比,我们可以看到不论是 Dubbo 还是 Spring Cloud 对比 Kubernetes 都有诸多缺点。相比阿里巴巴的 Dubbo、Netflix 的 Spring Cloud, Google 提供的 Kubernetes 才是具备完整的一站式的微服务解决方案的技术方案。如图:

Kubenetes解决了什么问题?

如果使用住房来比喻的话,前者就像毛坯房,还要自己装修,Kubernetes 则是精装修的商品房,帮你解决所有问题,拎包入驻即可。另外,自建 Kubernetes 集群成本比较高,推荐使用公有云厂商提供的 Kubernetes 服务

微服务和网关

如果把分布式的微服务系统比喻成一家公司的话,那么网关就是该公司的前台,当有用户要访问公司必须在前台登记确认身份,疫情期间可能还需要量一下体温什么的。这一步骤就叫 网关鉴权,根据用户描述的任务和身上携带的证明,网关用户的业务类型将用户带到所属业务范围内办公室,这一步骤就叫做 网关路由。如果用户太多一个前台处理不过来,就会多开设几个窗口来分流,这一步骤就叫做 网关层面的负载均衡。网关是微服务的大门,对于微服务至关重要。

以下是网关常见的工作方式:

网关的工作方式

除了上述的鉴权,动态路由,负载均衡,通过网关还可以实现以下高级特性:

  • 网关限流(人太多,把门关起来,或者在门口排队)
  • 金丝雀发布(将小部分用户带到还未开放的新办公场地去体验一下)
  • 弹性伸缩

网关是微服务的大门,因为网关对于对微服务来说至关重要,是微服务弹性伸缩的能力来源。并且网关的开发成本其实并不高,所以市场面有很多单独的网关产品,我们可以简单看看,如图:

主流网关产品对比

微服务和安全认证

早期分布式单体应用的会话管理

早期的单体应用用户会话方案都是通过服务端存储 sessionid + cookid + filter 来保存和管理用户状态会话,但是这种有状态服务有很多弊端,例如服务重启用户状态丢失,难以横向扩展等等,后单体应用时代大家开始把用户会话状态放在类似 Redis 等存储中间件中,来解决系统的横向扩展和重启后会话不丢失的问题。

架构如图:

redis 存储会话

微服务中基于 Auth 的认证方案

在的微服务体系中,身份认证模块将被统一抽取出来交给单独的服务处理,该服务通常称为 Auth Service。访问令牌通常由 Auth 颁发,由网关统一鉴权,AuthService 身份认证职责的分离,可以让微服务本身更加关注业务。

基于 Auth Service 的工作逻辑如图:

网关访问 AuthService 鉴权

不过这种基于 Auth 认证服务的方案会将所有请求发往 Auth 进行验证,认证服务承受的压力大,架构方案重,造成不必要的性能损失。其实大部分的应用系统都不需要这么严格的安全认证等级。那么有没有一种轻量级的技术是可以由认证服务颁发令牌后,不在需要依赖 Auth 鉴权,由服务自行验证令牌的有效性,这样就可以大大减少对 Auth 的鉴权请求。答案是有的。它就是目前非常流行的 JWT 鉴权方案。

JWT 结合 RBAC 角色权限模型是目前非常主流的轻量级认证方案。它的工作流程如下:

RBAC+JWT

JWT 备受推崇,广泛使用的原因,是因为它在由 Auth 服务颁发令牌后,在网关即可验证令牌合法性,无需再请求认证服务,请求少,性能好。令牌本身还可以自包含少量的用户信息,JWT 大概是一串这样的编码,它由三个部分组成,你可以通过 JWT IO 这个网站对 JWT 进行解码,从而获取 JWT 中的信息:

image-20211120103303879

JWT 的详细生成和解码过程就这里不在赘述了,JWT 并非没有缺点,我们看看它的优缺点:

优点缺点
紧凑轻量一旦颁发无法吊销,只能自动过期
减轻 Auth 压力,简化 Auth 实现包含信息越多,传输开销越大

总结

RBAC 角色模型 + JWT 鉴权方案是目前微服务主流的安全认证体系,也能应对大多数系统对于安全认证的需求,也是目前市面上大部分的企业应用生产中的最佳实践

微服务的运维监控

生产就绪系统 Production Ready

说完了开发环节,最后来说说微服务是怎么运维的。我们知道仅仅只是 完成功能(Feature-Complete) 只是软件开发流程中很少的一部分,那么从完成编码到 生产就绪(Production Ready),还需要经历哪些环节 ?我们可以参考下图:

Production Ready
  • 集成测试:用户功能的准确性,性能和压力测试

  • 日志管理:日志要规范,要区分:Info,Wrong,Error 等不同的等级,日志格式统一,方便日志收集,监控和排查

  • 监控预警:包含业务指标监控,应用指标监控,CPU,内存,磁盘网络 IO 监控等等,设定合理的预警信息

  • 调用链监控:呈现分布式系统的调用关系,调用性能,找到性能瓶颈,快速定位问题

  • 高可用考量:双机备份,主从备份,异地多活,容灾策略,应用弹性机制等

当我们确保应用满足生产就绪(Production Ready)的要求,我们就可以发布到生产,交付价值了

基于 EFK 的日志采集方案

基于容器部署的微服务架构不可能像传统应用那样通过 SSH 登录服务器上扒日志信息,所以只能采取统一的收集机制。

Kubernetes 中推荐使用 EFK (Elasticsearch + Fluentd + Kibana)采集日志,它的工作流程如图:

EFK + K8S
  1. Fluentd 会将采集的日志直接发到 ElasticSearch,中间也可以增加 kafka 作为缓存层
  2. ElasticSearch 通过 Log Parser 初步解析日志,可以过滤垃圾日志
  3. 通过 Kibana Dashboard 查询 ElasticSearch 显示日志

分布式系统的服务监控方案

目前主流的微服务监控体系是通过 Kubernetes + Prometheus 来搭建,如图:

Kubernetes+Prometheus
  1. 通过 Prometheus 发现 Kubernetes 服务
  2. 通过 Alert Manager 监控和报警 Email,SMS
  3. 通过 Grafana 展现和监控服务的运行各项指标

基于 Skywalking 分布式链路跟踪监控

Skywalking 是无侵入分布式链路跟踪框架,可以在不添加一行代码的前提下完成对微服务分布式系统的链路跟踪,是目前主流的分布式链路跟踪的解决方案,2019 年 SkyWalking 成为 Apache 顶级项目,SkyWalking 的作者吴晟也因此当选为 Apache 软件基金会首位华人董事,这里就不展开讲了,SkyWalking 工作大致工作原理如下:

image-20211120160815978

SkyWalking 对分布式调用链的展示:

SkyWalking调用链展示

总结

本文从云原生的发展历史,讲述了我们程序员为什么要拥抱选择云原生。讲解了基于云计算的基础底座所衍生出来的云原生系统对传统单体应用所带来的颠覆性改变,然后讲述一些微服务的工作原理,架构布局和运维方案。但是在真正生产级云原生应用中,远远不止要要考虑以上的内容,还有更多需要考虑的因素,例如:

  • HTTPS
  • 编码规范,测试覆盖率,E2E 测试
  • 监控:Log/Trace/Metrics,业务指标监控
  • 持续集成:CI/CD 流水线
  • 完善的 README 帮助文档

更多细节就不展开讲了,期待跟大家共同学习和交流,谢谢大家。

参考文献:

免责声明:文章转载自《聊聊云原生和微服务架构》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇TP框架 mysql子查询Centos 7 安装mysql后出现 ERROR 2002 (HY000)解决方案下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

个人亲历运维面试

Docker 1. docker通过哪些方式实现资源隔离的 Docker 主要通过六大 Namespace 来实现资源的隔离 Mount Namespace,挂载命名空间,用来隔离挂载目录,让不同 Namespace 拥有独立的挂载结构,而程序中对挂载信息的修改不会影响到其他 Namespace 中程序的运行。 UTS Namespace,UTS Nam...

Docker最全教程——从理论到实战(六)

Docker最全教程——从理论到实战(六) 托管到腾讯云容器服务托管到腾讯云容器服务,我们的公众号“magiccodes”已经发布了相关的录屏教程,大家可以结合本篇教程一起查阅。   自建还是托管? 在开始之前,我们先来讨论一个问题——是自建容器服务还是托管到云容器服务? 这里笔者建议大家托管到云容器服务。对于中小团队来说,很多情况下,团队中的运维人员是缺...

Kubernetes增强型调度器Volcano算法分析

【摘要】 Volcano 是基于 Kubernetes 的批处理系统,源自于华为云开源出来的。Volcano 方便 AI、大数据、基因、渲染等诸多行业通用计算框架接入,提供高性能任务调度引擎,高性能异构芯片管理,高性能任务运行管理等能力。 1      为什么K8S需要Volcano     K8S自带的的资源调度器,有一个明显的特点是:依次调度每个容器...

X86架构与ARM架构比较(摘录自网络)

引言  CPU是怎样运作的?   CPU的运作与人脑的运作差不多。先谈一下人这个系统的工作方式。眼镜、耳朵、舌头、皮肤等等感觉器官接收到“触觉”,把信息传给大脑,大脑把信息处理后,把处理结果送给手、脚、嘴等执行器官就可以运动了。   人脑的功能就是从某个感觉器官读取信息,处理信息,然后再把结果送给执行器官。   一个完整的系统与人这个系统差不多,传感器接收...

Docker快速指南

Docker使用Go语言开发,基于Linux内核的cgroup、namespace以及AUFS等技术对进程进行封装隔离,是一种操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。 Docker则使用宿主机内核提供的隔离机制创建沙盒环境,容器内的应用进程直接运行于宿主的内核。 因为容器内没有虚拟硬件和内核,容器在启动时间、...

在vue项目中 获取容器的高度

左右并列两个容器,左边的不固定高度,右侧的高度要和左边的高度一致, var offsetHeight = $('.left).outerHeight(); $('.right').outerHeight(offsetHeight); 因为获取的容器是动态的,内容的多少会导致高度变化,在created时,始终获取到的是默认的高度,当内容增加时,高度还没变,...