Chat三人行之微服务怎么玩

SUNSKY 发表于 2020/02/13 14:57:56 2020/02/13
【摘要】 2017年3月6日周一晚8点半,进行了以“微服务化实战案例分析”为主题的交流活动。本场Chat由庄表伟提供实际案例,由王渊命、肖德时、陈皓(左耳朵)共同分析、诊断,希望能够通过更加贴近实际的讨论,给大家带来更多的启发。以下是主持人赫阳整理的实录,记录下了问答的精彩片段。「Chat三人行」是GitChat推出的特色栏目,旨在融合各路专家的不同视角,让思想的碰撞为读者点燃智慧的火花。(本栏目得名...

2017年3月6日周一晚8点半,进行了以“微服务化实战案例分析”为主题的交流活动。本场Chat由庄表伟提供实际案例,由王渊命、肖德时、陈皓(左耳朵)共同分析、诊断,希望能够通过更加贴近实际的讨论,给大家带来更多的启发。以下是主持人赫阳整理的实录,记录下了问答的精彩片段。

「Chat三人行」是GitChat推出的特色栏目,旨在融合各路专家的不同视角,让思想的碰撞为读者点燃智慧的火花。(本栏目得名于“三人行,必有我师”,每期Chat的作者人数皆为两人以上。


分享人简介

  • 庄表伟,华为公司内源社区平台架构师,开源社理事。

  • 王渊命,QingCloud 容器平台负责人,前新浪微博架构师。

  • 肖德时,曾任Redhat Engineering Service部门内部工具组Team Leader,是国内第一代 Docker 代码贡献者。

  • 陈皓(@左耳朵耗子),前阿里和亚马逊的技术主管。GitChat技术顾问,本场Chat特约嘉宾。

案例背景

庄表伟:这个案例,是我在工作中遇到的具体的问题,我们在公司里,需要建设一个内部的“开源社区”,大家可以理解为一个面向华为内部员工共同使用的Github。从2013年底开始建设,到现在3年多的时间。在当时,我们能够选择的基础平台,其实非常有限,最合适的,也就是Gitlab的开源版本。至于后来出现的Go的Gogs、PHP的Phabricator,当时都还没有,再加上我对Ruby也比较熟悉,就自然选择了Gitlab。而Gitlab,是一个Rails的项目,因此我们的平台,原生就是带着Rails基因的。

华为目前的研发人员,超过8万人,另外还有数量非常多的外包团队,因此,要提供一个足够供他们使用的平台,分布式架构是一个必然的选择。随着Docker与微服务技术的逐渐成熟,对于Gitlab的微服务架构改造,也就成为我们思考的重要问题。

这是目前Gitlab的架构图,不过我们在对Gitlab做二次开发的时候,还没有Gitay这个组件。另外数据库,用的也不是PostgreSQL,而是MySQL。

另外,https://gitlab.com/gitlab-org/gitlab-ce/blob/master/db/schema.rb 这个目前Gitlab的表结构,一共有78张表。我们在后续的开发过程中,添加了不少,目前还在做梳理,大致上会保留103张表。

目前对于数据库中表的分类主要包括:

  • Platform:平台的大多数其他表。

  • Project:与组织、项目相关的所有信息,这一类下面还有2个子类:

    • Code:与代码相关的各种信息。

    • Issue:与Issue相关的各种信息。

另外我们的扩展还包括一些表:

  • Group: 与讨论组相关的各种表。

  • Social:与社交行为相关的各种表。

所以,初步的想法是从大的平台中,分离出:Project、Group、Social三类服务,剩下的留着不动。


问:监控系统如何监控自己?如果监控自己都没有很好的运作,那么当我们谈到调用链监控的时候是不是存在不确定性?

肖德时: 这是用健康检查机制来保证的,坏了会报警。

王渊命:监控与报警系统其实一般是两个系统,报警系统依赖于健康检查以及监控系统的输出的数值。监控系统不正常工作,顶多是发现问题的时候排查诊断有一定困难,但没监控系统你还是要能人肉排查的吧。

庄表伟:我也想说说我的理解:监控也是分层次的,不同层次的监控,是逐级往上监控的。对于最基础的监控:比如机房是不是有电,这个也需要,而且一定得靠不是互联网的手段来报警。

我还有一个联想:在分布式系统中,多个实例的选举机制。也是互相监控的情况。


问:阿里云推出了容器服务,采用他们容器服务是不是会降低微服务的门槛?

肖德时: 我认为不会。微服务的设计和部署都很重要,但是架构设计更能体现价值。

王渊命:我觉得直接使用容器服务可以降低容器服务本身的维护门槛,但容器只涉及微服务的运维管理问题,至于如何架构,如何拆分,服务如何治理,还是有很多门槛的。

庄表伟:其实,我倒是想提一个类似的问题:比如完全用docker原生的技术,还是用kubernets的平台,是不是会降低微服务化改造的难度?

陈皓:容器平台不会降低门槛,因为微服务的重点不在PaaS,而是在自己怎么拆分自己的业务,还有自己业务的架构。微服务更多说的是业务架构、业务应用生命周期的调度和业务应用间的关系。打个比方:微服务是汽车,容器平台是公路,公路是让汽车跑得更好,但公路再好不会降低汽车的生产门槛。:)

王渊命:我是比较看好容器平台对微服务的支持的,只是现在容器平台上层的工具链还不够成熟。比如服务治理,监控,以及服务注册,这些都可以让渡给容器平台的。

肖德时:解偶过程有什么经典坑,有这么一个,就是一个服务启动后依靠多个其他子服务。

陈皓:根据程序的本质:程序 = 控制Control + 逻辑 Logic这个Principle来看,所谓控制,就是我们程序对数据和流程的控制(比如:分布式、并行等),逻辑就是业务逻辑,Control是程序复杂度的下限,而Logic是程序复杂度的上限。就是说,如果业务逻辑本身就复杂,我们是无法通过程序的手段降低复杂度的。Docker和K8S就是控制,而业务逻辑才是整个系统复杂度的根源。我们经常把控制和逻辑混在一块,导致程序或架构更加的混乱和复杂。


问:微服务化之后,系统管理后台和app使用的微服务的业务代码需不需要分开实现。gateway需不需要分开?

王渊命:你的这个gateway是API gateway么?这个肯定要分开的吧。但管理后台,一种是直接用业务代码的API,好处是只维护一套API,一套业务逻辑,缺点是需要给管理后台做许多专门的API。

如果管理后台单独实现,直接操作数据库,这种是比较方便,但缺点是以后数据库升级就比较麻烦,缓存相关的处理也比较麻烦。如果团队大了,最终会切换到前面那种方式。

提问者:是API gateway。

王渊命:还有一种办法是管理后台的读操作直接读取一个从库,但写操作需要通过业务api。这种管理后台开发人员的灵活性比较高,可随意定制,也一定程度考虑到了数据一致性问题。

庄表伟:这种搞法,似乎更累啊。

陈皓:个人觉得:不管是不是微服务,管理后台都是要和用户的业务分开的,从安全的考虑也应该是这样的。


问:但是如果把管理后台和app的功能放到一起,权限方面怎么控制,系统用户和会员是放到一起,还是分开设计?因为我们做的都是一些传统应用。

庄表伟:嗯,是说最后一种。

王渊命:我觉得他问的是API层,这个其实挺矛盾的。比如 user service,同时也给管理后台输出接口么?这个我觉得应该按照API认证和权限机制来控制。

庄表伟:在我们的系统里,管理后台的任务,还不算繁重,所以并没有特别的处理。但是,如果有非常多的管理、配置、权限之类的逻辑,似乎独立一个管理服务,会更加妥当些。但是,这个管理的服务,应该会调用其他业务的API,而不是搞读写分离吧。

陈皓:从业务和安全的角度来讲,像权限比较大的专人使用的API,是另一个网关。

王渊命:没办法,管理后台的需求变化非常大,如果全部要业务团队来输出api,会比较累,时间上也会有问题。所以直接给个从库搞也是一种妥协的办法。我是按照互联网应用的需求来分析的。

陈皓:我觉得不要把什么事都往微服务上来靠,微服务不核心,只是一个手段,核心是业务。所以,还是要从业务上来挑选不同的手段。

庄表伟:我插一句,聊聊我们的系统的思考。基本上,我是打算,把能分的分出去。剩下的还是都放在一起。而且,之前肖德时提到的判断标准,我觉得很有道理:有横向扩展压力的业务,才需要拆分出去,作为微服务。

王渊命:没有完美的方案,要根据业务阶段选择。比如当前业务紧张,用户需求开发团队都忙不过来,管理后台的需求就耽搁了,但有些管理后台的需求又是运营团队和管理团队必须的(比如内容审核 等等)。这时候就只能用一些妥协的,可能违反设计原则的办法了。


问:商城一般后台有系统用户管理,会员管理,商品分类,商品管理,订单管理等。商城的商品管理和订单处理引擎之间的关系?

王渊命:我理解你的意思是,比如我们用了 用户和订单微服务,这个是直接面向最终用户的api,输出给web和app,这时候管理后台需要管理用户以及订单,这部分接口和用户的接口有部分重复,但也有一部分转有的,这部分应该放在 用户和订单的微服务里,还是单独搞管理后台的微服务,是否共享数据库。我前面的回答都是按照这个理解回答的。


问:我的问题主要是后台这部分功能,在微服务里面应该怎么放,是合在一起,还是分开,如果合在一起,那么api 网关应不应该合在一起还是分开。因为我看了很多微服务的分析架构,但是都没有讲到管理后台这么分怎么开发。

陈皓:我们先不说微服务,我们先说SOA,对于电商这样的平台,服务也需要分层次,有后端服务(如:数据model层的),也有中台服务(如:业务和技术中间件),还有前端服务(提供给用户的服务),对于这三个层次,后端和中台的是可以共享的,前端的建议分开,gateway也应该分开。

商城的商品管理和订单处理,这应该是两个业务,我不知道你说的关系具体是什么,能具体说一下吗?


问:商品与订单流程引擎看上去是分开的模块,但在运行时是紧密相关的,比如订单处理过程经常要读到商品的各种特殊属性来做不同的逻辑,所以修改商品处理流程实际上需要同时修改商品管理模块的流程管理模块,那么多次修改之后非常容易让两个模块之间偶合得很紧,那么当初解偶到微服务的意义 就大减,那么怎么去避免这种偶合问题?

陈皓: 按我的理解,一旦订单下了,应该对下单的商品做一个“小快照”和reference,因为商品的信息可能会经常变化的,所以,一些和订单的相关的数据必需要下单时持久化在订单内(比如:价格、折扣、商品的基本信息和基本属性,等等),这主要是怕用户下单时和之后的商品数据变化产生不一致的情况,所以需要把相关数据冗余到订单上来。当然,订单中心也需要反向查一些商品的信息,但是从业务上来说,这样的情况一般来说是对不影响订单的状态的,所以,从业务上来说,这应该是一个从业务上来说就是松耦合的两个系统。所以,其实这个还是业务问题,这就是微服务最难的地方——业务分析能力。

提问者:以我的理解,管理后台这么错综复杂的东西,如果业务量不是特别巨大,那么只需要把数据库、缓存、消息队列等基础服务分出去,如果某个无状态的API业务量巨大,那么就应该把它单独分出来能横向扩展。

陈皓:你说的是技术中间件,还有业务中间件,也是可以共享的(比如:权限中心、短信中心、支付服务之类的)。

肖德时:商城一般后台有系统用户管理,会员管理,商品分类,商品管理,订单管理等。我见过的大多数就是单体应用来支撑就够了。没有流量。落数据库就可以了。


问:微服务接口的版本如何控制冗余比较好?比如有接口需要升级,但又要考虑对老接口调用的兼容,代码层面如何实现或部署比较好,有没有什么标准规则?

肖德时:微服务的网关做路由到新旧两个版本的实例上。

庄表伟:关于这个问题,我先抛个砖,这种情况,不是一般都是在API里,加上v1,v2这样的路径,就可以了吗?

王渊命:这种方式新版本的接口其实相当于一个新接口,对老接口完全没影响。但这种做法也有成本,就是版本不好控制,有的接口新老版本是一样的,有的是不一样的。某一个接口需要升级新版本的时候,其他接口怎么办?在网关层路由到旧接口?

我觉得大多数情况下,接口的参数以及返回值变动都不应该作为新版本,一般在代码层作为兼容,除非有非常大的变更,需要完全重新设计API。

庄表伟:我觉得,你调用一个接口,就存在一种依赖。无论怎么处理,依赖总是个麻烦。所以:把麻烦显式的暴露出来,还更好一些。(所以v1,v2就不错)

陈皓:关于微服务接口的版本兼容,无论有没有微服务都是需要考虑的。这个可以学习一下各个公司的API设计的方式和维护的经验,google一下也有很多相关的规范文章。


问:微服务中所有前后端交互是否都要走API gateway?

肖德时:可以走,也可以不走。看你的数据流向。开始的时候,你可以全部放到API Gateway。

王渊命:我个人认为 api gateway 是对外输出的,服务之间可以直接通过服务发现互通。


问:微服务之间是否会存在依赖关系?如何管理?

肖德时:有API联动就有依赖,这个依赖是一种病毒。一定要优化避免。

王渊命:会有依赖关系,我文中建议的方式是进行依赖分层,避免依赖循环。复杂情况下,你可能需要一个聚合层来聚合各服务的api数据然后组装成最终对外输出的结果。

陈皓:关于依赖关系,有很多pattern可以解开依赖,一种是IoC/DIP的设计思路,变业务间的依整为所有的服务都依整一个统一的协议。比如一个Pub/Sub的消息/数据总线(当然,这是依赖变得复杂时的玩法)。


问:关于依赖我有个简单例子,比如发送手机验证码修改密码,修改密码这个服务我请求后,必定会联动后面的短信网关服务,发送验证码到用户手机上,然后让用户完成修改密码这个操作。当然这只是一个例子,碰到这种业务,如何避免依赖调用?

王渊命: 你的这种依赖是正常的啊。不然要微服务何用。

肖德时:我所说的依赖是你的API服务,因为其他子API,变的不可用了。我所说的依赖是你的API服务,因为其他子API,变的不可用了。因为微服务下,很难调试。当你有几十个微服务的情况下,调用链条就多了很多,你无法快速定位。所以,从API的单一原则来讲,必须保障API的服务的可用性。

王渊命:依赖一个是要有跟踪机制,另外一个是避免循环依赖。

提问者:有zipkin就可以,可惜不是dubbo里的,springcloud提供的。

肖德时:zipkin是工具,但是不是灵丹妙药,一定要保持简单原则。

王渊命:服务多了,很容易循环依赖,不小心一个调用,就相当于内网 ddos了。

陈皓: 发短信这个服务是个无状态的服务,也就是一个什么都不知道的,别人让我干啥我就干啥的服务。而发验证码这个事,是用户认证系统要干的事,也就是说,用户认证系统生成验证码,然后调用“发验证码服务”,而“发验证码服务”会调用更为公用的的“发邮箱服务”或“发短信服务”。这也是一种解耦的方式“依整于接口而不是实现” (接口其实就是一种协议)。


问:赞同在对于API和WEB的拆分时,model层单独抽成服务,不过对于这种服务该怎么去建设呢,是对其他服务提供API调用还是其它的,这一块的扩展该怎么考虑?

王渊命:model层不应该算单独的服务吧,应该是一个 lib 由其他服务依赖吧?model其实可以理解成服务之间的数据传输的 schema。用 protocolbuffer 定义然后各服务自己生成也一样吧。


问:器编排系统开放给应用开发人员使用时,️比较成熟的权限管理方案吗?Gitlab后端采用的网络文件系统选型时有考虑过glusterfs吗?为什么最终采用了nfs呢?优秀实践能稍展开分享下吗?

肖德时:这个问题好几个串起来,我回答容器编排加权限,这块目前都是自研的。用成熟的方案就可以,比如Django。

庄表伟:分2个部分。第一个部分关于权限的,我也想了解。先回答后一个部分。因为git是一个配置库,如果有些文件缺失,会导致整个配置库的数据错误。不像普通的分布式文件系统。我们可以等等,晚点再看。所以,git的配置文件的同步,我们现在就是使用git自己的同步协议。因此,想来想去,没法用现成的分布式文件系统。


问:对于服务间的通信请问应基于哪些考虑来选择REST还是rpc,且服务间的通信需要考虑哪些安全信息?

王渊命:我觉得有几个考量标准:

  • qps以及接口输出,如果非常大的量级,rpc还是有优势的。

  • 开发语言,如果开发语言有不支持 rpc 的,只好用 REST 了。

另外 rpc 库一般都支持服务发现中心,直接通过 smartclient 模式互相直接连接,以及进行流量切换,REST 一般还是需要个 lb来做这个事情。

肖德时:restful可以,遇到性能问题在rpc,内部数据调用用rpc合适,但是年轻程序员不一定能搞定protobuf之类,还是用httprestful.可以。安全,有jwt之类,很多方案,没有什么特别的。

陈皓:任何事情都是trade off, RPC有很多问题,且不利用服务的各种调度。但是RPC可以提高性能,所以,建议使用RPC时,最好不要使用很长很长的链接,而且需要使用一个RPC的中件间或proxy。


问:想请问一下,什么的样的场景适合微服务?大家的判定标准是什么?

肖德时:分布式场景下才会有这个问题,比如我做的容器云平台,底下是分布式系统,所以我就利用这个微服务加快构建体系。这个叫因地制宜。还有一种是当单体业务或者SOA的业务依赖太重了。期望加快一个单体应用中的一个功能的水平扩展的时候,就可以考虑加入微服务模块。

王渊命:一般是纵向伸缩出现瓶颈的时候才需要微服务化。还一个笑话说,如果你的几个团队互相看不上,你就得拆成微服务了,也就是团队协作原因。


问:现在Docker只是让部署更快吧?和解偶没关系,那么解偶过程有什么经典坑可以分享一下?

陈皓:Docker的强项除了环境部署,环境隔离,还有集群调度(自动化调度的前提是自动化部署),Docker和业务解耦没什么关系。业务解耦好处很多,我做业务这么多年,解耦最大的坑就是“程序控制逻辑会比较复杂,尤其是业务的流转状态”,我看到很多公司都把一个订单的状态机放到了各种不同的模块里去,结果每个模堆块维护整个状态机的一部分,最终导致状态混乱,各种bug和问题,这应该是最大的一个问题。要解决这个问题,其实是另一个话题了,可以放在以后的chat中讲。


问:如何来设计微服务之间的访问和通信是采用同步还是异步的原则,同步和异步访问有比较好的介质么(中间件)?

王渊命:同步模型就是通用的 rpc/rest模式,异步模型一般是 actor 模型。有许多现成的框架。

庄表伟:关于同步、异步的理解:“如果没有实时的业务压力,能够异步的就异步”,我这样说对吗?

提问者:我觉得非必要,不要搞太多异步的,异步带来出错难跟踪,就这一个问题就可以搞死人。

王渊命:除非有好的 actor 框架把复杂度屏蔽了。

庄表伟:嗯,我也是抛一个观点来大家聊:假设已经有一个很稳定的消息队列+任务总线呢?是不是会更加自然的把任务丢到异步的队列里去?

提问者:现代系统本身都是消费者远多于CPU数量的,异步带来消费者不需要等待,但worker线程这个最费资源的单点没解放出来。除非是用户不想等待,否则不要经常引入异步机制。

肖德时:假设已经有一个很稳定的消息队列+任务总线呢?是不是会更加自然的把任务丢到异步的队列里去? 肯定会。银行的业务百试不爽,天天再用。因为到后端以后,银行的业务并不是高并发容量。所以不需要微服务。但是,随着互联网业务出来后,就不行了。

王渊命:异步队列这种和前面说的微服务场景不一样,异步队列这种写入就算成功了,不会等待结果。如果微服务的远程调用做成异步的,调用后,对方是要异步通知到调用方的。场景不一样。

肖德时:怎么讲,业务量真正的扩大了。异步解决不了业务上的一个完整交易。必须一次性完成。这个就瞎了。所以你会看到很多金融的业务在不断的当机中度过难关,找互联网企业找方案借鉴。


问:工作流引擎作为基础模块,应该是可以作为单独的微服务的,但相关的业务又是在另外的微服务中,但工作流流转过程中要频繁的调用业务的微服务,而业务逻辑中也有可能调用工作流的服务,这其中涉及的性能问题和事务问题如何平衡?或者说这种拆分是不是有问题?

肖德时:首先这里就是循环依赖了。微服务已经起不到效果。要保证业务逻辑的设计不要循环依赖。应该在一起的就放在一起。别搞微服务。你可能都不需要扩展实例。

假设已经有一个很稳定的消息队列+任务总线呢?是不是会更加自然的把任务丢到异步的队列里去? 肯定会。银行的业务百试不爽,天天再用。

因为到后端以后,银行的业务并不是高并发容量。所以不需要微服务。但是,随着互联网业务出来后,就不行了。 怎么讲,业务量真正的扩大了。异步解决不了业务上的一个完整交易。必须一次性完成。这个就瞎了。所以你会看到很多金融的业务在不断的当机中度过难关,找互联网企业找方案借鉴。

陈皓:正好我在Amazon工作过,Amazon是个超级喜欢Workflow的公司。Workflow的微服务的实现,可以参考Amazon在AWS上的SWF - Simple Workflow。简单来讲这个Service有如下几个组件供你参考:

1)Workflow: 这个东西就是引擎,其用来记录整个工作流当前的工作历史,并把工作流执行的历史和相当的数据上下文发送给Decider,这个组件也是无状态的。

