【 ECUG 演讲分享】吴海黎:CODING 微服务架构演进之路

​近日,CODING 平台技术总监吴海黎参加了由 ECUG 社区举办的技术大会,与听众一同分享了 CODING 微服务架构的演进历程。让咱们一块儿来欣赏精彩的演讲内容吧。spring

你们好!我是来自 CODING 的吴海黎,今天我给你们分享的内容是微服务拆分的实践,微服务几乎能够说是当下的一个主流架构,但愿今天的分享能给你们落地微服务带来帮助。整个分享分为三个部分:第一是单体架构的简介,第二是微服务架构落地方案,第三是 DevOps 之于微服务的重要性。安全

1、单体架构简介服务器

虽然第一部分是介绍单体架构的主要痛点,可是仍是应该跟你们分享一下,单体应用对于咱们在业务早期,业务处理单一,团队规模较小,单体应用的中心化处理方案是可以下降团队的沟通成本,下降架构的复杂度,从而提升研发效率的这么一个架构。因此是否升级微服务架构,取决于咱们所处的业务阶段和组织架构。介绍完单体架构的优点,咱们一块儿来看看 CODING 微服务改造前的 Backend Service 是什么样的。网络

首先这个架构应该是 0.5 版本的微服务架构,能够看出这个架构有一部分服务已是拆分红独立的微服务了,而且服务之间的注册和发现是依赖于 ETCD 去作服务发现与注册的事情。服务之间的通信方式是 GRPC,咱们选 GRPC 的缘由是部分的服务是架在 GO 上面的,部分的服务是放在 Java 上面,因此咱们须要跨语言的通信方式。架构

咱们能够清楚地看到这个架构存在的主要问题是服务拆分了,可是并无治理,服务的耦合性依然很是严重,好比说咱们如今整个入口依然是 CODING 的主站,而后经过主站的流量分发走 GRPC 接口去调用新的服务,没有彻底的作微服务的拆分事情。服务之间的耦合性依然很是严重。负载均衡

看完技术架构,再看一下基于架构的迭代问题,能够看出 CODING 天天的迭代工做量是很大的,咱们天天大概是会新增 200 多个需求,100 多名工程师进行研发,合并 50 屡次 MR,可是因为咱们的业务是分红多个部门进行研发,若是一个部门的业务 Staging 验收失败,可能会致使咱们在整个产品迭代部署失败。运维

回顾一下架构和迭代的主要痛点,第一个是迭代慢,二是编译构建慢,三是难以扩展,四是稳定性慢。分布式

带着问题来看一下微服务架构的主要定义,我把马丁的关于微服务的定义重点圈出来,我对它的理解是咱们须要有一种方法论去切分咱们单体的服务,使每一个微服务的数据独立不共享,可独立构建和部署,而且构建和部署应当有一套自动化的工具来加速整个构建和部署的过程,也就是 CI/CD 和 DevOps。介绍完微服务的定义,你们不难看出微服务架构是用以业务变得复杂的手段,团队规模扩大后,咱们将复杂的业务作出合理的拆分,从而方便各个业务独立部署,独立技术架构演进的这么一个技术架构解决方案,也是咱们解决以前问题的架构解决方案。 微服务

介绍完微服务,能够清晰地看出 CODING 的微服务改造总体方案出来了,咱们的整个改造是开源方案为主,避免本身造轮子去蹚一些没有必要的业务上的雷。第二是咱们会聚焦核心目标作必要拆分,咱们不会一来把全部的单体业务所有拆分为微服务,咱们仍是按照一个节奏、步骤去增量改进。第三点是兼容原有架构,技术选型对原有技术架构咱们是无侵入、可逐步地将全部的应用拆分红微服务,而且线上用户没有感知。第四点是 DevOps 的部分,我重点把 ops 作了颜色上的区分,就是在强调咱们在作微服务拆分的时候有 50% 的架构都放在了可运维架构上面。工具

2、微服务架构落地方案

微服务架构的落地前期主要关注两个方面,第一方面是如何拆,第二方面是微服务的技术架构选型,主要是两方面的技术架构选型,一是基础设施层,另一个是应用层选型。

