惟品会、滴滴、沪江架构师,关于微服务粒度、高可用、持续交互的实践分享交流(下)

架构师小组交流会:每期选择一个时下最热门的技术话题进行实践经验分享。前端

本期小组交流会邀请到了沪江黄凯、惟品会郑明华、滴滴赵伟、七牛云肖勤,对微服务粒度、高可用、持续交互展开了交流。数据库

本期接着上期惟品会、滴滴、沪江架构师,关于微服务粒度、高可用、持续交互的实践分享交流(上)进行了交流。后端

第二轮:话题交流设计模式

滴滴赵伟:在整个服务,从单体服务到微服务的演进过程中,如何去影响业务的这种正常发展?服务器

惟品会郑明华:从单体服务到微服务的改造,有两种方式,一种是小打小闹,每次稍微改一点,这个时间会很是长,有时候会发现改不动了,改的成本很是高。我举个例子,之前咱们作订单改造的时候,后来咱们怎么作呢?就是一个个来,先把物流分出去,由于物流是相对独立的。先把物流的订单拆除,怎么作呢?让物流把他的业务和数据先存到,建套模型、物流的上层业务会有另外东西就是作双写。写的时候写两边,老的订单系统写,新的订单系统也写,两个都写。双写带来的复杂度仍是挺高的。网络

滴滴赵伟:对,你的数据的一致性,一边写成功一边没写成功,这个确实是很麻烦的。架构

惟品会郑明华:咱们读的时候会有校验。写的时候是双写,但读起来会有校验,就是把新老两个地方读,而后校验。若是校验对两个数据均可以,可是若是发现不对,以老的数据为主,而且告警。负载均衡

滴滴赵伟:你怎么去判断哪一个是老的数据?好比个人隐私的操做,我下了个订单,下完订单,新系统和老系统。框架

惟品会郑明华:写的时候并无对比,可是读的时候会有对比。我举个例子,回顾一下刚才讲的那个同窗,写的时候的确是写了两套不一样的数据库。咱们对比有两种方式,一种是咱们有个 bcp 系统,两个数据都会归结到另一个地方帮你作检查,这种方式咱们不多作,全部的机器平台之外,物流系统是不作的。好比说客户在读订单,他在打订单的时候会把这两个订单都读出来,读出来接口会帮他作对比,这两个订单是否一致,若是不一致,以老接口读出来的数据为主。新的接口数据告警,要么人工参与,看问题是出如今哪里。运维

滴滴赵伟:如今运行的效果怎么样?

惟品会郑明华:这是一种传统的作法,仍是能够的。我在前公司的时候基本上是按照刚才我讲的方法解决了,并且咱们该拆的都拆了不少,物流、金融、外汇、退税、订单,基本都是按照这种模式一个个拆的。可是你说不影响业务根本是不可能的,其中人力参与对订单的拆分,对业务系统的拆分,自己参与的人力都会影响到业务系统的。还有另一种比较干脆的方式,就是作另一个系统。整个系统一旦上线之后,新的业务能在两个系统实现,直到有一天,我把老系统卸掉。

滴滴赵伟:那你牵扯到数据迁移吧?

惟品会郑明华:不管哪一种方式都会涉及到数据的迁移,一旦数据模型变化之后,都会涉及到数据的清洗迁移。若是新老两个数据模型不能兼容,数据无法迁移,数据的迁移会带来数据损失。

滴滴赵伟:那你在迁移当中你须要停服务吗?

惟品会郑明华:基本上不须要停服务,目前为止,我在阿里的时候,不会中止服务。由于新的业务都已经在设计,两边的数据都有,我把老的数据迁回来就能够了,不会影响到我真正的业务。

滴滴赵伟:咱们最先就是按微服务的架构去设计的,并无经历从单体服务到微服务的演变过程,因此我很好奇的一点,在作单体到微服务,整个过程中你以为有哪些点是你要去关注的,或者是那个地方有这种挑战性,或者那些点是必须去考虑的,或者那些是要去作好的?