2)Decider:这个东西分析Workflow传过来执行历史和相关的数据上下文,并根据用户定义好的流程来做出下一步应该做什么的决定,并把决定交给Workflow。

3)Worker:各种各样的干活的Worker,完全无状态。定期的以long poll的方式从workflow拉取要干的活,并回传结果。


问:有关api网关一个问题,是否除了鉴权,sso的功能也放在网关做,目前如果要支持原生app的权限,是否只能用token-base方式还是继续用传统的cookie-base方式?另外一个问题,本人一直觉得使用rpc开发微服务是种非最佳实践的方式,那么在微服务体系中是一定要有rpc,还是可以不采用?不采用的话我们该如何做?

王渊命:我觉得网关做鉴权没问题,但sso这个本身应该是个服务吧,不应该是网关的。app 一般肯定是 token 机制啊,cookie是浏览器的机制没办法,app又不受这个限制。rpc 可以看前面关于 rpc 和rest的分析吧。

陈皓:1)API的鉴权设计有很多方式,这个其实和API的设计有关系,也和安全有关,个人觉得这个话题放到未来的API设计中去吧。

2) RPC是不是微服务的最佳实践,我给两个不同的案例:Amazon内部是拒绝RPC的通通走web service,而且Amazon是喜欢pull模型而不是push模型。阿里内部是喜欢RPC的,因为需要性能,而且中间件一开始也用push模型,但后来变成了pull模型。 (我个人喜欢Amazon的方式。)

陈皓:两个小时就这样过去了。大家的问题还有很多,我们不可能回复这么多的问题。很感谢大家的问题和讨论。我也是第一次做这个事,所以,有点喧宾夺主,三位嘉宾见谅了。在这里我简单总结一下:

  • 业务上的分析和解耦能力

  • 相关的软件设计的基础

还是性能优先,还是高可用优先……这样才能设计出合理的架构(个人建议应用的拆解应该先从不同的业务分离开始,然后进化到业务中间件的出现,再到技术中间件,然后再到SOA。)只有当我们的业务架构进化到了可以微服务的时候,才能开始进入微服务的领域。


(以上内容转自GitChat,版权归GitChat所有,转载请联系GitChat,微信号:GitChat,原文:《Chat三人行之微服务怎么玩》

本文转载自异步社区。

原文链接:https://www.epubit.com/articleDetails?id=NC7E3EF931C500001A2B41C30E67215BD


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。