经历了研发困局、运维之痛,同程微服务从1到1w的旅程

内容来源:2017 年 9 月 9 日,前同程艺龙架构师谢康在“ArchData技术大会上海站”进行《同程微服务从1到1w的旅程》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:4418 | 12分钟阅读

摘要

本次演讲主要介绍同程微服务的演化进程,如何通过各方面的升级让微服务架构趋于完善,以及在大规模微服务化过程中总结的一些经验教训。

嘉宾演讲视频回放及PPT,请复制链接:http://t.cn/RgbsbVv,粘贴至浏览器地址栏即可。

同程微服务起源

在12年到14年之间因与其他同行的激烈竞争,导致我们的系统变的臃肿不堪,因此迫切需要一个新的服务化平台。这个平台需要具备这几点要求,首先要简洁、高效、可靠,其实能够跨语言、跨平台,最后还要能够快速实现,对开发者友好。

为了实现这些要求,我们开始研究关于微服务的相关方案,最终实现了上图这样的服务系统。整个架构简单来说就是一套协议,两个容器,三个服务

因为微服务比较推崇轻量级的通信协议,所以我们就选择了HTTP2,基于该协议提供两个平台。由于时间和人力上的关系,要想做所有的平台还是不太现实,因此我们决定先搞定最核心的两个平台,分别是基于.Net和Java的轻量级容器。在此之上就是微服务核心的几个部分,服务注册,服务发现和服务状态。最后通过服务将数据上报到zookeeper,通过Zookeeper作为配置和调度中心将整个系统作为分布式集群给管理起来。

从单体架构到微服务

2015年12月份我们正式上线了一个服务Demo,正当要松一口气的时候,问题出现了。最大的问题在于团队人员对微服务不了解,面对这种情况,我们在半年内组织了40多场关于微服务的分享培训,不仅仅是让大家了解微服务,更多的是统一对它的认识,只有认知达成一致才能真正的去应用。

虽然做了这么多的努力,但是等到2016年7月整个平台系统上也只有600个服务在运行。这明显不符合预期,相对于SOA治理我们提供了很多的工具,让开发变的便捷简单,只需要将服务代码提交到git后续的步骤都会自动化完成,那么问题到底出在哪呢?后来发现还是因为前面提到的原因,大家对这套新的东西并不是很放心。

运维之痛

抛开研发层面,运维也存在着问题。为了前面提到的600个服务,运维方面已经是疲于应对了。首先是Docker,虚拟机分配任务翻倍,这是由于平台中服务耗尽的时候会触发一系列的机制申请新的资源,而这些资源都需要运维人员check之后才能分配。其次是发布量的问题,原来的平台中很多项目都是一周或两周发布一次,现在微服务之后甚至可能是每天多次,发布的时候还要保证平滑,让前面的业务无感。另外故障排除的时间也延迟了一倍,原先只有一个服务的情况下排查还相对简单,微服务之一次调用被拆成了多个服务,很难去判断哪个节点出现了问题。这些不协调的因素集合在一起之后,报警量当然也会随之增多,运维人员处理起来力不从心,疲于奔命。

运维系统的全面升级

针对上述情况我们仔细分析了一下,发现了几个问题。首先是运维体系跟不上,以前那种手动写脚本的方式已经无法应对当下的场景。其次因为微服务的发布频率很高,所以测试的自动化也要跟上。还有包括以前的持续集成和底层服务编排也不再适用。

所以在推行微服务的过程中,运维系统也要进行全面的升级。首先在源头上要有一个一站式的工单系统,通过这样的一站式运维平台进行整合然后交给运维处理。由于服务发布频率非常高,所以我们联合了自动化测试小组开发了一个集成测试化环境——天镜,将所有的case和单元测试集成起来,在上线之前就能够生成一份测试报告,判断是否能够发布。一旦判断为可以发布就先做持续集成开始发布,最后到底层的PaaS平台分配资源。

整个流程看起来和微服务关系不大,但是微服务对底层的PaaS平台有很强的依赖,如果没有这一系列的步骤就很难去实施微服务。所以这里给大家一个建议,在底层的基础设施还不够完善的时候,不要贸然去推微服务

兼容并处

经过一系列的升级,到2017年2月的时候平台中的服务终于达到了5400多个。这时运维是没什么问题了,不过研发方面又出了新的难题。一方面有大量的新老员工对微服务开始感兴趣,过来咨询如何进行迁移。另一方面随着服务量的增多,出现了各种罕见的故障。简单说个大家不常碰到的问题,因为有着跨平台的需求,所以我们经常要从windows向linux发包,有一段时间出现过发送的包全部丢失的情况,最后经过与运维人员的配合才发现是linux内核中的参数出现了问题。