惟品会郑明华:把一个大的系统拆成了多个服务,不少个服务到了数据库之后,这个分布式的问题怎么解决?这的确有考虑的问题,包括消息中间件,多个服务,每一个服务我经过消息的方式来作通信的时候,那消息的稳定性、顺序性怎么去解决,这就是从技术角度考虑的。

而后我怎么拆服务,仍是从业务角度来拆。我但愿每一个业务是自包含的,可独立部署的。好比订单的拆单和订单的寻仓,这是两个不一样的服务,而这两个服务应该彻底解耦关系,按供应商或者商户拆单,作完拆单之后,你才能把订单分发到不一样仓库里面去,这是两个前后的动做。这两个动做不该该纠缠在一块儿,这两个动做对应的是不一样服务,应该是彻底隔离开的,并且他们之间的数据库也是隔离开的。因此若是从业务角度考虑,只要业务了解深熟之后,对服务的拆分不是很大难题。

七牛肖勤:服务的分拆确定会让结构更加复杂,但微服务在理念描述上已经意识到,从服务架构着眼,设计上考虑了部署的问题,运营在架构中的优先级也是排在第一位的,而以往在设计模式、软件架构基本不会考虑到部署、运营的问题。因此,若是要支持微服务架构,必须有一套行之有效的运营、部署的工具和方式,这也是容器相关技术和容器云如今备受关注的一个缘由。

依赖的问题,包括一部分的复杂性问题,取决于拆分时候边界和接口的定义、数据联通的方式,设计得是否是足够合理,服务提供者是否是清楚需求的方式,服务调用者是否是理解接口的意图,也就是说团队针对每一个服务的沟通,对事情的定位,对接口的抽象,是否是有一个一样的认知水平,达成一个共识。只要保证接口稳定、合理,实现无论怎么变化,对整合架构就不会有负面影响。服务的局部修改反而能够更快速,由于不会涉及一个大系统的调整。

因此说,不能为了拆分而拆分,拆分的意图要准确描述问题的解决。在一个系统里面,定义接口比怎么实现更重要,不要设计很差理解、不合理的接口。

滴滴赵伟:由于我也在考虑若是让我去作单体服务到微服务,我以为监控告警必须先行,而后这种服务的降级之类的,可能要去考虑到位的。

惟品会郑明华:你说的是大的问题。若是没有很好的监控对大的互联网来讲是个灾难。

滴滴赵伟:据我所知从这种单体服务到微服务的这种转变过程中,可能像他们这种东西都是缺失的,除了这些还包括人员能力的问题。他之前作单体服务,你让他忽然转成这种微服务它可能有种不适应,包括他定位问题的这种方式转化都有些发生变化了。

惟品会郑明华:不管在阿里仍是惟品会都是有比较完善的监控。包括一旦用了咱们服务框架之后,从外部调用到咱们后台服务,到数据层的调用。每一个调动服务,包括操做都有很详细的监控,包括每个环节的耗时,它都能帮你监控出来。举个淘宝的例子,淘宝有个鹰眼系统,那个鹰眼系统就能检测到全部的电容链路。包括每一个链路的后期说话。因此淘宝也有详细的告警系统。包括流控、限流、降级,这些都有详细的方案。好比服务怎么去注册,怎么去发现,机器出现故障之后,它怎么去告警,怎么从你的服务器中去拆掉,卸下来,这些都是你要作微服务的基础措施吧。没有这东西你靠员工去作,若是几百台机器,几百个服务,还能应付。就几万个服务,几万个机器,可能就搞不下去。

因此这种基础措施应该是搞大型互联网系统的必备的。没有这东西我以为搞互联网简直吃很差,睡不着,你都不知道那个地方出了点小毛病。若是有很好的监控设施,咱们就能及时发现问题。小毛病也有可能后面藏着重大隐患。

我曾经碰到一个事故就是个人硬盘满了,由于全部应用日志都存进去了,当时没有监控硬盘的利用率,结果线上服务异常。若是有监控的话,包括 CPU、IP,包括硬盘、监控系统、降级限流,还有另一种是系统压测,都是我认为大型互联网系统必备的手段方法。

