前言
随着业务零碎的复杂性越来越高,零碎之间的调用也越来越多,在微服务拆分和迭代过程中,是一直的拆分出新的独立的服务还是封装独立的组件以 jar 包依赖的形式提供服务是咱们常常须要面对的问题,本文将具体探讨这两种不同的形式区别、各自的优劣势及实用的场景,心愿可能对大家有所启发。
一、组件化 & 服务化定义
随着公司互联网业务倒退越来越迅速,零碎的复杂性越来越高,零碎之间的调用也越来越多,在微服务拆分和迭代过程中,常常会遇到两种场景问题:
- 本人零碎外部的一些公共功能模块到底以什么模式提供服务,是封装好所有逻辑和办法而后以 jar 包的模式提供,还是独立拆分出一个服务而后通过接口的形式来提供;
- 波及对外部零碎服务的调用,零碎外部可能有很多的服务都须要调用内部服务,然而调用逻辑都是一样的,那么针对内部零碎的接口调用逻辑和办法是封装成一个 jar 包给外部各个服务依赖调用,还是把对外部零碎的接口调用逻辑和办法独立拆分成一个服务,而后外部各服务通过调用这个独立拆分进去的服务去调用内部零碎服务。
针对以上两种场景,咱们能够总结概括为 组件化 和服务化 两种不同的服务提供模式:
组件化定义:即把零碎外部的一些公共功能模块或者对外部零碎调用的一些逻辑办法封装成一个独立 jar 包,有须要的零碎间接依赖该 jar 包来应用相应的服务,在此咱们称之为组件化;
零碎外部公共功能模块组件化示例,服务 A、B、C 都独立依赖的组件 D 来应用相干性能。
内部零碎服务接口调用组件化示例,服务 A、B、C 都通过组件 D 去调用内部服务 E
服务化定义:即把零碎外部的一些公共功能模块或者对外部零碎调用的一些逻辑办法独立拆分为一个服务,该服务再对外裸露对立的接口供所有有须要的服务去调用,在此咱们称之为服务化。
零碎外部公共功能模块服务化示例,对应就是把示例图 1 中组件 D 独立拆分为服务 D,服务 D 再提供接口给服务 A、B、C 去调用。
内部零碎服务接口调用服务化示例,对应的就是把示例图 2 中的组件 D 独立拆分为服务 D,服务 A、B、C 通过调用服务 D 去调用内部零碎服务 E。
那么在理论工作中,面对不同的场景和问题,咱们具体该抉择哪一种形式呢?是否相干的参考规范,有哪些问题是须要咱们特地关注和思考的,接下来咱们会具体介绍下组件化和服务化各自的优劣势及实用的场景。
二、组件化的优劣势及实用场景
组件化这种通过 jar 依赖的形式去调用第三方服务到底存在哪些劣势和劣势呢?
2.1 组件化存在的劣势
- 服务调用性能高,因为都是间接通过调用 jar 包里的办法来调第三方服务,性能损耗较少,对性能要求较高的场景应用该形式会有肯定劣势;
- 节俭服务器机器老本,因为不须要独立部署服务,能够节俭服务器资源,尤其在服务器申请量大 QPS 高须要部署大量服务器资源的场景下可能节俭的服务器资源也越多。
2.2 组件化存在的劣势
- 可维护性较差,一旦调用其余服务的逻辑办法须要变动,或者第三方提供的 jar 包须要降级的话,除了该组件自身须要保护降级,咱们本人零碎外部依赖了该组件的服务都须要跟着一起降级,随着工夫的推移,梳理保护起来会很麻烦;
- 组件降级老本高且危险较大,零碎外部依赖了该组件的服务如果很多的话降级老本会很高,这外面的老本包含了开发保护降级各个服务的老本、测试验证的老本及运维公布的老本,需降级保护的服务越多,老本越高,对应的危险也越大。
2.3 组件化实用的场景
那么具体哪些场景适宜应用组件化的形式来部署呢?依据咱们的教训来看,合乎以下场景特点的倡议应用组件化的形式:
- 本人零碎外部一些公共性能解决场景,不波及到数据库资源层面的连贯和调用,适宜组件化的形式;
- 对外部零碎服务调用场景,服务并发量大对服务性能的要求很高,次要是一些 to C 的服务,要求高性能低延时,须要尽量减少服务调用链路,这种状况比拟适宜把对外部零碎调用逻辑和办法以组件化的形式来提供,如果业务自身对性能要求极高,在很多状况下会优先思考性能问题而容忍组件化带来的一些劣势;
- 公司对于服务器资源老本管制要求较为严格,尽量降低成本,这种状况对于初创公司或者我的项目较为常见些,常常是要求是低成本疾速试错。
2.4 应用组件化的案例
案例一
利用商店月活用户 2.4 亿,日活 6000 万 +,对商店服务器性能要求十分高,商店外部很多服务都波及到了大量的内部零碎服务调用,比方 CPD、游戏、DMP 等等,在用户体验和性能优先的前提下,咱们都是通过组件化的形式来集成对外部零碎的调用,容忍一些在保护和降级上的不便。
2.5 组件化应用的背面案例
案例二
再分享一个商店应用组件化形式的一个背面案例,商店内很多服务模块都波及到一些经营资源位的治理,很多服务都须要向客户端下发一些经营位的资源素材,在最后没有充分考虑各类场景问题,最显著的就是这些资源素材的获取都波及到数据库资源的连贯和调用,在应用组件化后会导致咱们开发保护老本高,迭代效率低。
三、服务化的优劣势及实用场景
3.1 服务化存在的劣势
- 服务化后可做到资源隔离,互不影响,对调用方暗藏外部细节,可独立进行开发部署,晋升开发效率;
- 相比组件化来说可维护性更好,服务化之后各个模块服务之间是解耦的,不论是调用其余服务的逻辑办法须要变动,还是第三方提供的 jar 包须要降级,只须要该服务自身降级即可,只有接口协议不发生变化,调用了该服务的其余服务都不须要变动,保护起来十分的不便;
- 服务降级成本低且危险可控,不论依赖了该服务的零碎有多少,咱们只须要解决好这一个服务的降级,开发保护降级老本、测试验证的老本及运维的老本绝对组件化来说都极大的升高,危险也小,在当初各类 jar 包平安问题频发须要及时降级修复的情景下,服务化的劣势显得更为显著。
3.2 服务化存在的劣势
- 服务性能绝对组件化来说较差一些,服务化拆分的越多,服务之间的互相调用越简单,调用链路也会变的更长,服务之间的网络申请调用越多性能越差;
- 服务化后多服务多节点部署,会带来一些人造的分布式系统固有的问题,比方一致性、分布式事务处理等,另外就是节点变多、服务链路变长带来的服务整体稳定性降落问题等;
- 服务化后会减少更多的服务器资源老本,在服务调用链路上每独立化部署一个服务,为了确保服务性能,对应的就会减少原有服务相应的机器资源数量或者更多,服务拆分越细老本越高;
3.3 服务化实用的场景
那么哪些场景适宜应用服务化的形式来部署呢?合乎以下场景特点的倡议应用服务化的形式:
- 针对本人零碎外部的一些公共功能模块,如果波及到了数据库层面的资源调用,倡议应用服务化的形式提供,防止所有依赖该公共功能模块的服务都要配置保护对应的数据库资源信息,前面保护起来会十分苦楚,比方数据库变更、机房迁徙等;
- 针对内部的零碎服务调用,如果有很多外部零碎都对外部服务有依赖,然而服务并发量较小对性能要求不高,服务调用链路变长影响也不大,对并发量和性能要求不高的业务通顺也不须要太多的服务器资源,这种状况下倡议把对外部零碎接口调用封装成独立的服务,当对外部零碎调用逻辑发生变化或相干 jar 包降级场景下咱们只须要降级这一个服务,不须要本人零碎外部所有相干服务都降级。
3.4 服务化应用案例
案例一
零碎外部公共功能模块服务化的案例,利用商店各个模块在返回信息给客户端之前常常会有一些公共的过滤逻辑,而这些公共过滤逻辑的解决还波及到跟 mysql 及 redis 进行交互,因而把这些公共过滤逻辑间接独立拆分为一个独立的服务,目前该服务不仅对我的项目内提供服务,还会给公司内其余部门很多业务应用。
可能有同学会有疑难,针对用户量大,对服务并发量和性能要求较高的服务,多拆分一个服务进去解决了数据资源隔离的问题,然而如何解决服务调用链路变长导致性能降落的问题,比方上文提到的那个经营资源组件化的背面案例(示例图 6),针对这种咱们能够通过在调用方减少缓存的形式来解决性能问题,因为这个业务场景对数据的实时性要求并不高。
可能有同学会有疑难,针对用户量大,对服务并发量和性能要求较高的服务,多拆分一个服务进去解决了数据资源隔离的问题,然而如何解决服务调用链路变长导致性能降落的问题,比方上文提到的那个经营资源组件化的背面案例(示例图 6),针对这种咱们能够通过在调用方减少缓存的形式来解决性能问题,因为这个业务场景对数据的实时性要求并不高。
案例二
内部零碎服务调用服务化案例,咱们有一个开放平台零碎,该零碎次要是服务于开发者,对系统的性能要求不高,其中有一个需要波及到内部零碎服务调用,且开放平台零碎内有多个工程都须要调用该内部零碎服务,为了便于后续的服务保护和降级,就把对外部零碎服务的调用逻辑对立封装到了一个专门用于内部零碎调用的外部服务里,而后通过该外部服务来调用内部零碎。
四、总结
总结下组件化和服务化各自优劣:
综上所述,组件化跟服务化两种形式没有相对的好坏,各有优劣,具体该应用哪一种形式跟咱们的实在的问题场景有关系,大家能够参考以上的剖析,联合本人的理论我的项目状况去抉择合乎本人的形式,技术最终是要服务于业务,大多数状况下没有最完满的解决方案,只有最适宜的解决方案。
作者:Yao Wenyu