服务化作为整个业务体系中最核心部分,一旦业务研发人员发现问题首先想到的就是向我们反馈求助。这种情况的出现导致我们的咨询量暴增,且很难对所有的问题作出应对。

DevOps工具

我们的整个升级方案中,前一阶段解决的只是DevOps中的运维部分,Dev还没有一个很完善的解决方式。在反思了这一问题之后,我们开始着手完善DevOps的整个流程问题。最终实现了在开发人员写第一行代码之前就已开始介入,无论是Java还是.Net或者Go我们都能提供一致的项目模板或脚手架,安装完成之后就能享受所带来的便利。同时考虑到多语言多平台的现状,我们还做了一个通用平台,这样开发者在不同语言之间进行迁移的时候也能获得一致的体验。

到了测试联调阶段,我们也进行了相应的改进。使得代码在编译的时候只要有一个良好风格的注释,剩下的就可以交由组件处理。比如将所有的注释和接口抽取出来做数据契约和接口契约生成wiki文档,在调试的时候该文档就会生成,它给联调带来了极大的便利,发布之后的回归测试也能够用到。

DevOps作为一个庞大的平台,一定要有一整套的OpenAPI机制,保留足够的透明化,让用户能够知道系统运行的时候到底发生了什么。我们有一个完善的监控系统让每一步调用,每个接口的响应时间都能通过OpenAPI机制让用户获取到。必要的时候,还会开放一部分的运维权限给开发,因为只有开发人员才会知道系统出现的问题该如何维护。

以上就是我们目前所提供的DevOps工具,相对来说还是有所不足,因为当出现新的工具的时候,研发人员总会期望有更好的工具,所以我们还是会进行不断的演化升级。

关于服务粒度

前面分享的都是同程两年的微服务历程,在这个过程中我们也总结了很多经验。比如大家最关系的服务粒度问题,微服务如何拆分,分到多少粒度才合适。

在谈具体的拆分方式之前,先来了解下康维定律和领域建模。康维定律简单来说就是系统设计(产品结构)等同组织形式,每个设计系统的组织,其产生的设计等同于组织之间的沟通结构。同程就是一种典型的树形结构,底层会有一些高频的互访,最终我们的微服务架构也是类似于这种结构。

上面这两个概念相对来说比较宽泛,这里说下我们的具体方案。

第一是按照团队组织结构切分,明确服务的归属,切勿出现跨组的服务,这样物理上的切分能够让服务获得更好的内聚性。

第二个是按服务的发布升级频率分,我们刚开始做的时候,经常会出现一个有多个接口微服务中,仅有一两个接口是高频的,剩下90%只有少量的访问,但是每次发布时这些接口都需要全部带上,测试的时候也都需要再跑一遍,造成很大的资源浪费。因此我们推荐将哪些特别高频的服务接口单独剥离出来。

第三是按服务调用数量级分,一般使用Restful风格设计的接口,update和inset应该是放在一起的,但是update和inset之间如果有一个访问频率远远高出的情况下,就有必要考虑将它分离出来。

最后就是按照数据的读写分离划分,之前我们的很多设计都是基于增删改查,但是这种设计大部分情况下查询都会高出几个数量级。这时候我们推荐采用CQLRS模式,将幂等操作和会导致数据变更的操作分开,也就是常说的读写分离。

关于服务版本

在一开始只有600多个服务的时候版本问题还不明显,当达到5000多个时就给我们造成了很大的困扰。之前刚开始用服务的时候大家都没有定义版本,一直的都是1.0,导致服务内的接口不断增多。这主要是由于服务的开发人员不敢随意的对代码做修改,怕服务下线后引起服务的宕机,所以只能不断的增加接口。

为了解决版本问题,我们开始使用标准的语义化版本。版本号有4位,前两位是大版本号,后面是小版本号。在修改或删除原先的接口后,需要升级大版本号显示的告知调用者该服务做了不兼容的升级。如果只是优化了逻辑或者新增接口的情况下,则要升级小版本号。

这种方案在刚开始推行的时候也出现了很多问题,有的团队是不知道如何写,有的则是一味的升级小版本,毕竟这样安全些。这个问题也是微服务治理的一个重要方面,就是微服务平台要能够评判服务的质量。在我们的平台中有一整套的中台机制,在服务注册的时候不光会上传服务的节点、IP、端口,同时还会上传所有的接口和数据契约。也就是说它会解析包的原数据,将对方需要知道的数据都抽取出来,甚至包括注释,它的好处在于服务发布的时候能够知道是否有不兼容的升级,调用方也能知道服务升级具体做了那些事情。

