当前位置: 首页 > 科技观察

微服务难吗?本文简单了解一下服务拆分和服务发现的前提

时间:2023-03-16 12:32:14 科技观察

服务拆分。服务拆分的前提首先是要有一个持续集成平台,让服务在拆分过程中保持功能一致性。这种一致性无法通过人的经验来实现,而是需要经过大量的回归测试集,以及不断的分裂、不断的进化、不断的集成,才能保证系统始终处于一个可以被验证的状态。验证并交付。与其闭门造车一段时间,谁也不知道功能最终会不会出bug,所以又要花一个月的时间来修bug。其次,在接入层,API和UI要动静分离,API由API网关统一管理。这样无论后端怎么拆分,都能保证前端有一个统一的入口。此外,在拆分过程中可以实现灰度发布、路由分发、流量切分,从而保证拆分的顺利进行。拆分后的微服务之间,为了高性能,不建议每次调用都进行鉴权鉴权,而是在API网关上进行统一的鉴权鉴权。一旦进入网关,服务之间的调用就可以是Faithful。第三,数据库要设计好。不应该有大量的联合查询,而应该把数据库看成是简单的key-value查询。复杂的联合查询通过应用程序层,或通过Elasticsearch。如果数据库表之间的耦合很严重,那么服务拆分就不能拆分了。第四是让应用无状态。只有无状态的应用才能横向扩展,所以拆分才有意义。服务拆分时机满足服务拆分前提后,先拆哪个模块,后拆哪个模块?什么情况下应该拆分出一个模块?微服务拆分绝不是一个很大的飞跃。高层主动将应用拆分成碎片,最终会大大增加运维成本,但并不会带来收益。拆分微服务的过程应该是痛点驱动的,因为业务确实遇到了快速迭代和高并发的问题。如果不拆分,会对业务发展造成影响。只有这个时候,微服务的拆分才有一定的好处,增加的运维成本是值得的。微服务解决的问题之一:快速迭代互联网产品的特点是迭代速度快,通常在一年半内决出胜负,第一者一统天下,第二者被***收购,其他的死。所以,快速上线、快速迭代才是生命线,一旦成功,身价百亿,所以无论付出多少运维成本,微服务架构都是值得的。这也是为什么大部分使用微服务架构的公司都是互联网公司,因为对于这些公司来说,好处是显而易见的。对于很多传统应用来说,每六个月更新一次,企业的运营相对稳定。IT系统的质量对业务没有关键影响。在他们眼里,微服务改造带来的效果还不如多加班开发几个。微服务拆分机会一:频繁提交代码,出现大量冲突。微服务对快速迭代的作用首先是独立开发。如果是单体应用,几百人开发一个模块。如果使用Git进行代码管理,经常遇到的事情就是代码提交冲突。同一个模块,你改他也改,几百个人根本无法交流。所以当你要提交一个代码的时候,发现和别人提交的有冲突,所以因为你是后来提交的人,所以你负责Merge代码。毕竟Merge成功了,等你再次提交的时候,发现又发生了冲突。你很生气吗?随着团队规模的增加,发生冲突的可能性也会增加。所以应该拆分成不同的模块,每十个人维护一个模块,也就是一个项目。首先,代码冲突的概率小了很多,一有冲突,一群人喊一声,基本问题就解决了。每个模块都对外提供接口,其他依赖的模块不需要关注具体的实现细节,只需要保证接口正确即可。微服务拆分时机2:小功能需要积累到大版本才能上线。微服务对线上理事级会议快速迭代的影响,首先是要独立上线。如果不拆分微服务,每次上线都是一件很痛苦的事情。当你修改了一个小角落的功能,但是又不敢马上上线,因为你依赖的其他模块才开发了一半,你要等他,不敢马上上线,因为其他模块依赖了该模块也开发了一半。当所有的模块耦合在一起,相互依赖时,没有人可以独立上线。相反,导演需要协调各个团队。大家开会,约定一个时间点。不管功能大小,死活都要在这一天上线。这种模式导致上线时单次启动的需求清单非常长,风险比较大。也许一个小的功能错误会导致一个大的功能异常上线。这么长的功能需要一点Check,非常小心,所以在线时间长,影响范围大。所以这种迭代速度不能快,最多一个月一次也不错。服务拆分后,在接口稳定的情况下,不同模块可以独立上线。这样上线次数增加,单次上线的需求列表变小,可以随时回滚,风险降低,时间缩短,影响面小,并且加快了迭代速度。对于需要升级的界面部分,灰度有保证。首先,添加接口而不是改变原来的接口。在注册中心监听调用状态时,发现该接口不再使用,遂删除。微服务解决的第二个问题:高并发互联网产品的特点是在短时间内积累大量的用户,这比收入和利润更重要。如果没有庞大的用户群,融资就会出现问题。因此,对于并发量小的系统,微服务的驱动力较弱。如果只有少数用户在线,多线程可以解决问题。顶多应该是无状态的,前面部署一个负载均衡器,单个应用部署多个副本。微服务拆分机会三:横向扩展流程复杂,主副业务耦合。单体应用无状态后,虽然可以部署多副本承载一定的并发量,但是资源非常浪费。因为有的业务需要扩展,比如下单、支付,有的业务不需要扩展,比如注册。如果一起扩张,消耗的资源可能是拆分后的数倍,成本可能还要上亿。而且由于配置比较复杂,在同一个项目中,在配置文件中往往是这样组织的:一块属于本模块,下一块属于另外一个模块。在这样扩容的时候,一些街角商家也需要仔细审视配置,否则不敢贸然扩容。微服务拆分契机4:断路器降级完全依赖if-else在高并发场景下,我们希望请求失败也不会占用资源。它应该尽快失败并尽快返回,我们希望当某些角落业务不正常时,不影响主要业务流程。这就需要熔断策略,即当A调用B,B一直异常时,为了不让B影响到A,B的调用可以熔断,即A不调用B,而是返回一个临时的Fallback数据,当B正常时,释放熔丝,正常通话。有时为了保证核心业务流程,将角落业务流程,如评论、库存号等,手动设置为降级状态,即默认不调用,所有资源都用于订单以及大促销的支付流程。如果核心业务流程和角落业务流程在同一个流程中,需要大量的if-else语句根据下发的配置来判断是否熔断或者降级,这会使得配置变得极其复杂和困难维护。如果核心业务和角落业务分为两个进程,可以使用标准的断路器降级策略配置,在某些情况下可以放弃对另一个进程的调用,统一维护。服务拆分的方法很好。当你觉得要拆分某个程序的某个部分时,有没有什么办法可以保证流畅呢?首先要做的是规范原有的工程代码,也就是我们常说的“接手任何一个模块都能看到熟悉的面孔”。比如打开一个Java项目,应该有如下几个包:API接口包:所有的接口定义都在这里,内部调用也必须实现接口,这样一旦要拆分出来,本地接口对于远程接口,call可以更改为Called。访问外部服务包:如果本进程要访问其他进程,外部访问的封装就在这里。对于单元测试,对于这部分Mock,可以在不依赖第三方的情况下进行功能测试。对于服务拆分,调用其他服务也在这里。数据库DTO:如果要访问数据库,就在这里定义原子数据结构。Access数据库包:所有访问数据库的逻辑都在这个包中。服务和业务逻辑:主要的业务逻辑在这里实现,拆分也是从这里拆分的。对外服务:提供对外服务的逻辑在这里,接口的提供者必须在这里实现。另一个是测试文件夹。每个班级都应该有一个单元测试。要查看单元测试覆盖率,集成测试应该通过模块内部的Mock方法实现。接下来是配置文件夹,配置文件,配置分为几类:内部配置项。(启动后保持不变,更改需要重启)集中配置项。(配置中心,可动态下发)外部配置项。(外部依赖,与环境有关)当一个项目的结构非常规范,那么在原有服务中,首先独立功能模块,规范输入输出,在服务内部形成分离。在分离新进程之前,先分离新jar,只要能分离新jar,就基本实现了松耦合。接下来新建一个项目,启动一个新的进程,尽快注册到注册中心,启动服务。这时候可以先去掉新项目中的代码逻辑,只调用原来的流程接口。为什么越早独立越好?就算独立前逻辑还没实现?因为服务拆分的过程是渐进的。随着新功能的开发和新需求的引入,此时也会有对原有界面进行修改的新需求。如果要分离业务逻辑,一半是独立的,新的需求来了,改旧改新都不合适。新的还没有独立提供服务,如果旧的改了,会造成老项目向新项目的迁移,在迁移和变更的同时合并起来会比较困难。如果尽快独立,所有新的需求都会进入到新的项目中,当所有的调用者更新后,就会转而调用新的流程,对老流程的调用会越来越少,最终新流程将代理所有旧进程。接下来,可以将老项目中的逻辑逐步迁移到新项目中。由于代码迁移不能保证逻辑完全正确,需要持续集成和灰度发布,微服务框架可以在新旧接口之间切换。最后,当新项目运行稳定,调用监控中没有对老项目的调用时,老项目就可以下线了。服务拆分规范微服务拆分后,项目会更多。如果没有一定的规范,就会很混乱,很难维护。首先大家经常问的一个问题是,服务拆分后,原来在一个进程中的函数调用,现在是A调用B,C调用D,E调用。通话链接会不会太长?它会相应地减速吗?服务拆分规范1:服务拆分最多可以做三层,服务拆分调用两次是为了水平扩展,所以要水平拆分,不要垂直拆分。也就是说要把产品和订单拆分,而不是把下单这十个步骤拆分,然后一个一个调用。垂直拆分最多可达三层:基础服务层:用于屏蔽数据库、缓存层,提供原子对象查询接口。有了这一层,当数据层发生某些变化时,如分库分表、数据库扩容、缓存更换等,对上层透明,上层只调用本层的接口,并做不直接访问数据库和缓存。复合服务层:该层调用基础服务层完成更复杂的业务逻辑,大部分分布式事务都在该层实现。控制器层:接口层,对外调用组合服务层。服务拆分规范2:只能单向调用,严禁循环调用。拆分微服务后,服务之间的依赖关系复杂了。如果循环调用,升级的时候会很头疼。不知道先升级哪个,再升级哪个。,难以维护。因此,层与层之间的调用规则如下:基础服务层主要进行数据库操作和一些简单的业务逻辑,不允许调用其他任何服务。复合服务层可以调用基础服务层完成复杂的业务逻辑。它可以调用复合服务层。不允许循环调用,不允许调用Controller层服务。Controller层可以调用复合业务层服务,不允许被其他服务调用。如果有循环调用,比如A调用B,B又调用A,则分为两层:Controller层和复合服务层。A调用B的下层,B调用A的下层。也可以使用消息队列,将同步调用改为异步调用。服务拆分规范3:串行调用改为并行调用,或者异步。如果某些组合服务的处理流程确实很长,需要调用多个外部服务,就应该考虑如何通过消息队列实现异步解耦。比如下单后需要刷新缓存,通知仓库等,这些都不需要在下单成功的时候做。相反,您可以向消息队列发送消息以异步通知其他服务。而且使用消息队列的好处是只需要发送一条消息,不管下游依赖方是一个还是十个,一条消息都搞定了,下游多几个listener就可以了。对于必须同时完成的订单,比如扣库存、优惠券等,可以并行调用,这样处理时间会大大缩短,不是多次调用时间的总和,而是最长的系统调用时间。服务拆分规范4:接口要实现幂等的微服务拆分,服务间调用出错时肯定会重试,但为了不二次下单二次支付,所有接口都需要实现幂等.幂等性一般需要通过设计幂等表来实现。幂等表中的主键或唯一键可以是事务id或业务id,通过这个id的唯一性可以标识一个唯一操作。还有使用状态机的幂等操作。当呼叫到来时,它通常会触发状态更改。下次调用来的时候,发现已经不是这个状态了,说明上次的调用已经完成了。状态改变需要是原子操作,即并发调用时,只能执行一次。可以使用分布式锁或者乐观锁CAS操作来实现。服务拆分规范5:严禁嵌入接口数据定义,微服务接口之间的数据透明传输往往是通过数据结构,如果数据结构是透明的,则从底层到顶层使用相同的数据结构层。或者上层数据结构嵌入底层数据结构。当数据结构中增加或删除一个字段时,受影响的区域会非常大。因此,每两个接口之间应约定接口数据??的定义,严禁嵌入和透传。即使它们几乎相同,也应该重新定义它们。这样,接口数据定义的改变只影响调用者和被调用者。当接口需要更新时,相对可控,易于升级。服务拆分规范6:规范的项目名称微服务拆分后,项目名称有很多,开发者和开发团队也有很多。如何让开发者看到一个项目名或者一个jar的名字,就大致知道它是做什么的,需要一个标准化的协议。比如pay的出现就是支付,order的出现就是下单,account的出现就是用户。再比如,compose是组合层,controller是接口层,basic是基础服务层。api的出现是接口定义,impl是实现。pay-compose-api是支付组合层接口定义。account-basic-impl是用户基础服务层的实现。服务发现选择微服务拆分后,服务之间的调用需要服务发现和注册维护。主流的方式有以下几种:Dubbo***就是Dubbo。Dubbo是一个标准的SOA架构的微服务框架,已经得到了广泛的应用。虽然中间中断了一段时间的维护,但是随着微服务的兴起,重新维护起来,是很多熟悉DubboRPC的开发者的首选。第二种SpringCloud是SpringCloud。SpringCloud为微服务而生。当Dubbo不再有人维护的时候,它已经推出了一个成熟的框架来支持微服务。DubboVSSpringCloud对比:Dubbo更注重服务治理,原生功能不够全面,而SpringCloud则着眼于整个微服务生态,工具链非常全面。SpringCloud具有高度可定制性,通过各种组件满足各种微服务场景。使用SpringBoot统一编程模型,可以快速构建应用。基于注解,简单易用,但学习门槛较高。Dubbo在ZooKeeper中注册的是接口,SpringCloud在Eureka或Consul中注册的是实例。规模比较小的时候没有区别,但是一旦规模大了,比如实例数在10000级别,接口数据在100000级别。对于ZooKeeper中的treesize,规模比较大。此外,ZooKeeper是强一致性的。当一个节点宕机时,节点间的数据同步会影响在线使用,而SpringCloud好很多,实例级别少一个数量级,Consul不是强一致性。Kubernetes第三个是Kubernetes。Kubernetes虽然是一个容器平台,但是它是为运行微服务而设计的,所以它提供了很多微服务运行的组件。SpringCloud能做的很多事情,Kubernetes也有相应的机制,而且因为是容器平台,所以比较通用,可以支持多种语言,对业务没有侵入性。但由于是容器平台,微服务运行生命周期的维护相对全面,服务间的调用和治理相对薄弱。服务只能满足最基本的服务发现需求。所以在实际使用的时候,往往会结合使用Kubernetes和SpringCloud。Kubernetes负责为微服务提供运行环境;服务之间的调用和治理由SpringCloud处理。ServiceMesh第四种是ServiceMesh。ServiceMesh在一定程度上弥补了Kubernetes服务治理的不足。入侵业务代码0,将服务治理下沉到平台层,是服务治理的趋势。但是ServiceMesh需要使用单独的进程进行请求转发,性能并不理想。加上社区比较新,还不够成熟,所以还没有达到大规模生产使用的标准。好处来了。请结合自身情况谈谈对微服务架构的理解。扫描下方二维码关注技术栈公众号。欢迎在技术栈微信上留言讨论公众号。小编将选出10位评论最精彩的网友,赠送一本书?~活动截止时间为9月20日12:00。特别感谢机械工业出版社为本次活动提供的图书赞助。迫不及待送书的朋友可以点击阅读原文直接购买。本书简介本书首先从微服务架构兴起的背景出发,探讨微服务架构为何会在分布式系统的发展中逐渐取代单体式架构;一篇讲解,让读者不仅可以系统地学习SpringCloud的相关知识,还可以全面掌握微服务架构应用的设计、开发、部署、运维。