易高级架构师教你玩转持续交付开发流程[文末有福利]

项目介绍

三拾众筹是一个创新型的业务,我们的理想是做不一样的众筹平台:

  • 基于内容产品提供众筹服务

  • 专注探寻最有创意的想法、最有温度的故事

  • 深耕影视、游戏、音乐、传媒、动漫等泛文娱领域

  • 从2016年7月份项目筹备,经过两个多月的开发,10月份平台正式上线运营。我们的口号是:再小的力量,也能掷地回响。

    时间线

    在运行一个创新业务的时候,我们的技术会面临很大的挑战,这和我们创新业务的特点是有关的:

    第一:业务是快速变更的,不可能想好的所有的事情才开始启动我们的项目,所以刚开始的时候,所谓的创新更多的是在试错,我们希望项目在做的时候,不断地收集反馈,不断地调整方向,最终找到突破点。在不断调整方向的过程中,技术必须做到及时响应。当业务需要技术提供弹药的时候,技术不能说我们还在调研,我们还在建厂房,功能不能变更。

    第二:业务爆发式的增长。前面说我们去找方向,什么是正确的方向,很难去判断,但是至少我们不是为了维持某种状态去做的,因为我们是一个从无到有的过程。一旦我们找到了正确的方向,接下来业务就会出现一个提升或者扩张,但是时间是无法预期的,往往是爆发式的,很难线性的去判断。但是对于技术来讲,如何能够不拖业务爆发的后腿,是一个棘手的问题。当业务有很大的流量导入的时候,我们的系统不能撑不住,挂了。

    第三:资源成本投入。所有的创新项目资源都是有限的,如果资源很多,往往就没有了创新的土壤。资源不多就必须将有限的资源用在刀刃上。

    需求

    面对这三项挑战,我们的技术团队必须具备三项技术能力:

    1. 快速迭代:产品要快速交付,快速部署。

    2. 可扩展:系统能够通过横向扩展的方式,支撑更大的流量

    3. 技术有按需的能力,只扩展应该扩展的模块。

    这让我们这个创业团队想要借助云的力量,借助 易云容器平台的力量。

    对于云来讲,按需的能力是天然的,在 易云上,我们是按需按时分配的。而快速迭代和可扩展,是云的潜力,使得我们不需要采购机器,安装系统,部署环境。

    那三拾众筹如何才能发挥云的潜力,如何设计我们的系统,使用什么样的开发过程,才能让云真正的帮助我们的业务?

    这里有一个重要的概念,就是Cloud Native。有人之前翻译为云原生应用,我觉得比较直白,我起了一个小清新的名字,叫做向云而生。

    这表示我们的应用应该设计为面向云和容器平台去应用的。

    设计目标

  • 使用标准化流程自动配置(declarativeformats for setup automation),从而使新的开发者花费最少的学习成本加入这个项目。

  • 和操作系统之间尽可能的划清界限,在各个系统中提供最大的可移植性。

  • 适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源。

  • 将开发环境和生产环境的差异降至最低,并使用持续交付实施敏捷开发。

  • 可以在工具、架构和开发流程不发生明显变化的前提下实现扩展。

  • 另外还有12原则

    三拾众筹是非常相信12原则,把整个系统按照12原则进行设计。

    12 Factors

    1. Codebase-One codebase tracked in revision control, many deploys

    2. Dependencies-Explicitly declare and isolate dependencies

    3. Config-Store config in the environment

    4. Backing services-Treat backing services as attached resources

    5. Build, release, run-Strictly separate build and run stages

    6. Processes-Execute the app as one or more stateless processes

    7. Port binding-Export services via port binding

    8. Concurrency-Scale out via the process model

    9. Disposability-Maximize robustness with fast startup and graceful shutdown

    10. Dev/prod parity-Keep development, staging, and production as similar as possible

    11. Logs-Treat logs as event streams

    12. Admin processes-Run admin/management tasks as one-off processes

    系统架构

    服务架构

    三拾众筹的架构采用的是服务化的架构,是由一系列相互协同的服务组成的。服务之间有协作的过程,服务对外也提供了统一的界面。每一个服务本身有自己的存储,有自己的缓存。

    所有的服务分两个区域,也即服务分两种类型。第一是应用的服务,第二是基础服务。

    在应用服务里面,对外有一个主站服务,同时承担了API 关的职责。他会把前台的请求分发到后台,并且根据规则进行路由。

    服务与服务之间都是通过Restful API也即HTTP的方式,服务之间会有明确的依赖关系,而且依赖关系的强弱在这里用实线和虚线做区分。通过这些依赖关系来构成和编排我们的服务。

    我们最初上线的平台也不是这样的,而是只有一个众筹平台。是随着功能的丰富,应对更快的变化,而逐渐拆分的,例如对于支付模块,当我们需要接入更多的支付方式,针对支付有更多的优化需求的时候,我们需要独立出一个收银台的模块,进行服务拆分。包括会员,包括订单的部分。

    为了支撑应用服务的环境,我们还有一些基础设施服务。

    比如注册中心,服务之间有自动的服务注册与服务发现的机制。我们的所有服务是通过注册中心进行相互关联的,不需要人工的编排,是可以自动的发现服务。

    我们可以通过服务的控制台去管理服务。我的服务状态是什么,对应的版本是什么。

    每个应用都涉及到一些配置参数,如果配置参数扔在每个服务上的话,对于运维来说代价比较高了。对于微服务架构来讲,必然需要一个集中化,可分发的配置中心,也是在基础服务中的。

    我们会使用Git仓库作为配置的后端,通过配置中心去分发Git仓库中的配置,同时后面我们还会提到,有一个流程来管理整个过程。

    在这个架构里,所有的组件都在容器里面。每个服务构建的结果就是镜像,在运行期就体现为容器。

    这里面的每个服务都使用的是 易云的无状态服务,除了构建服务,构建服务是从代码构建为镜像,是在我们自己的服务器上运行,也是一个容器。

    设计要点

    接下来我分享一下我们的设计时的考虑及实现要点:

    第一.Cloud Native的设计

    1. 从设计开始,我们就隔离了基础设施和后端服务依赖,这个隔离一方面是由容器来做的,隔离了应用和服务器之间的关系,隔离另一方面,应用层我们用了很多的框架,例如我们后面提到的springboot和springcloud,我们使用公共的开源的框架和工具,把一些面向服务化,容器化的基础功能进行实现,对于应用本身不需要关系这些过程,他只需要关注中间层,根据spring的规约来进行开发。

    2. 从一开始,就把配置和代码进行分离。将配置和镜像进行分离。

    3. 对于编排的问题,通过springcloud和consul进行服务发现的功能,来实现服务的自动编排。

    第二,容器化的实践

    1. 广泛使用了容器,在我们看来,容器就是服务。当我们实现一个新功能的时候,首先要考虑需不需要单独拆分为一个新的服务。

    2. 通过提供一批基础镜像,来简化服务的开发,可以说是应用开发的模板

    3. 使用了 易云基础设施平台,因为他非常开放,技术导向,对程序员友好。提供了丰富的API,通过这些API可以实现自动化,实现自动交付。另外蜂巢提供了很多基础PaaS服务,包含数据库,缓存,CDN,对象存储,负载均衡等,降低构建服务的难度,提高开发效率。我们几乎用了所有的PaaS服务,使得我们不必要过多关心平台层面的东西。

    第三,微服务基础设施

    1. 服务的注册,发现和负载均衡机制。这个机制目前是通过spring cloud来做的。Spring cloud是一个非常完整的微服务开发的框架,他的主要作用是在应用和设施之间提供一个抽象层,让我们用一致的API去使用不同的服务发现的机制,比如基于Java开发的eureka,包括我们使用的consul。

    2. 我们实现了配置中心

    3. 我们实现了服务控制台,可以查看各个服务的状态,以及获取服务状态变更的消息通知,还有对于服务端点Endpoint本身进行管理。对于微服务架构来说,每一个服务的端点Endpoint应该更加智能,这是和SOA的区别,我们也是这样的,对于每一个服务,我们借助springcloud提供的一系列管理端口,我们的服务控制台可以通过这些管理端口去控制他,包括去查看和修改某一个服务节点的配置,查看某个节点的日志,都是可以通过服务控制台去实现的。

    镜像构建

    为了尽量降低服务本身和基础设施之间的关联,在构建基础镜像的时候,分成几个层次去考虑。

    1. 最里面的一层,是OS和系统工具的一层,我们是基于Debian系统进行构建。

    2. 应用环境的部分是和应用分离出来的,包括JDK,consul服务发现的机制等,这里有个小工具dumb-init,可以实现在一个Docker里面实现多进程。如果在Docker里面使用多进程会有一个比较大的坑,如果某个进程死掉,他的子进程就会变成僵尸进程,没有办法收回,导致我们关闭Docker容器的时候是需要强制杀掉的,这对于程序需要优雅关机来说是很有问题的。Dumb-init可以解决这个问题。另外dumb-init可以实现信号的重写。比如有些应用是需要接收一些信号,比如ctrl+C才能结束的,为了响应SIGINT信号,可以通过dumb-init进行转发。

    3. 在应用层的Dockerfile会非常的简单,选择一个正确的基础镜像,然后把包打进去就可以了。

    基于Gitflow代码管理和协作流程

    Gitflow是一个代码管理的流程,我们基于他实现了一个协作的流程。这个协作的流程体现在我们如何去发布我们的新版本,如果修改线上的Bug,如果进行开发,怎么集成测试,最重要的是怎么去验证,验证什么东西。整个过程需要自动化,整个过程都是通过gitlab-ce提供的界面,最重要的两个界面是Merge Request和自动化Pipeline来做的。所有的问题修改,所有的提测,都是通过gitlab-ce的Merge Request界面进行操作的。一旦Merge Request接受之后,都会有一个跟在后面的Pipeline,一个持续集成或者持续发布的任务,来完成后续工作,这些后续工作就是我们交付的流程。

    我们使用两个蜂巢的环境,来作为开发和测试环境以及线上环境。对于特定的环境,我们自动构建和发布之后,会自动的进行部署,对于开发人员,QA人员,甚至线上预发环境的运维人员来说,他们只需要在Gitlab里面操作完了,相应的版本就构建上去了,这些版本都会在镜像仓库中,会对应我们的分支,会有独立的版本。我们还可以按需的去部署更多的环境,去进行检验,比如线上的扩展验证。

    如图所示,左上角为提交的Merge Request,右面为Merge Request的详情,如果点击Accept Merge Request就会触发左下角的Pipeline进行整改发布流程。

    整个交付流程如图所示:

    1. 开发有一个主分支称为develop,但是所有功能的开发都不在develop上开发,而是新开分支进行开发,可以根据发布的时间点确定某个功能是不是要上线,例如图中在这一版中,feature x, y可以上线,于是Merge到develop分支,而feature z赶不上这一版,会在以后的版本上线,所以暂且不Merge到develop分支。

    2. Feature x,y合并develop分支需要经过Code Review,一旦合并后,会触发自动构建镜像的Pipeline,然后自动部署develop环境。开发需要在这个环境里面做集成和基本的测试,包含单元测试和冒烟测试,当集成和基本的测试遇到缺陷的时候,需要回到feature所在的分支进行缺陷修复,修复后重新Merge到develop,从而重新部署develop环境。当开发任务代码质量可以达到的时候,方才提测到QA。

    3. 有一个Release分支用于做测试验证,提测的发起是由develop分支Merge到release版本实现的。每次做release的时候,首先会从Master分出一个版本到release,Master分支的版本是当前的线上版本,则Develop Merge到release,其实是和线上版本的一个合并,保证当前的开发版本和线上版本可以兼容。这次Merge会触发Pipeline构建镜像,并且自动发布release环境,QA可以对这个环境进行自动化测试,或者手工测试,保证代码可以达到发布的质量。如果测试出现缺陷,则需要回到feature所在的分支进行缺陷修复,修复后重新Merge到develop,从而重新部署develop环境,在develop环境测试完毕后,再次Merge到release,然后QA再测试,如此反复,直到可以达到上线标准。

    4. 一个release分支可以达到上线标准,则将release分支合并回master分支,这次Merge会触发Pipeline自动构建镜像,自动部署预发环境。线上运维人员可以对预发环境进行测试。

    5. 如果预发环境没有问题,线上运维人员可以从镜像手工部署两套线上环境中的一套,如图中Online A和Online B,做灰度发布,新老版本先更新其中一套环境,然后前端通过负载均衡器将请求不断的从老版环境切换到新版环境。

    6. 如果需要性能测试,性能测试人员可以手工从镜像部署一套性能测试环境进行测试。

    7. 如果线上发现缺陷,则需要从Master上分出一个分支到hotfix,hotfix修复完毕进行测试后需要合并到Master分支,同时需要合并代码到develop分支。

    配置管理

    如图是一个配置管理的流程,

    所有的配置文件都放在代码仓库Gitlab里面,进行代码级别的管理。

    在Gitlab界面里面,点击accept进行代码合并,合并后触发webhook,调用配置中心。

    Git2Consul从Gitlib中pull所有的配置文件,并且将配置文件的内容通过consul的客户端同步到consul中。

    Profile=A的app和Profile=B的app通过consul的客户端将配置从consul中配置到服务中,完成配置的管理。

    总结

    最后总结一下:

    首先,最大化利用开源工具和云端技术建立微服务和敏捷基础设施,构建Cloud Native 应用,充分释放云的潜力

    其次,基于容器技术自动化构建、发布和配置流程,改进敏捷交付环境和产品快速迭代能力,及时有力支撑业务。

    自10月27上线以来,三拾众筹系统(不包括基础服务)发布版本1710次,其中43次线上版本发布;发布线上配置33次,新系统设计到上线1 ~ 3周。

    最后,通过实践打磨的方案才能适合自己,开放性是选择云平台关键评估因素。

    福利

    易蜂巢代金券兑换码:Z3710E6GADV3

    登录 易蜂巢,使用兑换码兑换即可获得20元代金券!

    声明:本站部分文章内容及图片转载于互联 、内容不代表本站观点,如有内容涉及侵权,请您立即联系本站处理,非常感谢!

    (0)
    上一篇 2017年2月5日
    下一篇 2017年2月6日

    相关推荐