首先看一下微服务拆分,微服务拆分是一个业务和组织架构强关联的问题,同一个公司不一样的业务阶段不一样组织架构拆分的方案也不相同,微服务的拆分是否合理,直接决定服务之间的通信次数、分布式事物,以及后期业务演进的便利性。

 简单经过一张图来看一下,若是说拆分粒度太小,服务的 RPC 和分布式事务均可能致使性能严重降低,这也是我在 2017 年在北京第一次作创业的时候,我当时犯的一个错误,第一次咱们把一个电商的微服务拆分得很是细,几乎是能够理解成按照表的维度去作了微服务的拆分,带来的结果就是服务与服务之间的通信很是消耗性能,分布式事务很是之多。

若是是拆分粒度过大,就起不到业务的独立演进的目的。

在介绍微服务拆分以前,我以为有两个大的方法论或者说结论须要跟你们分享,第一个是 DDD,因为时间关系,咱们在会上理解到 DDD 是一种架构设计的方法,是咱们划分业务便捷有效保证微服务高内聚低耦合的方法论就能够了。

咱们在具体落地的过程当中,是经过一个事件风暴的会议来实现聚合和限界上下文,这是咱们须要在 DDD 里面理解的两个概念。其中聚合是咱们在业务领域的组成部分,在同一个微服务中,而限界上下文是服务边界和微服务的边界。

第二个是康威定律,康威定律严格来讲不是方法论,只是一个结论,在讲咱们的业务模型每每和咱们的组织架构匹配,也和咱们的系统结构匹配,而每个业务部门的业务顶域、技术栈、同对文化的差别,必然致使迭代的频率、发版频次的不一样,也使得单体应用没法知足公司组织架构的升级,同时也意味着微服务拆分的必然性。

这张图是 CODING 最后的单体应用拆分方案,我分红了横向和纵向两个部分,能够看出咱们首先是因为部门之间业务不一样,对于独立部署是刚需,因此咱们先进行了部门级别的微服务拆分。在部门内部,咱们是根据 DDD 的设计方法划分业务与业务之间的边界,造成最终的拆分方案。右边的图是咱们拆分以后的微服务概要的分布图,能够看出拆分以后咱们是每个微服务技术架构能够独立演进,业务高度聚合,可独立构建和部署。

看完拆分方案,咱们一块儿来看看技术架构,主要是两个部分,第一个是基础设施层,一个是应用层。首先是基础设施层,咱们最后选用的方案是 Service mesh+K8s,我把 springcloud 放在这张图上面,不是说 springcloud 自己是一个基础设施层的解决方案,是由于咱们在作技术选型的时候,其实是用 springcloud+K8s 和 Service mesh+K8s 作了一个对比。其实严格来讲,二者重点的区分都是对架构的侵入性和具体实现语言的无关,以及从此咱们架构演变的便利性,因此咱们最终选择的方案是 Service mesh。

其实 springcloud 这几年的发展能够分为三个阶段,第一个是大量整合 Netflix 的一些开源组件;第二个阶段是因为 Netflix 迭代速度可能知足不了 springcloud 社区对于组件升级的须要,springcloud 本身造了一些轮子,好比 spring gateway 这样的东西。第三个阶段是随着国内对微服务应用技术愈来愈多,能够看到一些开源的大厂,好比说阿里,他们作了一些开源的贡献,有不少组件相继出来。可是对咱们而言,对于架构的无形入侵是咱们作技术选型最重要的一点,因此咱们最终选择是在基础设施层解决微服务的网络治理的问题,因此咱们选择的是 Service mesh,具体来说咱们选择的是 LINKERD2。

接着看一下应用层,能够看出咱们应用层的技术选型基本上是围绕两件事情来作的,一个是流量的管理,第二个是服务的治理。第一个主要是经过 spring cloud gateway 和 Apollo 的配置中心和 Hystrix 来完成。能够看到因为咱们网络的管理,下沉到了基础设施层,因此咱们这一层没有服务和网络相关的中间件。

首先看一下流量管理是怎么作的,首先讲讲咱们流量是怎么从外部进入内部服务器的,咱们这边先是在用云服务器的负载均衡功能将流量打到,云厂商提供的负载均衡的功能,将流量打到了云服务器的 Nginx,再有 Nginx 作反向代理到多个实例的网关作 HA。咱们这边对网关组件定义的功能主要是鉴权、认证、动态、路由,跟安全相关的东西,好比说IP白名单功能,好比说限流。

还有一个比较重要的特性是如何监控和报警咱们的 API 服务,咱们选用的方案是 Hystrix+Promethus,因为时间关系,若是你们对这个自己的技术选型或者说有架构上的疑问,咱们能够放在会后讲完以后提问环节一块儿聊一聊。