主持人:单体服务到微服务这种重构拆封的会遇到什么样的难点?或者怎么样去解决?

惟品会郑明华:刚才都讨论了,像服务框架、架构框架、基础设施,是要解决的问题,没有这些储备,服务或者微服务根本就是实现不了。

滴滴赵伟:另外的一个的话,我以为微服务的话整个成本会很高。微服务的成本,好比机器,运维人员的能力成本,对吧?这都要提高的。

惟品会郑明华:包括这个测试定位都是成本。

滴滴赵伟:对。都是成本,整个成本都会上升的,小公司的话他可能这个在这方面投入应该不会大的,由于没钱了。

惟品会郑明华:因此服务后微服务是要看团队的能力,要看公司。

主持人:API 网关是怎么设计的?

七牛肖勤:在微服务架构中,每个微服务均可以作为服务的提供点,客户端能够直接调用。当要同时调用多个微服务时,客户端则须要逐一发送多个独立的请求,这样效率会很低效。经过设计 API 网关作为系统惟一的接入点,客户端全部请求都先通过 API 网关,而后再由它将请求路由到合适的微服务。这样客户端只须要同 API 网关交互,而没必要调用特定的服务,并且 API 网关能够调用多个微服务来处理同一个请求,这样简化了客户端与服务之间交互的次数,同时简化了客户端的代码。咱们的 API 网关目前具有流量转发,服务发现,流量控制,服务降级,权限控制,容错及监控的功能。

流量转发具备负载均衡的功能,采用的是轮询的方式,服务发现则是基于 Consul 作的。用户请求进来后经过 Consul 查询到全部可用节点的访问地址,再经过轮询的方式将请求发给后端的服务进行处理,对于返回的结果仅做转发,由请求方解释和使用。而且在 API 网关中带有监控的组件,对请求数,失败数等进行监控,传送到 Prometheus 服务器上。经过监控数据对请求进行流量控制及服务降级等相应的处理。

滴滴赵伟:咱们的 API 网关,主要分两部分。一部分是承接外部的请求,即所谓的 API 网关。另一部分是对 API 进行生命周期后台管理服务。这两套东西所有都是之外部方式提供服务的。咱们当时使用网关也就解决几个问题。

第一是解耦,对于前端跟后端,内部服务不要在公网直接暴露,经过网关可除去,外部服务经过 HTTP 请求过来,外部也不须要依赖 Client 的这种东西。而后后端的话也是能够去持续开发,下降外部调用成本。而后经过这种调用的,也经过 Json 的这种格式。网关对 Json 进行入参,而后到后面把 Json 转成对象,而后出参数才能对象转 Json 这种屏蔽这种复杂性。经过网关,咱们也会去作一些这种鉴权、流控、降级、监控这方面的。经过网关能够把整个口就收拢掉了。而后管理后台,主要是对 API 的生命周期的管理,包括鉴权,还有 API 这种后端这种服务之间的映射,这种关系之类。咱们就经过在管理后台,一旦改完以后,因此互联网关不是单台机器,而后全部的网关都要同时要生效之类的这种,也经过 MQ 这种去广播这种消息。

沪江黄凯:那这个 API 网管是否是至关于一个单点?这样会致使全部的流量所有经过网关转送到下一个服务中去。网关一旦出现什么事情,或者是它的效率很慢,会致使整个的业务流程都慢下来了。

滴滴赵伟:咱们首先看整个业务量吧,对代驾来讲,它业务量其实并无那么高。由于它不是很高频。咱们虽然是单点,可是咱们机器不是单点的,有多台机器的。通常要出问题的话,网关不太会出问题。可能后端服务会出问题。后端的服务出问题,不是它作一次新的这种发布,有 bug,或者他的这种服务的耗时从过去。好比说 5 毫秒,6 毫秒,忽然变成 500,600 毫秒的这种,可能会致使一些问题。因此咱们在网关上面,会去作流控、降级、监控这些事情,以保证它的这种。在网关上面作流控。作流控降级这种去保证它的这种金融健康。

