大话解析微服务架构痛点(一)- 跨服务查询的实现方式和问题分析
提到微服务,必然会提到DDD领域设计,DDD思想下最大的问题是如何在项目中实践,因为真实世界的业务都是牵连着多个业务领域的,而技术上把应用系统按广义DDD思想划分为一个个独立领域服务分而治之后,如何既保持其独立性,又建立好关系机制,让服务之间协同完成一项项实际业务事务,是微服务技术落地要面临的挑战,所以本文讨论的主题,便是这些挑战的一个痛点表现面。
下面我们用一个通俗的开会场景案例来展开讨论。假设,一个电商公司起初只有一个总部部门,部门人员都在一个楼层办公,老板想开会只需要站起来吼一声去X会议室,相关人员就会快速到位。后来公司壮大,拆分成三个部门,人员分别在另外三个层楼办公,部门A负责客户领域业务,部门B负责商品领域业务,部门C负责订单领域业务。老板在总部又想开会,并且这次开会主题是了解公司订单业绩,同时想了解订单的客户在全国的分布情况,也想了解订单的商品都有哪些供应商,看看这些供应商还有哪些优质商品可拿来加强推广。这时老板站起来吼是没用了,那打电话吧,此时本文研究的问题出现了,老板陷入了深深的沉思中:是分别打给三个部门的负责人,还是只打给一个部门负责人请他再打电话给另外两个?甚至还有没有其他方式来组织会议?比如发个朋友圈吐槽一下销量,部门C的老大看到后是不是会自觉发起会议?思考的深入点,如何让往后开会通知更高效?思考的再深入点,每次会议讨论主题所需的基础商业信息如何获取的更高效?老板默默的泡上一壶茶,意识到这问题本质上是个部门职能边界划分和部门协同机制的问题。
公司没壮大前,就像在传统单体架构系统里,使用数据库联表查询技术(站起来吼),很方便的就解决了开会通知和收集信息问题,但在微服务架构系统里,因为各领域数据库是分开的(商业信息在不同楼层部门里),应用系统实现此案例场景功能,就遇到了跨服务查询(多部门会议),需要使用API技术(打电话)或MQ技术(发朋友圈)来解决,本文先把老板打电话通知和收集信息的这一套操作,归为分开查询和集中查询两个策略来分析,姑且设定组织会议过程的职责在总部老板这,老板勤快的打起了召集部门人员去X会议室参会的电话。
第一部分
一、分开查询策略
思路:老板先打电话给部门C,询问到订单信息后,根据订单信息里带有的客户信息打电话给部门A找该客户的客户经理,再根据订单信息里带有的商品信息打电话给部门B找该商品的供应商经理,这样就能把所有相关人员召集起来参会。对应技术上就是基于主领域服务查询到的数据,再去查询其他关联领域数据。实践起来的方式又有如下几种:
1、同步循环查询方式
老板在打完部门C的电话拿到所有订单信息后,按照订单列表顺序,每看一条订单信息就打一次电话给部门A和部门B。
2、同步批量查询方式
老板在打完部门C的电话拿到所有订单信息后,先把所有客户和商品信息梳理出来,再一次性打电话给部门A和部门B,避免了多次打电话,为公司节省了话费,对应技术上是避免了网络请求的性能损耗,都节省了时间成本。
3、异步查询方式
老板在打完部门C的电话拿到所有订单信息后,不论是一条条打电话还是批量打一个电话给部门A/B,都是在电话里把要查询的信息要求说完就挂,而不是一直拿着电话在那傻等着,尤其是批量查询时部门A、B内部要查询很久的信息,这时老板可以先去做点别的事情,等对方有结果后再回电话给老板。在技术上,这是微服务架构的擅长项,按需增加服务实例(部门A/B接电话的人),搭配合适的负载均衡算法(如何轮流接电话的规则),可实现横向拓展系统承载能力,理论上只需要等待其中最长的一个服务端查询耗时就能得到所有结果,体现出微服务架构的优势,这也是为什么成熟RPC框架(电话机)都有异步通讯(来电回call)能力支持的原因。
分开查询策略的业务痛点:不论批量还是异步查询方式,也都是在解决查询效率问题。一旦遇到复杂点的业务需求,比如老板临时起意,只想研究最近1个月和客服咨询过的客户订单,而这些客户信息只有部门A的客服小王知道,那在部门C查询订单的时候,肯定会先得到包含有其他客户的订单,等到部门A返回结果时才知道要剔除哪些订单信息,由于分开查询的部分信息后置,导致老板在拿到部门A的信息后,还要回头对部门C的信息进行多次处理,也会枉费前面为了批量查询做的部分梳理工作,订单量越多,老板越发疲累懊恼,最后可能就精神崩溃放弃开会了。对应技术上,是带条件查询分页的需求,而查询条件又涉及到周边领域内部筛选时,突显出主领域数据过滤困难的问题,开发成本陡增,相当于要技术人员手工编码实现传统关系型数据库的join功能(之前一个楼层时员工可口头快速沟通)。还有一种极端方式,在某个服务上直连所有需要的领域数据库来查询(老板直接跑到A/B部门自己查),比如使用Mycat中间件来支持(请个专人跑腿),依靠底层数据库技术来解决,有点在分开查询方式上一条路走到黑的意思,不符合微服务思想倡导的趋势。但也绝不是说分开查询就没有用武之处,还是要看业务场景,在没有分散条件检索的场景下,只是聚合多个领域的数据,还是比较首选的方案,尤其配合上异步机制,特别适合像“首页”这种场景使用。
第二部分
二、集中查询策略
思路:经过上次会议的教训,老板痛定思痛,既然会议还是要经常开的,而且老板文思泉涌,常常按奈不住内心的小宇宙,总这样折腾自己也不是办法,干脆要求各部门负责人时刻提前准备好开会信息,而且今后老板只想打一个部门电话即可召集好参会人员。对应技术上,便是主领域服务端把周边领域的所需查询数据想办法先集中到一起,客户端来请求只要在一处查询。实践起来的方式又有如下几种:
1、冗余方式
这次部门A/B/C负责人坐在一起互相商量起来,既然老板提了要求,那必须满足,部门C负责人先说了话:“之前这种会议老板每次都是先打我电话,干脆你们把老板要求的信息都给我吧,当然,我也不是什么都要,像部门A客服小王知道的最近咨询过的客户信息点我肯定需要的,这样我内部查订单就直接筛选了。至于客户的兴趣爱好、在系统上泡了多久,又和其他客户聊了啥我就不关心了,除非老板又想到了啥,到时再加吧!另外,部门B的供应商信息和畅销品清单也给我一份,至于供应商的七大姑八大姨信息,老板开会从没问过,我就不要了。”,在技术上,便是在主领域服务中,冗余存储业务需要的周边领域数据。
2、视图表方式
这时,部门A负责人说话了:“除了客户下单时的咨询信息点要给你,还有每次客服小王接到新咨询客户时,都要跑你那告诉你增加,万一老板下次先打电话给部门B 呢,同样的信息点还得给部门B一份,干脆我们找一个资料室,把老板开会提到的信息都整理成册放进去,有更新了就去资料室修改,到时老板不论打给谁,都去资料室查。”,在技术上,便是将主领域数据和周边领域数据汇总到一个备份视图表,提供统一查询。
3、缓存方式
这下部门B负责人坐不住了,急忙开口说:“这你们是方便了,但毕竟老板关心的客户咨询客服的信息和我没有直接关系,老板肯定大多不会第一时间想到我,我却要专门有个人来关注客服咨询的情况,这要是以后老板还要筛选客户兴趣、七大姑八大姨关系的,我这也太浪费人力了。听说,老板那来了个秘书,要不我们把资料都放她那吧,她位置靠老板那么近,老板一喊开会,她那啥信息都有,那效率多高。”,这时,老板不知道什么时候来了会议室,正好听见这话,气不打一处来:“我这好不容易招个机灵点的秘书,帮我平时打点着紧急重要的事,给你们这一整,那人家还能干下去吗?就秘书那巴掌大的地方,你们这资料多了还不把人家埋里面。”,在技术上,便是将主领域数据和周边领域数据汇总到一个缓存中间件上,比如Redis,提供统一查询,但这种方式实在偏离了缓存的核心职责,缓存的主责是为了解决数据处理器之间处理速度不匹配问题、或多个处理器共享读取高频数据的提效问题等,所以业界的缓存技术产品很少对类似关系型查询操作有很丰富的支持。
4、搜索引擎方式
老板说完看了看大家,恢复了以往稳重大气的神态,慢悠悠端坐了下来:“这样吧,这事我替你们想好了,前两天我去市里图书馆看望老馆长,正巧听说他们有个秦老师傅快退休了,人特别精神且身体硬朗,我专门请了他来帮忙,人家是老司机,有多年查找资料的经验,你们往后把资料整理好都送他那去,客服小王有接到新的咨询,把客户信息也直接去告知秦老师傅,我呢以后啊先给他打电话,这样你们就解脱了!”,在技术上,便是将主领域数据和周边领域数据汇总到专门的搜索引擎来提供统一查询服务,专业的搜索引擎除了能支持传统关系型数据查询能力,还有一些特别能力,比如语义化查询、关联性排序等,也能有较好的查询性能,只是内部逻辑较复杂,维护和用好它的开发人员需要有较高的专项技术要求。这应该是一种比较终极的解决方案了,搜索引擎的产生就是为了解决数据聚合查询问题,但到底要放哪些数据,数据怎么投放和更新,既要满足业务使用性要求,也要尽量节约存储成本,还要能快速水平拓展承载能力,支持好业务发展,这是一个平衡问题。
集中查询策略的业务痛点:不论哪种方式,都存在一定的数据同步延迟问题,比如客户赵先生先下了笔订单,订单也被整理送到了资料室,但随后赵先生咨询了客服小王,小王还没来及和秦老师傅告知这个信息,这时老板喊开会,那这个订单就会被秦老师傅遗漏,相关的客户经理和供应商经理也没能被召集到会议上。所以在数据同步的方式实现上对开发人员有较高的业务要求和技术挑战,一般只要不影响业务做重要决策,常规性会说服业务接受一点点小的时间段误差,但在一些确实需要数据高实时性一致要求的场景下,需要专门独立部署定制化服务,这样的服务往往只能提供给一些相对小众客户使用。
从技术角度总结一下:业务微服务化后,跨服务查询面临2大难题,一是数据聚合效率问题,二是数据关联筛选问题;为了解决后者,又引入了数据冗余的一致性问题,但采用集中查询策略能更具性价比的满足业务的复杂需求。
在微服务架构下,我们都希望根据不同的业务场景和所处时期,选择最合适业务使用的跨服务查询方式,而实际系统直接开发人员的业务经验不一,所以不能完全把技术方案选择权都交给直接开发者自由发挥,否则系统的查询能力实现的好坏就完全依赖个人判断。一个人的力量都是有限的,理论上可以尝试寻找和不断沉淀,把以往业务问题解决方案的技术手段,通过实践完善总结为一种整体模式,将其落地为一个有各种业务套路的开发框架,来统一规范应对以上业务场景挑战,尽量跳出对个体开发者能力的依赖,让技术解决技术的问题,DDD思想下,还有一些落地方法论如CQRS就有另一思路来解决本文讨论的问题。后续有机会,将会逐步尽个人所理解,和大家一起讨论这样理论的业务技术框架可能的实现方式,以及微服务框架下的其他痛点问题。因个人能力有限,文有不当之处敬请斧正。