一点一点理解微服务
Posted sp42a
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一点一点理解微服务相关的知识,希望对你有一定的参考价值。
架构演进小史
随着用户数量的增加,我们的项目在一个 Tomcat 容器、一个 mysql 数据库上倍感吃力,用户抱怨访问响应速度慢,我们在服务器上观察 CPU 占有率飙高,可用内存不足等问题。这种集中式结构如下插图所示,也可称为“单机或单体结构(Monolith)”。
用户量上去了当然是好事,对于我们技术人员却是挑战更大了。首先我们可以想到一些简单直接的方法,就是升级带宽、升级服务器硬件配置等——不错,除了这些横向的方法外,还有纵向维度的方法,而且这是与软件深度结合的,并不是简单地修改硬性配置那么简单。
最开始 Web 服务器、数据库、文件资源是在同一台机器上跑的,一个服务器的处理能力是有限的,先将它们分离:Web 服务器独立一台机器、数据库独立一台机器、文件存储独立一台机器——显然,静态资源的文件如图片、视频等不需要动态处理,那么采用 Apache 或 nginx 即可,无须 Tomcat,或者部署在阿里云 OSS 专门优化文件的存储,甚至加入网络优化的 CDN 机制。
这种结构可称为分布式(Distributed)结构如图2所示,当然现在的这种做法是比较粗浅地按照软件形态来划分。
与此同时,Web 程序加入各种缓存服务,例如 JSP 动态页面静态化,那也是一种缓存策略,当然还有专门用于缓存的 Redis 或 Memcache 的服务。
数据库当然也是与 Web 服务器分离。如果发现性能瓶颈在数据库,采取主从数据库(Master/Slave)、读写分离和分库分表等的策略。与此同时还要不断进行优化 SQL,加入索引等工作。此阶段最后形成如插图所示的具体架构。
用户量达到一定数量级之后,发现上述优化的招数都不灵了,该如何是好?上述是一台机器做一件事情,光一台机器做不来,就要多台机器去支撑它了,故所以还是堆机器,但是策略明显不同。这种方式我们称为“集群结构(Cluster)”,如插图所示。
原先单机运行的服务,无论是Web服务器还是数据库服务器,把它作为节点(Node)复制多份副本,构成了一个集群,是一种组件的多个实例。比如说同时有 100 个请求过来,后端准备好有10台 Web 服务器,则平均分给每台 10 个请求去处理。可见这有一关键角色负责调度这些节点如何响应请求的,称为“负载均衡服务器”,用户的所有请求都先交给它,然后根据负载情况落实分配。通过一定的算法,让空闲的节点(负载较小)优先响应,故障的节点则不参与工作。
机器多的好处还不止于性能的改进,还使得容灾能力变为可能,一台机器挂了就挂了,集群机器允许部分机器挂了整个系统还是可用的。
请体会分布式(如插图 7.2)与集群(如插图 7.4)的微妙不同,分布式任务之所以区分 A、B、C……表示拆分过的不同业务,例如商城一个下单业务可分为下单初始化业务、支付业务、财务业务、物流业务等;集群的任务没有区分 A、B、C……是表示任务是一种整体业务,未经拆分且相互隔离,复制在多个服务器上执行。也就是说,集群下的任务仍是单机性质的应用,包含了多个业务能力,且没有与其他节点进行通信,任务自始至终都在单个节点中的进程完成。
集群与分布式两者并不冲突,实际中它们往往配合一起使用。
当业务增长到一定程度的时候,发现上述优化的招数都不灵了,又该如何是好?尽管集群结构的好处就是系统水平扩展非常容易,但不得不说堆砌机器的成本非常高。况且这一问题并不是线性的,比如说电商场景的秒杀促销活动:碍于单机应用的整合,“秒杀”都是部署在一个 WAR 包里面的,那样的话,当大量请求高速涌入时,无法识别哪些是秒杀流量,哪是是正常页面的流量,很可能因为促销活动影响了正常网络的访问。考虑这种情况,不得不把系统内部放进更细化的颗粒度去思考了,具体说,就是必须单独对一个模块进行扩展,而不是作为一个整体里“笼统地”扩展(尽管已经集群了)。渐渐地形成了一种“业务拆分”的技术手段,把一些业务逻辑使用独立的进程来承载,可以更细化地进行扩容,伸缩性更强。像这种以单个业务为视角的可为理解为分布式的进一步深化应用。
分布式下的任务可视作一个服务(Service),每个服务器节点都是只完成这一种服务的,专注性更强。这不仅是性能优化之下带来的要求,同时还是架构上合理化的迫切需求。试想想看,一个系统有论坛有邮箱有聊天室,涉及了用户登录和用户中心,由于分开部署都各自一套,不仅资源重复浪费而且管理起来也不轻松。于是为克服上述问题,分布式服务化等的各种思想和方法论在大型项目中被引入进来了。
微服务风格架构
深度分布式架构下的特征是业务拆分(服务拆分),形成一个比集群网联系更强、更密切的网络。以往我们在学习工作的环境都是把所有代码放在一个项目中,部署时打包WAR包上传到服务器中,这种就是单机结构。即使进化到集群结构,实际工作是多部署几台服务器但代码基本相同的,无须作太大的修改。但是当进入到当下这个分布式的结构之后,旧的代码可是要根据几个独立进程之间的通信问题作出修改。
假设仍是商城的例子,按照微服务的思想,我们需要按照功能模块拆分成多个独立的服务,如:用户服务、产品服务、订单服务、后台管理服务、数据分析服务等等。每个服务可以自己独立的 Web 容器或数据库,甚至这些服务可以是异种语言编写的(如 Java/php/Go/Node.js 等)。
在过去的单机结构中,一个模块调用另外一个模块,简单自如得像一个函数呼叫另外一个函数,不违和不做作,很少进行跨进程的调用,也根本不存在微服务才有的服务注册、发现。但经过业务拆分的服务化改造后,考虑的问题更多了,分布式网络拓扑结构、网络可靠性、通信机制等内容成为了我们关注的话题。不可避免地,各服务之间需要一种相互通信机制来沟通,这便是 RPC(Remote Procedure Call)调用了。
微服务的好处是:告别强耦合、混沌、笼统的大系统,化解为一个个“微小的服务”,能够有针对性的对某一模块进行扩展和维护,例如上述商城那例子,下订单模块和秒杀模块在促销前提升节点数量就可以了,而后台系统维持原有能力即可;另外因为解耦了、抽取了所以各模块变得可轻松替换了。微服务而外的好处是随结构带来的模块复用,这点很好理解,如同拆分了独立的函数,即可实现代码复用。这一点并非性能上的使然,而是业务服务化之后梳理带来的好处。
为了解决集群不能解决的问题于是提出了分布式的微服务。而微服务大体来说没有什么银弹级别的灵丹妙药,仍是“分而治之(Divide and Rule)”的哲学。另外一面来说,为了解决一个问题却引入了更多的问题要去克服。是否值得呢?一旦微服务改造或实施不成功,往往就不是“化繁为简”而是“简单的事情变复杂化”了,得不偿失。这不是逻辑上的悖论,还是那条恒古不变的金科玉律:总之视乎需求取舍而定,当集群实在满足不了,才上微服务。
提到微服务不得不提十几年前就有的 SOA(Service -Oriented Architecture),微服务与之有许多重叠的概念,但 SOA 的缺点是如 ESB(服务总线)和 WebService 子类的包袱比较重。微服务,顾名思义,其特点在于“微小的”各个子服务构成了一个大的系统,相对轻量级很多。
以上是关于一点一点理解微服务的主要内容,如果未能解决你的问题,请参考以下文章