沪江黄凯:服务注册进来之后,你的网关是怎么样发现这个服务呢?

滴滴赵伟:咱们有管理后台人工去配置的。每上一个服务要暴露的话,是须要去到我管理后台上面去配它的那个 Class,那个什么类名,方法,参数之类的都是要配进去的,而后跟个人 API Gateway 对外暴露的名字要作映射关系的。

惟品会郑明华:网关咱们也在作,咱们网关是一个集群,或者多个集群,不是单个集群。首先不是一个单台服务器,而是一堆服务器,并且这对服务器可能还不是一个小集群,而是一个大的集群,这个大集群可能还有多个小集群,他每一个集成多是对应不一样业务的,因此说即便是像你说的某个网络出问题了,它也不影响他全部的业务,这是第一个;第二个是网关主要就是一个通道,无状态、无业务逻辑,因此就是说他出问题的可能性很小。

沪江黄凯:大家用什么语言开发?

惟品会郑明华:咱们通常是用 Java 开发。

沪江黄凯:若是我是 HTTP 请求,会使用相似 HTTP client 做为转发工具对不对?

滴滴赵伟:咱们是以 Doubbo 的方式,那个 API 的 Gateway,他实际上也是在 Doubbo 上面,会去从 Doubbo 上面拿到你底层的服务,他的这个净化之类的,去调拨去的,他不会走那种的,就是说他会网关他会进来,咱们就进来计算,接受的是 Json,转成对象,而后打成二进制流,经过这种 Double 的这种 RPC 给调到后台去了。

沪江黄凯:因此你服务都是 Java 开发了,没有任何的其余的语言?

惟品会郑明华:这个不是。这个首先是服务跟语言没有关系,跟序列化协议有关系。

滴滴赵伟:他这种主要是序列化,由于语言是序列号的这种先后高地位之类的,这种可能不太同样,你本身的长度可能不同,因此可能就是用这种业界比较通用的一些,好比 Stream 的这类这些东西,或者说你本身去搞一套这种二进制的这种序列化。

滴滴赵伟:有些语言他可能不太支持,好比说像可能新进来的这种 Go,可能有些不太支持,因此这个有时候也比较麻烦一点。

沪江黄凯:咱们不少服务都是用其余语言写的,好比 Go,C++ 和 .NET 语言,若是要推 RPC协议,会形成其余的部门的反对,由于他们接不进去,这样对于驱动项目效率过低。为统一这些项目的管理,咱们都统一使用 Restful 做为服务间的交流方式。

滴滴赵伟:另外 HTTP,他的性能可能要比 RPC,TCP 这种纯的这种 TCP 可能要性能要低。由于我以为公司发展到最后,技术框架应该会统一。从业界来看,除了阿里,阿里作的方法他 HTTP 转成纯 Java。业界其余的一些大的公司,好比腾讯、百度好像都是多语言开发的,前面用 PHP,后面用 C。可是好像只有阿里作的比较好,整个技术框架统一。我以为多是要方向,这样成本会很低,业务间打通成本就会很低,后面发展会加速的,可是去作这件事确实很难。

惟品会郑明华:我如今在惟品会就是作这种事情,把 PHP 的语言逐步改为 Java 的开发。但我一直相信这个事情要作的。由于在公司内部,团队是流动的。若是都是 Java 的,流动还好。可是一个是 C,一个是 PHP 的,流动的难度就大。好比咱们有的业务不作了,技术团队也很差转成其余的语言。从另一个角度看,技术统一之后,开发维护或者沟通协调的成本都会下降不少。

主持人:如何提升服务的高可用?

沪江黄凯:微服务天生就是高可用的吧。微服务大部分属于无状态的服务,只要解决了横向的拓展问题就解决了高可用问题。对于这种无状态的微服务,咱们公司提供了Docker+mesos+marathon 三剑客的解决方案,因此应用程序不会死掉,若是死掉也会自动重启。那对于有状态的服务来讲高可用比较难,因此我以前就在问,你们的微服务都是无状态的吗。若是是有状态的,那就必须解决高可用的问题。

