有不少朋友或同事都问过我这个问题:为什么我们要搞微服务架构,一个项目把代码从头撸到尾不是很方便吗,开发更快速,部署也容易。而且一提起微服务,涉及的技术就一大堆,好像几辈子也学不完。
怎么解答这个问题呢?我想还是通过架构的发展变迁史来说起,为什么会出现现在的各种架构。只有从整体上了解了架构的脉络,我们才好更加全方位的评估一个架构。为此,我们有理由来梳理一下架构发展的来龙去脉,究竟为何会出现微服务,主要解决什么问题。微服务架构是最先进的架构吗?
本文我们来探索一下架构的变迁。以及从Java工程师的角度来看技术的发展,了解我们在讨论微服务的时候,都会涉及哪些技术。微服务的下一步将如何发展。阅读完本文,你将了解到:
首先我们还是回顾一下架构的整体发展史。
架构也是随着其缺陷不断演变而来的,下面是粗略的架构演变史:
上世纪70年代和80年代,大型机是计算机的工作方式。
问题所在
:最初的大型计算机使用打孔卡,并且大多数计算都在批处理过程中进行。没有在线处理,并且延迟为100%,因为没有实时处理。
架构演变
:随着在线处理和用户界面终端的推出,大型机范式发生了一些变化。
客户端/服务器体系结构将大多数逻辑放在服务器端,并将某些处理放在客户端上。
问题所在
:在该体系结构的最初几年中,开发社区仍在使用与大型机开发相同的过程,采用单层原则来为客户端/服务器编写软件,从而产生了诸如意大利面条代码
和Blob
之类的反模式。
架构演变
:引入了一项称为面向对象程序设计(OOP
)的重大改进;
客户/服务器模型基于三层体系结构
,包括展示层,业务逻辑层和数据层。但是大多数应用程序是使用两层模型编写的,胖客户端
将所有展示、业务和数据访问逻辑封装在一起,直接访问数据库。尽管业界已经开始讨论将展示与业务与数据访问分开的必要性,但是这种做法直到基于Internet的应用程序问世才真正变得至关重要。
在90年代中期,互联网革命发生了,Web浏览器成为客户端软件,而Web和应用程序服务器托管所有处理和逻辑。
问题所在
:开发人员仍在将软件设计为紧密耦合的设计,从而导致混乱和其他反模式。
架构演变
:作为解决办法,业界提出了三层体系结构和实践,例如领域驱动设计
(DDD),企业集成模式
(EIP),SOA
和松耦合
技术。
21世纪前10年见证了云计算作为服务托管形式的重大改变。应用程序需要的一些能力,云计算平台托管了基础功能:分布式计算、网络、存储以及计算等,与传统的基础架构相比,云托管的方式能更好的控制成本。
问题所在
:它诱使将尚未设计用于弹性分布式架构的遗留应用程序直接迁移和迁移到云中,从而产生了单体地狱这种反模式。
迁移到云还给行业带来了管理第三方库和技术上的应用程序依赖项的挑战。没有足够的标准来选择第三方工具,我们开始看到一些依赖地狱。另外服务扩容也是一个问题。
架构演变
:了应对这些挑战,业界提出了新的架构模式,例如微服务
和12要素应用程序
[1],弹性服务
。
诸如DDD
和EIP
之类的软件设计自2003年左右就已经开始实践起来了,此时一些团队将应用程序开发为模块化服务,但是传统的基础结构(如Java应用程序的重量级J2EE应用程序服务器和.NET应用程序的IIS)对模块化部署并没有帮助。
随着云托管的出现,尤其是诸如Heroku和Cloud Foundry之类的PaaS产品的出现,开发人员社区拥有了真正的模块化部署和可扩展业务应用所需的一切。这引起了微服务的发展。微服务为打造细粒度、可重用的功能和非功能服务提供了可能性。
问题所在
:原本的单体系统、未被设计为微服务的传统应用程序开始被蚕食,试图迫使它们进入微服务体系结构,由于拆解的不当,从而导致了被称为微单体的反模式。单体和微服务是两种不同的模式,后者并不总是可以替代前者。如果我们不小心的话,最终可能会创建紧密耦合,混杂的微服务。微服务剧增的另一个不希望出现的副作用是所谓的“死亡星球”的反模式。
架构演变
:诸如服务网格,边车,服务编排和容器之类的新兴架构模式可以有效地防御基于云的世界中的渎职行为。随着云平台的出现,特别是像Kubernetes这样的容器编排技术,服务网格已经引起了人们的关注。服务网格是应用程序服务之间的桥梁,可添加其他功能,例如流量控制,服务发现,负载平衡,弹性,可观察性,安全性等。
几种架构反模式[2]说明
单体地狱
[3]:
微单体
[4]:
积木塔
:单体应用程序类似于积木塔:您永远不知道发生故障时哪块砖可能会出问题。由于该应用程序的所有模块都在同一进程中运行,因此,如果某个模块受到错误的影响,则会降低整个过程,从而影响整个应用程序。 在完成故障排除之前,您可能会失去数百甚至数千个商机;科学怪人
[5]:科学怪人是一部著名的美国电影,讲述了一个天才科学家创造了一个怪物最终被其毁灭的故事。Istio 团队为以它来自嘲。Istio 本想扮演上帝一般的角色(统一 Service Mesh 江湖,成为微服务架构的事实标准),却因为过度设计与现实脱离,成为了一个怪兽(monster)。因此,重构的第一阶段,就是从肢解怪兽开始,把微服务架构重新改回了单体架构,但是内部模块划分还是很清晰的;方轮
:重新发明方的轮子,已经有了一个很好的方案,又搞一个方案来替代它;死亡星球
[6]:
意大利面条式的设计
:面条之间互相缠绕在一起,很难梳理清楚它们之间的关系。意大利面式的设计很形象的说明了软件开发中的这种现象:系统很难维护,各种功能逻辑缠绕在一起,没有清晰的模块和层次关系;The Blob
:表示的是一个类型具有了过多的职能,导致其过于庞大,最后使代码难以维护。架构演变步骤
一般的,每一个架构的出现,不是一蹴而就的,都会经历以下几个过程:
下面我们将于Java工程师
的角度来观察架构的大致发展史。
早期,大部分IT系统都是单体系统,例如传统的SSH架构,此时前后端也没有分离,UI组件也包含在了控制层:
这一时期服务的对象主要是传统企业,并发不高,主要是业务开发,这种开发方式很方便。当年刚毕业的时候我还和同学在纳闷,那些互联网公司是不是也用SSH框架。
其实真实情况呢?随着互联网企业的崛起,DAU持续增长,业务并发量也逐渐增高,SSH架构单JVM部署这种简单的方式并不能满足高并发场景,我们需要一种能够支持给系统进行水平扩展的架构。
为了方便给系统扩容,以及增加系统的复用性,出现分布式系统。
另一方面,系统模块快速膨胀,为了降低系统内部的复杂度,于是对系统模块进行拆解,分不到不同的系统中,降低模块耦合,加快迭代速度。
业界提出了三层体系结构和实践,例如域驱动设计(DDD),企业集成模式(EIP),SOA和松耦合技术。
早期的分布式系统是基于面向服务的架构SOA。SOA是微服务的前身,主要是为了摆脱单体应用的问题,达到以下效果:
根据一位印度小哥的介绍,我画了下面这张SOA的架构图:
也就是说,异构系统,也可以通过消息中间件的协议转换进行相互调用。一般这个消息中间件通常是用ESB企业总线实现的。ESB 是传统中间件技术与XML、Web服务等技术相互结合的产物,消除了不同应用之间的技术差异,让不同的应用服务器协调运作,实现了不同服务之间的通信与整合。不同公司提供了不同的ESB中间件实现。
但是其表现并不佳,主要是其太重了,主要体现在:
后来逐渐演变为了现在的MSA(Micro-Service Archeticture 微服务架构),从而实现了更加松耦合以及更加灵活的系统。
微服务
使用各个子服务控制模块
的思想代替SOA中的总线。服务控制模块通常至少包含:服务注册与发布、路由、代理。
微服务与SOA的对比
水平扩展
;微服务遵循单一职责,是一种克服系统复杂性的分解技术。如果你觉得你的某个微服务很复杂,那么考虑看看是否拆分的不够细?也正是因为这种拆分,本质上增强了安全性和故障隔离;SOA | 微服务 | |
---|---|---|
服务粒度 | 粒度较粗 | 细粒度拆分 |
部署难度 | 需要重新创建或者部署整个应用 | 每个微服务可以独立构建部署 |
通信开销 | 大部分业务模块在一个应用里面,通信开销低 | 更多的远程调用,增加了通信开销 |
存储 | 一般所有服务共享数据存储 | 每个可以拥有单独的存储 |
业务易上手 | 需要了解整个应用的业务,上手较难 | 单服务上手容易,但是服务集群理解比较难(复杂度守恒定律:业务复杂度不会因为迁移到了微服务而降低) |
通信方式 | SOA体系结构依赖于消息传递(AMQP,MSMQ)和SOAP作为主要的远程访问协议,协议偏重量级; | 使用轻量级协议,如HTTP/REST |
可扩展性 | 难以扩展 | 使用容器技术很方便扩展 |
正是因为微服务的拆解,让我们增加了系统的安全性和故障隔离,可以让我们针对不同的服务,实施不同的扩容和存储技术。
例如,一些微服务可能使用关系数据库,而另一些可能使用NoSQL数据库甚至挂载的文件系统。以这种方式构建应用程序增加了团队构建应用程序的可伸缩性。
在SOA系统,或者是传统的单体系统中,使用一个项目的时候,通常会有一个大团队的人在同一个项目的同一个分支上工作,并且总是互相干扰,出现各种代码冲突,随着代码增长,开发速度会呈现指数级增长。这是我们以前遇到过的问题,特别头疼,后来花了很大的精力对系统做了服务化改造拆分。
当然主导这个服务化改造也是需要申请不少资源的,即使没有新的业务上线。为了让老板认为我们正在做的改造是存在价值的,当时还写了改造前后的各种利弊对比。这是很重要的,我们总不能无故的去改造一个运行良好的系统。
有了微服务架构,应用程序由小型分散的开发团队构建,这些团队独立地工作和更改微服务。
这使得测试和升级服务以及随时间增加功能变得更加容易。
最终,如果一个微服务在规模和功能上增长,它可以被分解并分成多个微服务,从而保持微服务的小型、可管理和自治。
最后,采用微服务体系结构允许使用最适合其开发的任何语言
和技术堆栈
来编写单个服务。并没有严格的限制所有的微服务都必须使用相同的技术来开发,只要它们都通过相同的轻量级协议(如HTTP和消息)进行通信,并且数据结构以相同的格式进行序列化(JSON是最流行的选择)。
微服务的特点是:
单体系统要么是数据库变得太大了,要么是代码行太多了,更有可能的是,现在的开发人员不能快速地添加新特性。微服务体系结构避免了单体系统的缺陷,使用真实且可靠的分解技术来解决这些缺陷,并将重点放在敏捷开发和可替换性上,而不是可重用性上。
此外,与单体系统不同,微服务是一个可持续的体系结构,通过添加新的微服务来满足快速变化的业务需求,而不是修改(和破坏)旧的服务。
没有什么架构是免费的
尽管微服务有很多好处,但它并不是万能的。微服务在减轻整体应用程序固有的许多问题的同时,也带来了其他挑战。与技术领域的任何事情一样,总是需要在不同的体系结构和微服务之间进行权衡。
它所提供的敏捷性和开发速度是以增加操作复杂性为代价的,因为自然有更多的活动部件(或服务)—可能比单体应用还要多。
使用微服务架构可能会增加运维开销。 使用这种方法,您的部署可能需要大量资源。您可能需要更多的时间和精力来创建基础架构。 所有服务可能都需要群集以实现故障转移和弹性。 您的系统可能具有数十个单独的组件,并且在您添加新功能时,它将变得越来越复杂。
您可能会得到一个由20或30个或更多服务组成的解决方案,而不是一个整体系统,每个服务都运行多个进程。
最佳实践是,您应该通过DevOps自动化解决这些额外的工作开销。
把单体系统迁移到微服务也是一个巨大的工作量。不推荐用微服务重写系统,这不太现实,特别是单体系统业务比较复杂的时候。建议采用一种更渐进的方法,逐步地重构一个单体系统,逐渐地将它转变成一个由微服务组成的“新”应用程序。随着时间的推移,单体应用程序实现的功能数量会减少,直到完全消失或变成另一个微服务应用程序。最后,不要觉得有必要立即开始分解一切;花时间和工作在最合理的方式为你的团队。
在开始实际的迁移过程之前,我们得思考权衡以下问题:可以肯定的是,具有微服务体系结构的系统提供了大量的好处,例如独立部署、强大的子系统边界和技术多样性。
但是,因为微服务是一个分布式系统,它带来了开发分布式应用程序相关的复杂性的代价,如:独立的数据模型、微服务之间的弹性通信、最终一致性和操作复杂性等。开发和运行大规模的分布式服务也不是一件容易的事情。
在实际的把单体系统拆分为微服务的过程中,不建议用服务大小来衡量拆分效果,而是拆分的业务边界,可以考虑使用DDD的方式去进行建模设计。DDD是我们架构师工具箱中用于标识和设计微服务的优秀工具。
微服务需要关注的点很多,下面画了一张图来表述:
总的来说,微服务MSA架构需要以下技术点的支持:
- 配置管理;
- 服务发现和负载均衡;
- 弹性和容错;
- API管理;
- 服务安全;
- 日志管理;
- Metrics监控;
- 分布式调用链追踪;
- 调度和发布;
- 自动伸缩和自愈;
除了技术相关的,组织结构和团队文化也是很重要的。
下面是一般微服务涉及到的各种组件:
我们先来关注下微服务的各种技术栈的优缺点。
为开发人员提供了用于构建MSA的工具,例如:配置中心、服务发现、断路器、路由等。它是基于Java的Netflix OSS库构建的。
关于如何使用Spring Cloud构建一个微服务架构,推荐您阅读:Microservice Architectures With Spring Cloud and Docker,相关项目架构图如下:
其实dubbo只是一个rpc框架,其架构如下(来源于官方网站[7]):
调用关系说明
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心
注册
自己提供的服务。- 服务消费者在启动时,向注册中心
订阅
自己所需的服务。- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于
长连接
推送变更数据给消费者。- 服务消费者,从提供者地址列表中,基于
软负载均衡算法
,选一台提供者进行调用,如果调用失败,再选另一台调用。- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到
监控中心
。
其提供了Metrics监控,服务发现和负载均衡,rpc调用,其实不能算是一个MSA体系,不过后来阿里整合了Spring Cloud,推出了Spring Cloud Alibaba
,作为微服务开发的一站式解决方案。其中包含了Dubbo Spring Cloud
。
由于 Dubbo Spring Cloud
构建在原生的 Spring Cloud 之上,其服务治理方面的能力可认为是 Spring Cloud Plus,不仅完全覆盖 Spring Cloud 原生特性,而且提供更为稳定和成熟的实现:
Kubernetes是一个开源系统,用于应用程序自动化容器部署、扩展和管理。它支持多语言,并提供了用于配置,运行,扩展和管理分布式系统的原语。
下面列一个表格总结下
技术栈 | 优点 | 缺点 |
---|---|---|
Dubbo | 阿里背书; 成熟稳定; RPC高性能; 流量治理; |
耦合性高; 只支持Java; 国外社区小 |
Spring Cloud | Spring技术栈,快速上手,开箱即用; 组件库丰富; 不同Spring Cloud组件可以很好的集成工作,一切基于注释驱动 |
仅限于Java Java程序员承担了太多的责任 不能覆盖MSA整个生命周期 |
Kubernetes | 多语言和通用性; 易于构建跨团队的平台 覆盖MSA整个生命周期; 社区活跃; |
服务和原语通用化,技术门槛高; 配置繁琐,偏DevOps和运维; 平台快速发展,变化快; |
Dubbo只是一个RPC框架,提供的功能不能覆盖整个MSA生命周期。
Spring Cloud是开发人员友好的平台,可快速上手。
而Kubernetes是DevOps友好的,具有陡峭的学习曲线,但提供了更多的微服务问题解决方案。
Spring Cloud在JVM内部非常强大,而Kubernetes在管理这些JVM方面非常强大。
能力 | Dubbo | Spring Cloud | Kubernetes | 其他技术 |
---|---|---|---|---|
分布式调用链追踪 | / | Spring Cloud Sleuth | Zipkin,Skywalking | |
Metrics监控 | Dubbo Admin/Monitor | Actuator/MicroMeter | metrics-server | Prometheus,Grafana |
集中式的日志管理 | ELK | ELK | EFK | |
任务管理 | Spring Batch | CronJob | ElasticJob/XXL-JOB | |
服务发现和负载均衡 | zk/Nacos + client | Eureka + Ribbon | Service | |
API网关 | / | zuul | Ingress | |
配置管理 | Diamond/Nacos | Spring Cloud Config | ConfigMaps/Secrets | |
应用打包 | Jar/War | Jar/War | Docker Image/Helm | |
自动伸缩和自愈 | / | / | Pod/Cluster Autoscaler,Scheduler | |
发布和调度 | / | / | Deployment strategy,A/B,Canary,Scheduler strategy | |
进程隔离 | / | / | Docker,Pods | |
环境管理 | / | / | Namespaces,Authorization | |
资源配额 | / | / | CPU and memory limits,Namespace resource quotas | |
IaaS | GCE,Azure,CenturyLink,VMWare,Openstack |
根据以上对比,我们想要搭建一个完整的微服务体系架构,有很多技术可以选择的。那么究竟应该如何选择呢
下面是推荐技术选型方案:
公有云
;Dubbo Spring Cloud
完善其他组件。使用Dubbo Spring Cloud[8],配合Kubernetes实现DevOps系统。内部调用通过Dubbo RPC进行,提高效率。技术方案选型归纳如下:
架构没有好坏之分,只有最适合业务的架构,才是最好的。
这里我举个例子来说明架构选型是要跟业务匹配的。我们先来了解三种架构:
单体架构
:一个典型的单体应用就是将所有的业务场景的表示层、业务逻辑层和数据访问层放在一个工程中,最终经过编译、打包,部署在一台服务器上。微服务架构
:微服务是将一个大型复杂软件应用由一个或多个微服务组成,系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。Serverless架构
:无服务器架构是指大量依赖第三方BaaS(后端即服务)服务或暂存容器中运行的自定义代码FaaS(函数即服务)的应用程序,函数是无服务器架构中抽象语言运行时的最小单位。Severless架构中,我们关注运行函数所需的时间,从而计算需要支付多少服务费用。架构类型 | 什么时候采用 | 什么时候不采用 | 采用案例 |
---|---|---|---|
单体架构 | 应用中的各个模块紧密耦合在一起,这些模块在事务上下文中完全相互依赖。需要所有数据操作的即时一致性。 | 应用中的模块可以进一步解耦为原子性的业务服务,或者通用技术功能。 | ERP,CRM |
微服务架构 | 应用的各个模块在运行时以及事务处理中是完全独立的,各个模块的数据可以以无状态的方式进行操作,即使模块间有耦合,也可以通过最终一致性来达到解耦的目的。 | 如果不严格依赖其他模块,则无法独立部署和使用应用程序模块。 | 客户服务,订单服务,库存服务 |
Serverless架构 | 具有完全独立性和单独可伸缩性策略的应用程序模块可以分解为业务或技术的单个功能; 没有请求流量时,应用程序将完全关闭; 开发团队不必关心基础架构。 |
长时间运行的作业,CRUD服务或有状态服务 | 认证,通知,事件流 |
上一节我们讲到了架构的发展史,我们可以看出,目前正是从微服务时代过度到云原生时代的过程。基础的云平台提供:
我们基于云平台提供的运算能力,搭建自己的SaaS系统,最终通过DevOps部署到云上。关键层次划分如下:
IaaS
:Infrastructure-as-a-Service,基础设施即服务,提供给消费者的服务是对所有计算基础设施的利用,包括处理CPU、内存、存储、网络和其它基本的计算资源,用户能够部署和运行任意软件,包括操作系统和应用程序;
PaaS
:Platform-as-a-Service,平台即服务,提供常用的技术组件方便系统的开发和维护。把客户采用提供的开发语言和工具(例如Java,python, .Net等)开发的或收购的应用程序部署到供应商的云计算基础设施上去;
SaaS
:Software-as-a-Service,软件即服务,提供开发好的应用或服务,按功能或性能要求付费。SaaS 是软件的开发、管理、部署都交给第三方,不需要关心技术问题,可以拿来即用。普通用户接触到的互联网服务,几乎都是 SaaS。
想进一步了解单体应用如何拆分为微服务,然后上云,使用k8s进行部署,从而实现从单体应用走向云原生架构之路?方案架构师Andy Wu在Google云平台讨论了单体系统的问题,以及微服务的好处,服务上云计算的好处。并且通过一个真实的场景演示了迁移一个单体系统到这种新体系结构的过程。公众号回复:g01 获取一手完整资料。(英文版)
微服务中的分布式技术
在设计微服务系统,或者研究其底层原理的时候,会涉及到分布式基础知识的方方面面:分布式事务处理、分布式锁、分布式ID、分布式缓存、分布式搜索技术、分布式协调组件、消息队列、高性能通信框架Netty。这个我们在分布式专题专门来探讨下。
这篇文章的内容就差不多介绍到这里了,能够阅读到这里的朋友真的是很有耐心,为你点个赞。
本文为arthinking
基于相关技术资料和官方文档撰写而成,确保内容的准确性,如果你发现了有何错漏之处,烦请高抬贵手帮忙指正,万分感激。
大家可以关注我的博客:itzhai.com
获取更多文章,我将持续更新后端相关技术,涉及JVM、Java基础、架构设计、网络编程、数据结构、数据库、算法、并发编程、分布式系统等相关内容。
如果您觉得读完本文有所收获的话,可以关注
我的账号,或者点赞
吧,码字不易,您的支持就是我写作的最大动力,再次感谢!
关注我的公众号,及时获取最新的文章。
更多文章
本文作者: arthinking
版权声明:
BY-NC-SA
许可协议:创作不易,如需转载,请务必附加上博客链接,谢谢!
构建微服务技术中台,SpringCloud和Kubernetes该如何选型?
Adoption of Cloud-Native Architecture, Part 1: Architecture Evolution and Maturity 架构的演变和成熟度
Spring Cloud for Microservices Compared to Kubernetes
Microservices vs SOA: What‘s the Difference?
What is service-oriented architecture?
Microservices vs SOA: What’s the Difference?
《分布式服务架构:原理、设计与实战》
《Cloud-native-approach-with-microservices》
原文:https://www.cnblogs.com/arthinking/p/12812786.html