我们对版本号的机制做了多次迭代。第一代版本号是固定的,调用方调用的时候也要通过该版本号,只要有了服务名和版本号就能帮开发者进行服务查询和调用。这一代的问题在于每天都要更新多次版本,非常麻烦,为此提出的妥协方案是直接让开发者将版本号写在配置中。到了第二代就有了统一的向前/后兼容的策略,和明确的不兼容策略。只要接口没有发生改变造成不兼容,我们都能够找到,即使接口所在的项目包发生了多次升级。

关于过渡到微服务

最后也是最难的一步就是从如何单体架构过渡到微服务,过渡的时候不仅对业务研发有要求,对整个的微服务平台也有着要求。微服务框架要有良好的兼容性,让研发人员能够平滑的进行过渡。我们刚开始的方案是让开发者直接将代码打包接到平台中,然后通过服务治理系统进行拆分。

接下来就要讲到绞杀者模式和监狱模式。绞杀者模式很常见,就是将单体架构向微服务演化的时候,首先要保证单体架构不会继续增大,对于新的功能和模块要独立开来,原来的项目直接冻结,再把原先有的功能慢慢剥离出来。如果有些功能很难进行剥离的话,那么就要用到监狱模式。先做一个微代理的微服务项目,接入真正项目打包后的接口,什么时候接入的项目能够转换成微服务,就将微代理给去除掉。

虽然上面讲到了很多解决方案,但是还有一点需要提醒大家,“微服务不是银弹,不要过度微服务”。因为多一层调用势必会影响一些性能,整体的复杂度也会增加,运维和测试成本也会上升。因此那些对性能特别敏感或有高频运算的项目就不适合去做微服务。

以上为今天的全部分享内容,谢谢大家!

推荐文章

  • 微服务迁移前,来听听这6个思考和经验
  • Sharding-JDBC:分布式微服务数据库访问框架的设计与实现
  • Metrics:让微服务运行更透明

原文发布于微信公众号 - IT大咖说(itdakashuo)

原文发表时间:2018-07-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算

为您的组织选择正确的企业云解决方案

目前,云计算已被广泛使用,并且成为多数企业为之努力的目标。然而,入云所带来的现实问题也令人担忧。耗时费力的部署,安全风险,噩梦般的应用程序迁移场景以及不成熟的私...

2206
来自专栏ThoughtWorks

单体中心代码库 vs. 分布式代码库|洞见

去年中旬两位Google工程师在《美国计算机学会通讯》发表了一篇论文“Why Google Stores Billions of Lines of Code i...

3423
来自专栏重庆的技术分享区

微服务介绍

原文地址:https://medium.freecodecamp.org/an-introduction-to-microservices-2705e7758f...

1822
来自专栏solarest的专栏

为您的组织机构选择正确的企业云解决方案

云计算作为一种强大的新技术,正在被越来越多的组织迁移和使用。然而向云的迁移也着实让人担心。开发复杂度、时间损耗、安全风险、噩梦般的应用迁移方案还有不成熟的私有云...

2126
来自专栏zzzz

hadoop大数据平台架构之DKhadoop详解

大数据的时代已经来了,信息的爆炸式增长使得越来越多的行业面临这大量数据需要存储和分析的挑战。Hadoop作为一个开源的分布式并行处理平台,以其高拓展、高效率、高...

1633
来自专栏技术杂文

微服务:真正的架构模式

微服务的相关知识和它的神秘令我着迷。概念上的微服务就像是现代最有趣的流行架构之一。它足够功能强大,有着广泛的使用方法;也足够模糊,难以统一而论。

2723
来自专栏Java架构师进阶

一个程序员对架构的认识

架构是一个系统的草图(逻辑+物理角度),它是有生命的,随着业务的变化会不断演进。没有完美的架构只有合适的架构。

1063
来自专栏程序你好

数据库设计中的6个最佳实践步骤

如果设计得当,数据库是记录、存储、检索和比较数据的强大工具。然而,一个没有经过精心设计和目的的数据库不仅仅是无效的,它对那些使用它最多的人(开发人员)来说是一个...

1372
来自专栏IT大咖说

如何支撑微服务架构落地

编辑IT大咖说 阅读字数: 2265 用时: 7分钟 ? ? 摘要 如今微服务如日中天,优势和弊端也有各种描述,那么我们是否应该采用微服务架构?如何规避微服务的...

3689
来自专栏pangguoming

国外物联网平台(1):亚马逊AWS IoT

设备影子服务使用MQTT话题,便于应用和设备之间的通信,下面是相关的MQTT QoS 1话题:

5302

扫码关注云+社区

领取腾讯云代金券