再看一下服务治理,目前的注册和发现是依靠 K8s 的 EDCD 来完成,每个 K8s 的节点都会注册上去,K8s 的网络会复制到集群中间的节点到节点的网络群。另外咱们调用的方式是走的 GRPC,目前只支持重设和负载均衡,具体是依靠 LINKERD 去作了网络流量的劫持去完成这件事情。目前 GRPC 的调用还不支持熔断和降级,咱们目前在作整合的过程当中。我列了应用部分咱们关注的微服务架构问题集,以及咱们的选型方案给你们,有兴趣的朋友能够问我要这张截图。

我想补充一点,微服务的拆分不多是一次作完,架构改造不可能一蹴而就,咱们的经验是先肯定最紧急、最重要的业务拆分需求,以此为根,将业务依赖的技术服务和应用组件先剥离出来,做为微服务第一期的上线内容,重点是验证微服务的基础设施、应用层架构拆分方案的可行性。固然各类灰度方案是有必要作的,只有第一步的象限走稳,后期的逐步拆分才不会出太大的问题。前期咱们作微服务架构改造的时候,也犯了一些错误,咱们是将产品迭代和微服务架构改造分为两件事情在作,咱们两个方向分别去推动,会犯的一个比较大的错误或者是问题是,咱们须要不停地从主代码里面去合并代码到拆分的工程里面去。其实这个直接会致使咱们的拆分工做量愈来愈大,问题会愈来愈复杂。后来直接致使咱们拆分的项目改造的信心带来巨大的打击。

说完微服务的技术架构,咱们再一块儿看看如何去作本地开发环境。目前咱们的业务是由 100 个左右的微服务组成,很明显开发服务不可能所有造成微服务,由于就算服务 0.5G 的内存占用也须要 50 个净内存,咱们须要一个 K8s 集群环境部署全量 Master 版本的微服务,本地开发使用 Telepresence 提供的网络代理和转发机制,将本地的微服务新增或者替换到对应的 K8s 集群环境中去,就能够方便地完成本地的开发和测试工做。

另外,咱们也能够经过这个机制去作部门级别的微服务测试工做。 Telepresence 干的事情是它会将本身以一个 pod 节点的方式注入 K8s 的集群里面去,这个 pod 节点具体干的事情就是网络代理和转发的事情,会将集群的流量达到开发者自己的流量,开发者能够经过流量的获取去作本地的功能调试这么一件事情,其实这个对于一个微服务的本地开发或者是 K8s 的运行环境的开发来讲,是很是重要的一件事情。

3、DevOps 之于微服务

刚才咱们介绍了如何拆分微服务以及技术架构的基础设施和应用层的一些技术选型,也介绍了本地开发环境的搭建方式,最后咱们一块儿来看看 DevOps 为何对微服务如此重要。

首先分享一下什么是 DevOps,其实 DevOps 的核心概念是打通开发和运维的信息边界,使它们的认知和目标一致,最后使得它们的工具一致、环境一致,从而保障咱们的迭代速度和修复问题的能力,从定义上看,DevOps 包含文化的建设和工具的建设两个部分,文化的建设比较抽象,咱们就不展开说。咱们今天重点介绍一下工具的重要性,也就是自动化的重要性。

首先看一下自动化构建和自动部署,在 2019 年微服务改造过半以后,CODING 天天须要构建 20 屡次完成 50 屡次部署,这跟最开始可能一天咱们连一次版本都不能发布的数量变化是很是巨大的。假如这些事情都是没有自动化构建和部署的支持,光是这么一个事就是不可思议的工做量须要极大的团队来维护整个 CI/CD 这件事情。

咱们来看一个运维方面的问题,分布式追踪,能够想象一下若是线上出了问题,咱们须要在几百个服务实例中找到出错的服务,可能你还要找到服务里面,还有 10 个、20 个实例,你要具体定位到哪一个实例出了问题,若是没有分布式,这是没法想象的事情。可是若是咱们有分布式追踪的技术,咱们如今用的是 opencensus 这件事情,这个排查可能分钟级别就能作完。

最后不得不提起,CODING 作的就是 DevOps 全流程管理的事情,将咱们的代码从管理到需求管理、自动构建、自动部署全流程打通,极大加速了咱们微服务项目迭代的过程。

相关文章
相关标签/搜索