惟品会郑明华:若是有状态的服务,必须作到客户 Session 粘连,但性能会大幅度降低。

沪江黄凯:解决方法是否是 Active+standby 模式?客户端经过 VIP 访问?

惟品会郑明华:可是你仍是解决不了这个,一旦它死掉之后,客户连上来的状态也丢了。

惟品会郑明华:由于你如今客户都是连的 Tcp。

滴滴赵伟:它确定会断掉的,要从新连一下的,这确定的,你这边使用那个虚拟 IP 的话。当它连到后面仍是连到某一台固定的机器上,机器就死掉了,就是内部的那个 socket 就断掉了,虽然外部的没有断,实际上仍是要从新建。

滴滴赵伟:一旦一键 Retry 过了嘛,整个链路就打通了,这个时候断了其实用户实际上仍是要从新连一下的。

主持人:客户端 Retry 一下。

惟品会郑明华:可能还有难度的,由于当时你第一次建链接的时候,你用的那个 Docker,可能都没了,你再链接再重试也没用了,是看你连的是哪个。

沪江黄凯:那是否是要有一个 Session 的服务来存储状态?服务状态会存在 Redis 或内存中吗?

滴滴赵伟:因此你的这种服务就是无状态的了,由于你把状态已经搞到 Redis,因此说你的服务就成无状态的了,因此你得服务是能够互相扩展的,或者扩服务,减服务都没问题。

惟品会郑明华:要作到客户的黏粘,那个服务器起来之后才还能用,不然的话基本上很难作。另一个是你选择什么服务框架,就好比 Doubbo,这也是一个常见的模式。因此这里面已经解决了服务故障之后怎么重试的的问题。

主持人:线上的微服务怎么作持续交付?

滴滴赵伟:咱们其实尚未作持续交付,还在尝试持续集成。由于你要作持续交互的话,不是你一个业务部门可以单独去作的这件事情。由于你会涉及到不少,好比 IP 的分配,服务层报道。咱们是想经过 Docker 来作持续交互,你未来的 IP 怎么去分配,端口怎么去分配,包括 Docker 的持续分配。咱们原先最先的时候用的是腾讯的机器人,他那个系统,如今出来镜像都没办法用,你知道吗?真的搞得就很蛋疼,包括之后未来日志收集的查看,这些问题不是一个业务系统可以解决的,它必须跟运维部门去合做作这件事情,包括你要牵涉到一个发布的流程,咱们如今在尝试这种持续集成,持续交互咱们如今还作不了。

惟品会郑明华:我简单说下,就是持续集成/交付是一个比较大的东西。从开发到测试环境,包括灰度环境,包括预发布环境。好比在测试环境里怎么去集成,由于你是一个微服务,你想再把整个业务顺起来,须要周边的几十个,几百个服务才能把这个业务跑起来,那怎么解决开发的版本跟其余服务的测试问题,这是个大的问题。在之前的工序里面,它作了不少工做,包括建我的的测试环境,而后建整个团队的那种联调测试环境,以及你持续发布测试环境?那么这东西都要把它创建起来才能作到,才能正真作持续发布。

滴滴赵伟:就这个问题,这样除了你的业务以外还要牵扯到存储,好比 MySQL,Redis 这类东西,确确实实持续集成持续交互都是比较难的,如今 Docker,Kubernetes 是在解决这个问题,可是如今不少公司目前都还在尝试 Docker ,但业界玩的很好的还没怎么见过。

沪江黄凯:咱们已经有持续集成/发布的方案。因为咱们课件系统全部的服务所有使用 Docker部署。基于 Devops 和 Openstack 的启发,咱们充分利用了 Docker 一次制做随处使用的特性,利用 Jenkins pipeline 的功能,使开发只要提交代码就自动进入全自动交付流程,直至上线。

