用大白话讲微服务——大家都能看懂的演进过程转载本文请联系SH全栈笔记公众号。写这篇博??客的初衷是希望看到这篇文章的读者能够轻松理解我想表达的意思。但是程序分享往往会不经意地贴代码,容易让人看不懂。而且我觉得,只有对方理解了背后的逻辑,分享才有意义。所以接下来我会尽量用大家看得懂的语言来谈谈“微服务”。【写在前面】那么,什么是微服务?你不一定知道微服务,但你一定知道麦克穆劳,而且你知道麦克穆劳有个甜品站。你可能会问,甜品站和微服务有什么关系?我们先假设甜品站不是独立的,而是一家普通的麦当劳店。经营一段时间后,你会发现这里虽然人流量大,顾客多,但80-90%的顾客需求都集中在甜品上,导致甜品供不应求,而买的人却不多。剩下的菜。但是这家店已经关门了吗?那不好,总是有交通。所以综合考虑后,解决方案是将甜品这个“模块”从整个门店中分离出来,单独对外提供服务。这样既可以保持流量,又可以避免浪费。微服务也是如此,比如电商服务,假设耦合了商品、库存、订单、用户服务,但是订单模块可能会被访问??的很频繁,而用户和商品的访问频率是没那么高,如果为了同时为更多的用户提供服务,再部署一个包含商品、库存、订单、用户的服务,两个模块的资源还没有被充分利用。这个想法与甜点站的想法相同。如果把商品、库存、订单、用户分成四个服务模块,每个服务只负责处理自己的事情,就像甜品站只卖甜品一样。如果订单的访问量很大,那只需要再部署一个订单模块,不会造成资源利用不足和强耦合。最初的“WholeMcMurrau”店对应的概念是单体应用,后来独立的“甜品站”是从单体应用中抽取出来的“微服务”。如果您不知道单体应用程序是什么以及微服务是什么,那也没关系。如果您不知道为什么以及如何将单体应用程序转换为微服务,那也没关系。让我们用一个故事来充分理解这个概念。假设正在阅读本文的您拥有一家餐馆。0.【梦想开始的地方】你买了一家店面,想卖炸鸡和甜品,于是简单装修了店面,购买了相关设备,聘请了厨师、服务员等相关人员,你就开始搭起来了一块招牌对外开放。0.1店面就是我们平时使用的各种C端产品。如果没有概念,可以直接理解成钉钉、微信等我们日常使用的APP,都是C端产品。店铺的招牌(比如肯大吉、麦姆老)可以理解为我们在平时的APP中可以看到和使用的东西,我们称之为客户端。整个实体店可以理解为开头提到的“单体应用”,为顾客提供实际的服务。0.2设备的装修和采购对应我们的开发团队,从产品经理接到客户的需求开始,根据需求整理原型图,不断和客户沟通细节,反复修改原型图,最后最终确定要求。然后我们UI同学介入,按照原型图画了UI图,定稿了。然后,前后端开发同学根据原型图中的逻辑和UI图中的样式细节开始迭代开发,最终推出了产品。0.3FriedChickenandDesserts有了前面McGrath的例子,这个应该很容易理解。炸鸡和甜品其实是作为C端产品提供给用户的不同类型的服务。比如我们日常使用的钉钉,可以用来聊天,开视频会议,预定会议室。1.【越来越好】随着你不断推出新菜品,以及份量大、性价比高,朋友之间的口口相传——“那家飞餐厅还行”,也留住了一大批回头客。慢慢地,来店里就餐的顾客越来越多,后厨也渐渐不堪重负。不少前来的客人,因为等的时间太久,还是没有得到招待,更有什者,连个位子都没有。客人对美食的渴望变成了失望和愤怒,所以反手是一个超级差评。1.1新菜品的不断推出代表着我们的产品迭代,新功能的不断推出,为用户提供更多元化的服务,吸引更多用户使用我们的产品。比如疫情期间,钉钉在在线学习方面上线了很多新功能。1.2朋友之间的口口相传是指部分用户开始取代广告作为传播渠道,开始在社区内进行用户自我传播。这是很多产品想要达到的目标,把产品的潜力挖掘到极致,让产品自己说话。比起漫天飞舞的广告,这种朋友的推荐更受用户信赖。1.3对于差评,“后厨太忙”是指用户数量增加,每天的请求数也会相应增加,单个服务实例在一定时间单位内能够处理的请求数是有限的(也就是后厨人数有限,厨师就那么几个,能做的菜数也有限),直接导致一些用户的请求很慢,甚至直接无法访问(后厨太忙,部分顾客要等很久)。用户对产品的耐心是非常有限的,这种情况会导致部分甚至大量用户流失。2.【蜂拥而至】差评越来越多,坐不住了。你觉得这样下去,你可能会感冒,于是你想,如果厨师不够用,就应该多招人,于是就贴出了招聘启事,顺利招人。人的问题解决了,但是还有座位的问题。没想到之前来的人那么多,所以店里的桌椅很松散,但其实如果重新规划的话,还是可以多放几张桌子的,这样可以容纳更多的人同一时间。人们在店里用餐。2.1招更多人我们每项服务可以使用的资源是有限的。例如,您可以将JVM的最大堆内存设置为1G,也可以添加到2G。啊?什么是JVM?不重要,让我们重新理解前一句。2个厨师1分钟可以做5道菜,换手再招2个厨师,1分钟可以做10道菜。这对应的是扩容的概念,即增加服务器可以处理的运行资源,服务器可以处理更多的请求,服务更多的用户。这里的扩展是为了CPU和内存2.2重新规划桌椅的摆放。在开发之初,用户并没有这么大的体量,所以大部分API都没有优化,整个服务端应用的框架也很随意。因为在线时间非常紧张,这可能会导致应用程序的维护性、可扩展性和性能方面的劣势。通俗点说,那时候为了店里好看,为了追求ins的风格,桌椅之间的空间太宽了,但是后来人太多了,一堆人在外面排队,而店里熙熙攘攘,其实你已经“满座”了。这种情况对后续的迭代非常不利。所以开发对应的理念是重构代码和框架,优化算法,让API尽可能少的占用系统资源,减少响应延迟,提升整个服务的服务能力。这样,服务实例可以处理更多的请求。然而,有时,降低延迟和占用较少的系统资源无法同时实现。如果对响应速度的要求很高,可能会占用更多的系统资源,用空间换取时间。就像你重新布置商店,商店容纳更多的人(占用更多的资源),此时服务的响应时间可能会变慢(上菜会变慢),那么usespacefortime是什么?也就是你会提前准备很多食材,甚至是半成品,这样菜品的准备时间可以比平时少一半(比如提前准备好熟油,各种辅料等等)。3.【山尽头】虽然我们多招了几个厨师,重新规划了店内的桌椅布置,但随着时间的推移,每天来店里就餐的人越来越多,不能再招聘厨师。没有那么多炉子了。此前的“差评热”又开始在店内上演。你想,虽然店面人气是好事,但是每天来店里的人那么多,没地方就走。这钱不是赚不到吗?而且很多目标用户都在第三方网站上看到了这些差评,会直接影响到顾客是否愿意来店里,这会让你失去很多隐藏的顾客。于是你开始了轰轰烈烈的分店生意,在附近又开了一家店。还是老样子,就是这个味道~3.1开分支开分支对应的概念是多实体部署,就是把同一个服务再部署一次,让用户的流量从一个服务变成两种服务Carry。分店可以接管总店的客流量,缓解压力。4、【意志暗花明】随着时间的推移,分店开的越来越多,生意自然红红火火。但是作为一个不能只看表面的布局人,你会发现实际情况并不像看上去那么好。有的地区人流量大,有的地区人流量多,但对店里感兴趣的人却不多,分店周围根本没有人。在一些地方,树枝非常热。虽然热门店赚的钱可以抵消冷门店的亏损,但是追求完美的你认为这种情况必须要改善,因为这总是在浪费资源。所以经过一番研究,你决定在中心区开设一个客户中心。所有想来餐厅的人统一到客服中心,客服中心的人会根据各分店的人气分批次送客。这样一来,部分门店火爆,部分门店冷清的局面就迎刃而解了。4.1人流量分布不均主要出现在服务端运行多个实例时,即针对多个IP地址,调用哪个由客户端决定。如果设计的不够好,就会出现有时有些实例会成为热点,甚至是“差评”实例,而其余的实例并没有承载多少用户流量。换句话说,如果我是顾客,去哪家店不就是看心情吗?我可以去任何我想去的商店。当然,实际情况并没有那么夸张,客户会有自己的策略。而且,同时维护那么多服务器地址也很麻烦。如果此时服务端又增加了一个实例,则客户端需要同步更新。但是,如果用户量很大,因为这个问题频繁发包给用户更新,会给用户带来不好的体验。4.2客户中心的比喻有点夸张。实际上,这样做的人可能会早早破产。“客户中心”就是我们所说的“门户”。有了网关,客户端就不需要关心服务有多少个实例,也不需要维护所有的HOST。所有请求都直接从网关发出,网关决定将当前请求分发到哪个实例。“客户中心根据情况分批发送客户”其实对应的就是负载均衡的概念。这是什么意思?这意味着客户端产生的流量应该平均分配给所有实例。实现方式也有很多种,大致分为随机、轮询、一致性哈希、加权等。除了负载均衡,网关还有很多其他的功能。比如动态路由、限流、鉴权、日志记录、熔断、可编程插件配置等。5.【微服务关注点】看完这个故事,你可能觉得没什么,但其实你已经明白了应用程序从单体应用架构向微服务架构转变的架构生命周期和过程。这也包括为什么要切换到微服务架构,切换到微服务架构的好处在哪里。如果你没有意识到你理解了这个概念,你可以再读一遍上面的短篇小说。其实实际的微服务比上面的故事要复杂的多,微服务需要注意的点也比传统的单体应用要多。在微服务中,我们需要关注服务发现、负载均衡、统一配置管理、微服务集群的自愈和弹性伸缩、服务调度和发布、微服务中的调用链监控,包括Metrics监控、日志监控、Securityconsiderations服务,API的统一管理等。首先,将强耦合在一起的代码有序拆分是非常复杂的,微服务的拆分粒度也是一个很大的挑战。比如在一个非常复杂的系统中,一个用户服务的代码可能有几万行,但它仍然是一个微服务,没有拆分用户服务A和用户服务B。但是有些服务可能只有几百行代码行数,所以划分的粒度需要根据实际业务情况来选择。除了拆分服务的粒度,微服务本身还有很多组件。大家只知道故事中的关口。事实上,有很多组成部分。服务发布涉及到Jenkins,将我们的应用打包成DockerImage,然后通过自动化工具发布到相应的环境中。我们的应用运行在Docker中,所以我们需要一个容器编排工具来管理这么多的容器。比如我们现在用的是DockerSwarm,它和业界流行的Kubernetes一样,被很多人使用。有了容器编排工具,就有工具的可视化界面,Portainer对应DockerSwarm,Rancher对应Kubernetes。此外,我们还使用Gitlab作为我们的代码版本管理工具,MySQL和MongoDB作为数据存储解决方案。Redis作为缓存的解决方案。同时需要有一个地方统一管理所有服务的配置,我们称之为微服务的配置中心。此外,要在服务之间相互调用,它们必须知道彼此的地址。需要一个注册中心来保存所有服务的地址,并及时更新服务的状态。还有很多细节,比如如何搭建Jenkins构建流水线,如何实现CI/CD流程,如何使用ELK做统一的日志收集,集群中如何实现SSO等等,篇幅原因这样一一重复。
