9企业从单体架构向微服务架构转型的难点平台上有成功的案例,但看似简单的框架在实际开发过程中会面临很多问题。本文梳理了企业从单体架构向微服务架构转型的设计难点。主办方:金融公司潘志伟,十余年从业经验,精通微服务架构,精通大数据,有亿级用户平台架构经验,有API网关经验万级并发。以下专家也进行了分享:苏宁消费金融有限公司技术总监顾黄亮、zhuqibsMcd软件开发工程师等。问题一:企业从单体架构到微服务架构的转型,如何入手?这是大家比较关注的一个问题。企业计划向微服务转型,但真正实施后却难觅踪影。事实上,微服务架构的改造不仅仅是一项技术活动,更重要的是组织架构与技术改造的结合。其中,组织变革是起步的首要条件,包括统一思想和充分培训。(1)统一思想在准备实施微服务时,首要条件是获得高层的认可,因为这涉及到组织架构的调整和后续人力资源的增加。例如,在一个单一的应用中,它的组织结构包括开发部门和测试部门,运维部,DBA部,各部门各司其职,高层指挥。看似很合理的组织架构,但在项目或迭代的实际过程中,大量时间会耗费在跨部门的沟通上,形成一个孤岛式的职能团队。但是,在实现微服务的时候,希望它们能够相互协调,快速交付。如果仍然需要多个跨部门协调来处理问题,“微”就很难实现“微”的好处。微服务的团队应该是这样的:所以如果没有高层的参与,那么组织架构是不会调整的。(2)充分培养微服务开发的重心:微服务架构的开发人员具有“精”、“气”、“灵”的特点,否则在后续的开发阶段肯定会出现各种问题。“精”是指熟悉业务,熟悉模型选择的开发框架。“气”是指大家思想认知一致,能够一脉相承。“神”是指需要了解其理论知识,理解为什么要这样做。不是这样的。微服务在开发设计过程中需要注意以下几点:一份基准代码,多份部署(deploy):程序部署需要独立于环境,不改动任何一行代码,如图2-3所示显式声明依赖:通过依赖列表,准确声明所有依赖(如MAVEN依赖),新开发者简化环境配置过程“做产品”而不是“做项目”将配置存储在环境中:需要的代码和配置在严格分开,配置可以完全不同,但代码必须相同。配置和代码无关。“去中心化”治理技术将后端服务视为资源:后端服务是指通过网络调用程序运行所需的各种服务,例如数据库、MQ、缓存等,无需任何代码改动,用第三方服务替换MySQL数据库,严格分离构建和运行:构建阶段是指将代码仓库转化为可执行包的过程,发布阶段会将构建的结果与当前部署进行对比需要的配置组合起来,可以在运行环境中立即投入使用,比如回滚。运行阶段是指在选定的发布版本的执行环境中启动一系列应用进程。无状态进程运行应用:在运行环境中,应用通常运行在一个或多个进程中,任何需要持久化的数据都必须存储在后端服务中,比如数据库。问题2:微服务中所谓的服务如何拆分,服务拆分成哪些?好的粒度服务?在讲服务拆分之前,先定义服务:服务是分布式架构下的基本单元,包含了一组具体的功能。微服务的拆分方法没有明确的标准。可谓是千人千面。每个人对服务拆分和拆分尺度的理解都不一样。一些团队每个接口使用一个服务。一般来说,在拆分的时候,我们会结合理论知识和拆分原则来综合考虑:1)微服务拆分的理论指导——团队规模一般来说,5-7人的团队比较合适,因为沟通效率和团队扩展性可以保证。如果一个团队的人数太少,本来应该多人开发的服务最后会被1-2人开发,这会导致原本设计的服务拆分逻辑合并到一个项目中进行发展到最后,失去了服务的微观意义。-尽可能缩短项目交付周期。项目交付周期短,将需求变更频繁的功能尽可能分离成单独的服务,保证快速迭代,满足快速上线的需求,缩短项目交付周期,同时可以随时进行回滚可降低风险并提高系统稳定性。-改变一个业务迭代功能点的影响范围,尽量不要分布到多个微服务中,尽量将关联的实体对象存储在一个微服务中,避免分布式事务,比如抽取20%频繁变化的部分,80%%独立部署和管理,很少更改。-对于访问频繁、吞吐量大的服务,尽量使用独立的微服务,方便扩展,有效提高资源利用率。2)服务拆分原则——高内聚低耦合高内聚低耦合是软件工程中的概念。在软件设计中,耦合和内聚通常作为衡量模块独立程度的标准。但它也适用于微服务拆分。服务拆分的标准之一是高内聚低耦合。从功能粒度上看,高内聚意味着每个服务尽可能只能完成一件事情(最大聚合);低耦合意味着减少对外部服务的依赖,尽可能避免服务调用服务。从数据库的角度来看,每个服务使用独立的数据库,如果需要使用外部数据,必须通过接口调用。-切入业务模型在高内聚低耦合的前提下,可以通过业务线进行拆分,比如将用户、商品、订单、评论拆分成独立的服务。将相关业务聚合在同一个服务中,也避免了跨库带来的数据一致性问题。可能初期切入业务模型会比较粗糙,但可以通过后续的迭代频率和吞吐量指标来衡量是否继续切入。问题三:如何解决分布式事务?一旦服务拆分完成,就会涉及到分布式事务。在谈到数据一致性要求时,有两个非常重要的理论,即CAP定理和Base理论:CAP定理:C表示Consistency,即所有用户看到的数据都是一样的。A表示可用性,这意味着始终可以找到可用的数据副本。P表示partitionfaulttolerance,可以容忍网络中断等故障。BASE理论:BA是指基本服务的可用性,支持分区失效。当分布式系统发生故障时,允许其失去部分可用性。为了提高系统的可用性,S代表一个灵活的状态,允许系统有一个中间状态,不会影响系统整体的可用性。比如数据库的读写分离,写库到读库之间会有延时(从主库同步到从库),E表示最终一致性,数据最终一致.比如主从同步虽然有短暂的数据不一致,但是最终的数据还是一致的。在实践中,可以使用本地事务和发送MQ消息等灵活事务来解决分布式事物面临的问题,既可以保证服务的稳定性,又可以保证调用效率的高效率。对于MQ,可以使用Apache的RocketMQ提供的事务消息结合本地事务表。问题四:微服务框架选型?在选择微服务架构框架时,我们讨论的是目前主流的微服务框架Dubbo和SpringCloud。Dubbo诞生于阿里巴巴家族。是阿里巴巴服务化治理的核心框架,广泛应用于国内各家互联网公司。只需要通过spring进行配置即可完成服务,对应用没有任何侵入。设计的目的是为自己的业务服务。SpringCloud是著名的Spring家族的产物,专注于企业级开源框架的开发。SpringCloud发展至今,还在高速发展,几乎考虑了服务治理的方方面面,开发起来非常方便简单。这两个开发框架被互联网巨头广泛使用,所以选择任何一个框架都不会成为技术瓶颈。关键是看团队熟悉哪个框架,选择最好的,而不是跟风。问题5:微服务架构下网关的必要性以及网关下的限流、熔断、降级等操作。行的话网关意义不大。其实网关可以理解为反向路由,屏蔽内部细节,为调用者提供统一入口,接收所有调用者请求,通过路由机制转发给服务实例。同时,网关也是一个“过滤器”的集合,可以实现一系列相关的功能。安全认证、限流熔断、日志监控等与业务无关的横截面功能。-网关工作原理协议转换:将不同的协议转换为“通用协议”,再将通用协议转换为本地系统可以识别的协议,例如将http协议转换为dubbo协议。链式处理:消息从第一个插件流入,从最后一个插件流出,每一步中的插件对传入的消息进行处理,整个过程形成一条链。优点是它将处理请求与处理步骤分开。每个处理插件只关心需要在这个插件上做的处理操作,处理步骤和逻辑顺序由“链”完成。异步请求:所有请求都会通过API网关访问应用服务。无论业务量如何变化,网关的吞吐量都应该保持稳定。如果网关的请求被视为IO操作,处理请求的线程将被阻塞,直到服务器返回响应后才接受请求。操作系统所能承载的线程数是有限的。如果多个线程处于这种状态,系统会变慢。异步请求是指每个请求访问网关时,都会被打包成一个事件,CPU核心会维护一个监听器不断轮询请求事件,这样请求线程就不用等待数据返回了。请求完成后直接返回。-网关限流、降级网关熔断、降级是针对接口的,可以选择hystrix或者sentinel来做服务,一般来说需要有如下设置:设置错误率:可以设置每个服务的错误率达到指定范围开始融合或降级;withmanualintervention:可以手动触发手动干预,主动触发降级服务;设置时间窗口:可配置设置熔断或降级触发的统计时间窗口;主动报警:当接口熔断时,需要主动触发短信通知接口当前熔断器信息;问题六:如何设置超时时间?微服务中有一个接口调用涉及到多个依赖服务,每个依赖服务的耗时都不一样,所以超时时间怎么设置是很有讲究的,首先要有一个统一的——一刀切的态度,即每个界面的响应时间不要超过阈值(比如1秒或2秒),一方面提高了用户体验,另一方面也增加了系统的稳定性。如果调用链路比较深,需要通过发送MQ消息来解耦不必要的链路,其次通过并行调用来降低系统的响应时间。一般来说,超时时间一般不会超过1秒。如何优化到1秒,需要从系统的整体角度考虑,而不是只关注某一点。问题七:断路器设计需要考虑哪些要点?服务拆分后,系统中原来的本地调用会变成远程调用,引入了更多的复杂度。比如服务A依赖服务B,在这个过程中可能会出现网络抖动、网络异常等情况。当服务B不可用或响应变慢时,也会影响A的服务性能,甚至可能使服务A占满整个网络。线程池导致此应用上的其他服务也受到影响,造成更严重的雪崩效应。需要对以下几项进行个性化配置:?错误率:可以设置每个服务在错误率达到指定范围后开始熔断或降级;?人工干预:可进行人工干预,主动触发降级业务;?Timewindow:Available可配置设置熔断或降级触发的统计时间窗口;主动告警:接口熔断时,需要主动触发短信通知当前熔断接口信息;目前市面上可用的产品如:Hystrix或Sentinel,用于服务融合和降级,这里推荐使用Sentinel,不管是Dubbo还是SpringCloud,只要使用官方给的依赖,就可以快速接入。问题八:微服务架构中业务系统众多,那么如何保证数据的一致性,如何实现数据隔离机制等?微服务架构中的业务系统越来越多,不管是缓存场景还是内存数据库场景,redis的使用都很普遍,但是每个业务系统部署一套redis集群,很浪费资源。而且,考虑到同城异地建设信息系统,成本也相当高。有没有类似中台的机制?建立统一的redis平台,提供各种场景的服务?那么如何保证数据的一致性,如何实现数据隔离机制,如何评估性能等等?答1:(1)首先统一的rediscenter是很“技术”的,因为你需要很强的技术人员或团队;(2)rediscluster为了保证一致性,从master上读取数据,可以保证数据一致性,当然性能也差;redis主从模式,写入主节点,异步同步从节点,从从节点读取数据,读取性能提升,但一致性难以保证。这就是孟德尔不可能三角中的CAP原理,在保证P的同时,不能同时满足CA。(3)当然没有解决办法,但是redis作为缓存数据库,没有那么复杂。在现代分布式数据库,采用multi-raft架构最大程度的解决了这个问题——master是在变的,它根据不同的应用在不断的变化,同时reader总是在变化的master上写和读。(4)Redis也有东西s,但是它只保证一致性和隔离性,没有原子性,上面说了一致性。因为redis本质上是单线程的,一条一条执行命令。在这个执行顺序中,隔离是有保证的。回答2:第一个选择是纠正你对微服务架构的理解。在微服务架构下,要求各个原子服务的数据库和缓存相互独立。原因是当服务依赖的数据库或缓存出现问题时,只会影响到它。自身服务不影响其他服务,避免级联问题。其次,关于你担心的资源浪费,可以考虑各个服务的调用量,设置不同的服务资源配置。目前无论是使用docker虚拟化,还是云平台提供的redis服务,都可以实现非常低的成本。.因此,如果想要微服务稳定,按照标准模型,每个资源应该是隔离的,而不是聚集在一起。回答3:这个架构有问题。统一的redis平台或者集群提供服务,那么这个集群就必须要横向扩展,只能是cluster集群架构。因此,从一致性、数据隔离、性能评估三个方面来分析:1、可以实现一致性,集群的特性可以保证数据的一致性。2、无法实现数据隔离。单机支持多个数据库,每个数据库的数据都是孤立的,不能共享。Cluster没有数据库的概念,不支持多数据库。3.性能评估取决于承载服务的访问量。问题九:接口拆分成多个微服务后,接口响应变慢怎么办?答1:理论上不会出现慢的现象,可以从以下几个方面进行排查:(1)使用skywalking或者其他APM监控软件,定位问题,哪个服务慢;(2)查看慢服务所属容器的cpu和内存配置,以及运行时的cpu和内存负载;(3)如果cpu和内存占用较大,需要进一步拆分应用;(4)检查是否有串行微服务,不适合拆分。回答2:这个问题应该是拆分前没有规划造成的。1、拆分后,链路会变长,服务之间的通信、交互、处理都需要时间。这是正常现象,但不会导致性能陡峭。2.有几个拆分原则,比如严重性、速度、读写、多少;3、如果慢的话,查看链路监控,看看是哪里慢了,然后扩容,包括微服务组件的扩容和优化。答3:一个应用功能拆分成多个服务后,原来调用一个接口就可以完成的功能现在需要调用多个服务。接口响应时间较长,所以原来串行调用的服务应该改为并行调用。例如,接口A需要调用三个接口:S1(耗时200毫秒)、S2(耗时180毫秒)、S3(耗时320毫秒),采用串行调用方式,则接口A累计耗时=SUM(S1+S2+S3)=700毫秒。为了使响应时间更短,需要将这些串行调用的方法改为并行调用的方法。并行调用方式调用接口A累计时间为MAX(S1,S2,S3)=320毫秒。可以使用jdk8提供的CompletableFuture方法并行执行。
