单体-微服务-Istio,不断演进的架构史(架构篇)
Posted Coding And Thinking
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单体-微服务-Istio,不断演进的架构史(架构篇)相关的知识,希望对你有一定的参考价值。
早期开发单体应用的时候,所有的业务功能都集中到一个应用中,随着功能越来越多,规模越来越大,许多问题都凸显了出来。比如:
代码难以开发、维护。因为不论你负责的是哪一块功能,都要面对这个庞大和复杂系统的所有代码。这牵一发而动全身的局面,使得本来简单的功能迭代、小的改动都会让人头疼不已。
扩展难度较大。系统规模不断庞大,数据量不断增多,此时光是运行项目本身,服务器的资源就已经不够支撑,在单体架构下,这种情况只能进行垂直扩展(内存不够加内存,CPU不行升级CPU),无法水平扩展(即通过将系统不同的功能,分散部署到多台低配的服务器上来满足需要)。由于技术瓶颈的牵制,垂直扩展终有极限,后期需要花费高昂的成本才能换来一点点的提升,所以水平扩展才是王道。 在面对单应用负载过高的问题上,单体架构虽然可以通过水平扩展来进行负载分压,但做不到按需水平扩展,比如,整个系统只是订单模块调用最多最频繁,需要做水平扩展。但单体架构只能将整个项目部署多份,浪费了系统资源。
异构性差。单体架构的应用,都是使用同一套技术栈去开发的每一个功能模块,随着技术不断的出新、发展,某一类功能可能需要替换另一套技术栈,比如之前用java开发的项目,其中爬虫的功能模块需要替换为python来实现,这种情况在单体架构中就显得非常棘手,因为你目前使用的框架、依赖、编译以及运行环境都是针对java的,而你要变更技术栈的模块,又和这些是耦合在一起的。
为了解决上面说的种种问题,单体架构一步步演变到我们今天所熟知的微服务架构。
由上图可以看出,单体架构下,虽然开发团队针对功能模块划分出了不同的开发小组,但是每个开发小组依旧要面对整个应用的代码。而微服务架构下,做到了每个小组只需面对自己服务的代码,并且服务的技术栈可以互不相同,只要留出供外部调用的接口即可。抽取出来的公共服务(比如:支付服务),再应对其他业务场景时可以复用,单体架构下则需要再次的冗余编码。
可见,微服务架构确实解决了很多问题,但天下没有免费的午餐,从图中服务间的交互连接虚线就可以看出,由它引入的一个比较明显的问题,就是服务之间的网络通信该如何管理维护。
2. 服务间的流量管控:如何根据每个服务自身的情况做负载均衡,服务超时、服务熔断该如何处理,故障切换要怎样实现等。
3. 安全:服务间通信的认证授权要如何保证。
4. 可见性:在海量服务的通信网络上,如何做好链路追踪,日志的收集,服务的监控等。
5.对数据一致性的影响:以前单体应用连接一个数据库,通过本地事务就就能处理,现在需要面对分布式事务。并且实现分布式事务的时候,网络交互上出问题,往往是最不好处理的。
当然,虽然微服务架构引入了不少麻烦,但在面对海量用户,且系统功能庞大的场景下,它仍然是发展趋势。所以为了解决上述问题,并且更方便的落地,出现了很多微服务的框架:Spring Cloud、Grpc、Dubbo、Thrift等等。
上图就是市面上大多数微服务框架的体系结构,它们很好得解决了微服务的痛点问题,并且屏蔽了通信上的许多底层细节,使得开发人员花费很少的精力就可以搭建一套健壮的分布式系统。
可是这一套套看似完美的框架解决方案,很快就被开发人员在使用过程中发现了问题。
虽然搭建使用这套框架服务很简单,但仍然要花费大量精力去掌握和管理框架本身,因为解决框架出现的问题并不容易
这些框架往往只支持一种或几种特定的语言,但在微服务的定义中,一个重要的特性就是语言无关性。而那些用没有被支持的语言编写的服务,想要融入这套框架体系会非常困难
框架是以依赖库的形式供服务使用的,在项目依赖复杂的情况下,依赖库的版本兼容问题是个大问题,而且框架依赖库的升级无法对服务透明,业务服务很可能会因为与业务无关的依赖需要升级,而被迫升级。
话分两头,在软件架构发展的同时,基础设施领域也有着突飞猛进的发展,先是有了容器的概念,接着又是如雨后春笋般出现的容器编排工具,最终,我们最为熟悉的两款明星产品杀出重围---Docker与Kubernetes,服务容器化就这样进入了大大小小的软件企业。
从早期的以物理机为单位做隔离,到以虚拟机为单位,再到以容器为单位的发展,使我们可以越来越方便地对服务进行管理、迁移,以及系统资源的充分利用。走在前沿的大神们,为了更方便的管理容器,又推出了各种容器编排工具。
上图为Kubernetes管理下,集群内部服务的通讯图(其中省略掉了master节点以及与master节点相关的组件),Kubernetes最小的调度单位是Pod,而pod可以看作是一个容器组,容器里面运行的便是我们的服务。由图可以看出,Kubernetes主要通过kube-proxy来解决服务之间的通信问题。
kube-proxy:可以完成服务发现,以及负载均衡的功能。
ingress:可以理解为网关,用来接收外部请求的。
这些组件虽然满足基础的通信需求,但面对一些复杂的流量管控场景,就显得格外简陋了。不过不用着急,随着Service Mesh概念的诞生,一款网络基础设施层的新起之秀---Istio,脱颖而出。Istio虽然不是第一款Service Mesh产品,但在Google和IBM两大巨头的光环加持下,,最终成为了目前影响力最大的服务网格技术。
我们在Istio官网可以看到对其的描述:
它作为透明的一层接入到现有的分布式应用里。
2.解决了开发人员和运维人员所面临的从单体应用向分布式微服务架构转变的挑战。
3.它的功能包括服务发现、负载均衡、故障恢复、度量和监控等。还可以满足复杂的运维需求,比如 A/B测试、金丝雀发布、速率限制、访问控制和端到端认证。
从官网给的演示应用Bookinfo还可以看出,服务与Istio并无依赖,不会约束微服务的语言无关性。
上图为Bookinfo应用的端到端架构图,展示了它是一个包含多语言微服务的应用。每种语言的微服务都能很好的融入这套体系。
看到这里,你可能已经发现,Istio不正好可以解决上面那些微服务框架的痛点。没错,被你发现了,而且是从基础设施层解决的,而不是框架层面。(有时候可能换一个维度去解决问题,一切都会变得不一样)。
Istio可以说是Kubernetes很好的合作伙伴。Kubernetes 主要负责资源的调度和编排,Istio负责网络通信。Istio通过在服务旁边附着一个Envoy网络代理的方式,来实现对服务透明化的网络通信管理。这个Envoy代理在Service Mesh概念里被称作SideCar(边车),非常形象。如下图所示
在不改变右侧摩托车自身构造和属性的情况下,安装一个边车在它旁边,
将其变为一辆三轮摩托来增强功能。
注入了Istio的Kubernetes集群,如下图所示
Envoy网络代理在Pod中以容器化的方式,附着在容器化的服务旁边,为其提供完善的网络通信功能。
下面是一个由Istio支撑的,海量微服务应用的网络拓扑全局图
Istio在架构上分为数据平面和控制平面两块。
数据平面:由一组智能代理(Envoy)组成,被部署为sidecar。这些代理通过一个通用的策略和遥测中心(Mixer)传递和控制微服务之间的所有网络通信。
控制平面:管理并配置代理来进行流量路由。此外控制平面配置Mixer来策略和收集遥测数据。
架构图如下
Istio的核心组件:
Envoy:唯一一个与数据平面交流量交互的组件。被部署为服务的sidecar,为服务提供许多重要特性,比如:
动态服务发现
负载均衡
TLS 终端
HTTP/2 与 gRPC 代理
熔断器
健康检查
基于百分比流量分割的分阶段发布
故障注入
丰富的指标
Mixer:是一个平台无关的组件。在整个服务网格中负责执行访问控制和策略,并从Envoy代理和其他服务收集遥测数据。
Pliot:为Envoy提供服务发现、智能路由的流量管理功能(比如,A/B测试、金丝雀发布等)以及弹性功能(超时、重试、熔断器等)
Citadel:通过内置的身份和证书管理,可以支持强大的服务到服务以及最终用户的身份验证
Galley:对Istio配置进行验证、提取、分发的组件。负责将其余的Istio组件从底层平台(如:kubernetes)获取用户配置的细节隔离开来
Istio的核心特性:流量管理、安全、策略、可观察性
大家可以通过官网提供的BookInfo演示应用实例,亲自感受一下Istio的这些强大特性。https://istio.io/docs/examples/bookinfo/。
结语
在业务不断的驱动下,技术演进的长河越流越长越流越久,英雄辈出。Spring 今年已经17岁了 ,docker 7岁,Kubernetes 5岁,Istio 3岁。当它们老去的那天,又有哪些英雄会出现呢,让我们拭目以待。
长按二维码
以上是关于单体-微服务-Istio,不断演进的架构史(架构篇)的主要内容,如果未能解决你的问题,请参考以下文章
微服务架构学习与思考(12):从单体架构到微服务架构的演进历程