[Yelp] how to enrich search result | service 之间的关系


在yelp high level design中,service之间是否有互相调用的关系?
比如说这样的需求, 搜索结果会包含商家列表,每个商家会有图片,rating, 地址, 距离
想到两种方案

  1. client端从search service 拿回搜索结果,然后client再发出请求分别去business profile service, business media service, review service拿到信息来enrich 搜索结果
  2. client端只调用一次search service,由search service 来调用其他service来enrich搜索结果,一起返回给client端

请问high level design表达的是哪一种方案?个人觉得第二种方案有更好的user experience, 不需要多个request 让用户等待
如果第二种方案是业内常用方案,是否需要将service调用关系体现在high level graph中?
从架构角度,是否需要在client和现有具体service 之间增加一层service作为orchestration layer用来统筹多个service的调用关系与结果?比如对于问题中的需求。

如果有这种需求的话,第二种方案更好,体现在图里的话,Search Service 需要连到 Business Profile,Business Media Service。

我觉得不需要额外的 orchestration layer,每个服务会自己根据需要去 call 其他服务的 API。你说的统筹所有服务的服务原则上在 microservice architecture 里不合适的,每个子服务需要做到相对独立,就需要有自由去自行 evolve。
当然这样也不是没有问题的,会造成服务与服务之间的关系特别乱,服务总数特别多,全局观难以建立。这类问题是 service discovery 的问题,可以用专门的工具去把关系盘清楚,生成个图出来。

1赞

我不太同意,第一个方案感觉更好,第二个方案要求一个服务必须等待其他服务返回才能返回给用户,如果这里下游服务down了那这个服务就没法返回了,而且这增加了服务之间的依赖。相比之下第一种虽然要求客户端进行多个request,但是并不会有体验问题,客户端可以做到局部页面生成,每个request只有返回回来以后才生出那部分信息,没返回的话就现实局部等待动画就行了。

这样做的前提是能够做局部页面生成,在搜索场景下面,比如 Google Search,我不认为有必要去分步生成内容,也没见过页面一部分在继续等待数据的情况。我不觉得从 business media service profile service 拿 URL 会有很大的延迟,我倾向于一次性准备好数据一起给客户端。其中的具体图片会再通过 URL 单独 make request 去拿。

如果客户端需要等待第一个的结果再去请求剩下的,那确实不合适这样做。但是如果api设计的可以返回足够信息,客户端可以同时请求这些Api,然后在客户端进行组合,这也是一个方案。在这个场景下,我还是倾向减少后端服务互相调用,我认为更好的方法是把需要的额外信息提前存到searchService的数据库里,这样没有依赖关系。数据同步可以通过integration event异步进行

我明白你的意思。Search Result 如果可以分成核心信息和辅助信息的话,辅助信息不需要在 critical path 上,这是合理的。我们观点的区别在于我觉得所有的 business 照片都是核心信息,没有的话页面就没意义,而你觉得可以晚一步拿到不影响体验。这点可以具体看需求决定。

这样的 denormalization 优化了延迟,但增加了数据库间的关系,两个数据的 data model 就不容易各自改动了,我觉得还是弊大于利。这里不用搞这么复杂。

denormalization/data replication这个方案确实是增加了复杂度来换取低延迟。不过为什么增加了数据库间关系?他们还是各自管理数据库,只要Event的格式不变就行。这跟Api call差不多,只不过提前异步进行,并把结果提前存到数据库里了,比如有新的review,reviewservice发一个reviewPublished event 到message
broker, 其它服务把自己需要的部分存在自己数据库里,比如Search Service可以存一个title和id之类的

这样还有一个好处就是减少服务之前的依赖,增加了availability,每个服务都可以独立运行,不会因为别的服务down了就没法继续了。

这个方案可能在这个场景不太合适,具体需求看吧。如果系统里已经有了类似的代码,开发起来不难,设计上会复杂一些。

讨论一下挺好的))

用 message queue 做中转就不会增加 dependency。我本来理解你的意思是在 DB 之间直接 stream data。