其基本流程是这样的:

  1. 开发成功提交代码触发 Jenkins pipeline。

  2. Pipeline 由这样几部构成:测试、编译、打成 Docker 镜像、上传镜像、调用 Marathon API发布到 QA 环境。

  3. QA 经过自动或手动测试对 QA 环境进行验证,若有问题返回开发修改并从新触发 Pipeline。

  4. 测试经过后仍是由 Pipeline 自动发布到验证环境并调用脚本进行 FBT。

  5. 全部验证无问题后 Pipeline 先对产线使用金丝雀发布确认有无问题,若是没有问题便可全面部署。

整个持续交付流程中有几个特色:

  1. 整个发布,所有是由 Pipeline 脚本调用 Marathon API 进行的,没有任何人工参与。在实际使用能够根据业务的敏感性作必定的人工干预,好比发布到产线环境多是由运维人员协助完成。

  2. 交付过程当中的几个环境除了产线环境之外,并非物理隔离的。而是根据需求动态建立或消亡的,相似于每次部署都是一个全新的环境,这样作的好处是不容易产生发布的冗余数据和配置错误,这也是整个流程中最有特点的一个。

  3. Docker 的一次制做,随处可用特性在交付流程中大大的避免了环境不一致问题形成的部署复杂度。

滴滴赵伟:咱们如今想作这些事情,可是其中有一个比较麻烦的事,如今用这个的话。咱们确定要尝试新的技术的,不可能就是一刀切,就直接所有就上去了,每次所有就上去了,由于你并不熟这个东西,也没有通过现场的验证,确定也是逐步去试的。逐步去试问题就在于咱们有一部分服务是在 Docker 相似里面改的,有一部分服务它在外部的。服务的注册和发现,大家如今是怎么搞的?包括像这种日志,由于它放到镜像里面去,日志至关于输出,你怎么定位问题这个查日志,包括你的监控这块会怎么去作呢?

沪江黄凯:其实在整个框架中注册与发现有两种方式,一种是服务启动以后主动地向注册服务器注册信息。咱们如今使用 Consul,也就是说服务在启动后会自动调 Consul 的注册服务API,告诉 Consul 服务的 IP 地址和端口。这里 IP 地址是宿主机的 IP+ 映射的端口,宿主机 IP 经过环境变量自动注入 Docker 中,每一个 Docker 就自动知道了宿主机 IP。这种方法有侵入性,其实在咱们使用编排框架,好比 Kubernetes 或 Mesos,是知道启动在资源池中的 Docker 服务的端口是什么,名字叫什么,尽管端口和 IP 都动态的。还有一点是要解决内网和外网互通,这是咱们实现 Docker 微服务编排的必要步骤。若是启动了不少微服务,若是这些微服务都是无状态的,并且是平行服务,必定须要一个 Load balance。只要在这个 Load balance 上开端口映射,内外网就打通了。

沪江黄凯:另一种服务注册与发现是经过三方的工具不断监控编排服务的变化,若是发现有新服务启动,则自动注册。关于日志的输出,咱们使用 Volume 挂载 HOST 本地文件系统的方式,把 Docker 中的日志文件“引”到宿主机上,再经过ELK套件管理和查询。每一个日志文件都会有具体的 Docker 的 IP,查询问题很是方便。

滴滴赵伟:对于业务部门这个事情很难作很难作,除非你进来以后他们帮你解决这种问题或者系统部进来帮你解决这种问题。

滴滴赵伟:但问题是咱们如今尚未 Loadbalance 服务,他们都是本身经过 ZK 去搞得这种,Doubbo 的那个东西就至关于咱们在用 Loadbalance 这种东西。因此对咱们来讲,这东西就很麻烦很难去作。因此就一直搞不定,确定要先拿小服务去试一下,不能强上去,所有放到 Docker 里面去,这个受不了的,万一有问题的话,你承担不起这个责任吧。

沪江黄凯:对,是从一些小的应用开始实验的。其实一个流程验证跑通了,那么接下来就能够大规模的推进了,由于流程都是同样的。

相关文章
相关标签/搜索