联想企业网盘:SaaS服务集群化持续交付实践

1      前言

当代信息技术飞速发展,软件和系统的代码规模都变得越来越大,而且组件众多,依赖繁复,每次新版本的发布都仿佛是乘坐一次无座的绿皮车长途夜行,疲惫不堪。软件交付是一个复杂的工程,涉及到软件开发的各个细节,其中任何一环出现问题,都会导致软件不能及时交付,或者交付的质量堪忧。

从企业的角度来讲,如何利用更科学的工具、更科学的流程来提高产品质量,提升客户满意度,是刚需。从员工角度来讲,生命里值得追求的事情很多,不能把宝贵的时间浪费在一些机械的、重复的事情上面。

联想企业网盘从2007开始面向企业客户提供专业的云存储服务,10年来服务了250000+企业。软件的更新迭代司空见惯,联想企业网盘就是由成百上千台服务器组成的,是一个非常复杂的互联网应用,仅仅在服务端就有几十个模块协同工作,加上各种客户端,需要使用不同的编译发布环境,有时候需要单独模块发布,有时候需要多个模块联合发布,使得每次的升级情况都非常复杂。曾经经历过一次大版本的升级迭代,运维和研发团队不眠不休的工作了40多个小时,既影响了用户的服务,也使得团队疲惫不堪。类似的经历,使得我们思考如何通过技术革新来解决这一难题,能够把我们的工程师们从简单劳动中解放出来,这样在未来面对更大规模的集群的时候,才能够游刃有余。

缩短上线时间,提高上线准确度,是我们建设这个系统的初衷。

2      问题

先让我们借用一张图(来源于 thoughtworks 官方文档)来回顾一下软件发布的一个完整的流程:

整个过程中,代码管理,集成和测试,发布上线是3个主要的环节。我们所有的问题都集中在这3个环节当中。

1、代码管理

代码管理混乱是一个研发团队的常见问题,研发的过程中,代码的分支设计不合理,分支过多或者过少,分支依赖混乱,权限控制缺失,完全靠人治,没有代码审核。

2、集成和测试

从研发环境到测试环境,都没有统一规范的部署环境,研发团队直接给测试出版本(野版本),因为编译环境,人员水平的差异会导致各种莫名其妙(有时候很低级)的问题,极大的影响了测试的效率和准确度。

3、上线交付

代码最终部署到生产环境的时候,需要运维人员和研发人员频繁手工操作,费时费力,还容易出错,整个过程不可重复且没有记录,回滚操作复杂,有时候甚至是无法回滚的,一旦是上线出现错误,对我们用户的影响就是非常恶劣的。

3      实践

多年来,我们在研发过程中不断总结,想了很多的办法,在服务客户的同时积累了大量的生产环境运维经验,开发了许多工具和流程,来解决升级和产品上线的问题。,下面基于联想企业网盘的生产实践,分享一些我们在建设持续交付系统方面的方法。

如下图所示,我们主要讨论这几个方面:

 

3.1    代码管理

代码是软件交付过程的源头,所以合理的规划与管理尤为重要。

3.1.1    代码仓库

早期,我们所有研发人员的代码都存放在一个 SVN 库里,分支和 Tag 散布在各个模块的子目录里。SVN 是很好的一个工具,但是太灵活了,要大家严格遵守纪律,但是更多时候要靠大家自觉,但是人总是会有松懈的时候。一旦有人不守纪律,对于后来者就是一个苦不堪言过程。

所以我们的第一步,就是把 SVN 迁移至 Git。按照模块拆分为单独的库,每个模块单独授权,统一分支模型。仓库软件用的 Gerrit,它原本是代码审核工具,拥有强大的权限管理系统,Git 仓库只是附带的功能。

其实在从SVN迁移到Git的时候,有很多工程师会有疑问,为什么迁移到 Git?不是 SVN 不好,也不是为了追逐技术潮流,而是后面的自动化工作(包括代码审核工具)用 Git 更方便,当然 Git 强大的分支功能以及分布式也是一个重要原因。

3.1.2    分支设计

分支我们参考比较常见的一个 Git 分支模型(参考链接),针对我们自己的需求做了一些调整,如下图:

1、         设计两条主分支,dev 和 master,dev 是开发分支,master 是对外的稳定分支,持续交付系统会从master分支拉取代码进行构建;

2、         辅助分支只使用 feature 分支和 hotfix 分支,feature 分支原则上是尽量不建,只用于开发周期比较长的新功能开发,短平快的 feature 都直接提交至 dev。

3.1.3    审核

代码是产品质量的源头,代码质量不行,其他再多辅助手段都没用。代码审核是保证代码质量至关重要的一环。只要团队人员数大于一个就应该推行代码审核。

 

代码审核有两种模式:

l  集成前审核(pre review)

顾名思义,在代码合并至目标分支前进行代码审核,有问题改,改完再继续审核,审核通过则集成进目标分支,这一类审核的代表工具软件有:Github,Gerrit,其中 Github 是以分支为单位进行审核,Gerrit 以提交为单位进行审核。

l  集成后审核(post review)

先合并代码,然后进行审核,有问题只能用新的提交来修复了,这一类审核的代表工具软件(其实这两款软件也支持 pre review):reviewboard,phabricator。此种方式容易导致目标分支不稳定,所以一般不建议。

我们采用的是第一种集成前审核的方式,工具软件用的 Gerrit,以提交为单位,强制审核过后再合并至目标分支(当然这个过程是自动的)。

好了,话不多说,有图有真相,下图是我们的代码提交工作流:

图中黄色的部分即是代码审核的部分,每个提交需要经过其他人审核(Code Review +2)和持续集成系统验证过(Verify +1)才能合并至目标分支。

代码审核页面:

3.2    构建部署

在这里我简单的将构建部署分为持续集成和部署流水线,实际上,这两块很多地方有重合,这里的持续集成仅仅只讨论构建验证和自动集成,部署流水线包括从构建到部署至不同环境的整个过程。

3.2.1    持续集成

持续集成是一个大的议题,是敏捷开发的一项核心实践。在持续交付过程当中,持续集成将从开发到部署的各个环节组成一条流水线,是整个交付过程的核心。重点是要快速反馈,在集成代码之前迅速发现问题并改正。

我们把单元测试、编译验证、静态扫描和覆盖率检测分离出来(这一步骤的时间控制在 5分钟内,这也是前面为什么要把库拆分的原因之一),在研发人员提交代码后立即触发构建,在5分钟内把结果反馈给研发人员,继而快速修复错误,直至验证通过。

我们采用的工具软件是 Jenkins,最流行的持续集成软件,通过插件支持 Gerrit,功能非常强大。

在实际的实施过程当中,要求每个模块都要提供在一个干净环境执行编译、单元测试等等步骤的脚本或方法,构建环境可以通过 Vagrant 或者 Docker 来自动配置,我们内部采用了Docker 技术来隔离各个构建环境。

流水线

3.2.2    部署流水线

顾名思义,这一步骤就是把打包好的软件部署到不同的运行环境,并且要自动处理各个环境的配置(例如域名、数据库信息、登录信息等等),此步骤严重依赖于前面步骤的实现,仓库的规划、分支的规划、持续集成的流水线构建等等。

 

一个典型的部署流水线

 

在构建部署流水线的时候,我们要遵循几个原则:

1、         过程可重复;

2、         一次构建多地部署;

3、         模块化部署;

4、         变更管理;

5、         审计功能;

6、         快速回滚。

在选择部署工具方面,我们考察过两个:thoughtworks go 和 Jenkins(插件 Delivery Pipeline)。

Go 系统自带管道,但是灵活性不如 Jenkins;Jenkins 的一个好处是我们的持续集成都在 Jenkins 里实现,很多脚本都可以复用,甚至很多任务都能直接复用,缺点是管道各任务之间数据共享比较繁琐,需要额外的插件(例如 Copy Artifact),所以实现的不是很自然。

在实际的实施过程当中,能够完全实现自动化(无人值守发布)是一种理想状态,但实践当中总是会受各种因素制约,所以必要时也必须向现实低头。我们最终实现了一键部署加关键环境(例如生产环境)手工触发(下面图中的播放小箭头就是这样的步骤)相结合的流程,参见下图:

在实施过程当中,配置文件的管理也是很重要的一个议题。配置文件主要分为两类:

1、 配置文件与运行程序不能分离,像J2EE这样的应用,配置文件与编译成果物打包成一个 war 文件,我们的处理方法是把敏感信息(例如数据库信息)存放在其他的Git 库,构建的时候针对不同环境分别构建,构建时由Jenkins 自动记录代码的版本和配置文件的版本;

2、 配置文件与运行程序可以分离,类似于 nginx 这样,我们把程序打包成 rpm 或者 deb ,配置文件存放在 puppet 主服务器上,每次部署都触发 puppet 的自动分发。

在持续交付流程中,我们可以清楚的知道当前每个环节,每个节点都处在一个什么版本状态,这对于清晰的了解,快速回滚非常有用。参见下图,某项目部分模块不同环境版本信息(请忽略页面丑陋这个细节,红色即表示某个模块正在发布,还没最终上线):

---------------话题补充---------------

@IT薄荷叶:4 尾声 目前联想企业网盘的服务已经全面采用流程化的上线交付体系,从研发环境到测试环境到生产环境,全部是流水线作业,保证了各个模块间代码和版本的一致性,代表的集成、发布只需要我们轻点一下鼠标,然后就可以喝着茶耐心等待收到发布成功的邮件了。 持续交付是一个长期的需要不断完善的过程,公司的策略在变,产品需求在变,人在变,流程也在变,我们所做的仅仅是开始,还需要继续去摸索,磨合,打造出更为完善的交付系统。这是一个任何软件开发团队都需要重点考虑的事情,建立规范,制定流程,利用科学的工具来实践规范和流程,脱离小作坊式的交付模式,按时按质按量交付产品。 (1小时前)

http://www.oschina.net/question/2448759_2186294

时间: 2024-07-30 11:16:13

联想企业网盘:SaaS服务集群化持续交付实践的相关文章

Rancher集群化docker管理平台部署、特性及破坏性测试。

rancher是一个docker集群化管理平台,相对于mesos和k8s架构,rancher的部署管理非常简单方便.并且功能丰富.如下为本人绘制的逻辑架构图. 1:部署Rancher管理平台 规划: server:10.64.5.184 agent1:10.64.5.185 agent2:10.64.5.186 agent3:10.64.5.187 agent4:10.64.5.188 部署方式: docker容器启动 server端部署   依赖镜像:rancher/server:latest

SpringCloud注册中心集群化及如何抗住大型系统的高并发访问

一.场景引入 本人所在的项目由于直接面向消费者,迭代周期迅速,所以服务端框架一直采用Springboot+dubbo的组合模式,每个服务由service模块+web模块构成,service模块通过公司API网关向安卓端暴 露restful接口,web模块通过dubbo服务向service模块获取数据渲染页面.测试环境dubbo的注册中心采用的单实例的zookeeper,随着时间的发现注册在zookeeper上的生产者和消费者越来越多,测试 人员经常在大规模的压测后发现zookeeper挂掉的现象

.net core下简单构建高可用服务集群

原文:.net core下简单构建高可用服务集群 一说到集群服务相信对普通开发者来说肯定想到很复杂的事情,如zeekeeper ,反向代理服务网关等一系列的搭建和配置等等:总得来说需要有一定经验和规划的团队才能应用起来.在这文章里你能看到在.net core下的另一种集群构建方案,通过Beetlex即可非常便捷地构建高可用的集群服务. 简述 Beetlex的Webapi集群应用并没有依赖于第三方服务,而是由Beetlex自身完成:它主要是通过Client和策略监控服务相结合的方式来实现集群化的服

2020-04-05-SpringBoot+WebSocket基于Redis订阅发布实现集群化

SpringBoot+WebSocket基于Redis订阅发布实现集群化 前面讲了单机版的websocket如何使用发送群聊(2020-03-24-springboot快速集成websocket实现群聊),那么要是部署多个服务实现集群话怎么实现呢? 由于websocket是长连接,session保持在一个server中,所以在不同server在使用websocket推送消息时就需要获取对应的session进行推送,在分布式系统中就无法获取到所有session,这里就需要使用一个中间件将消息推送到

windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分布式架构:下面将先给出整个架构的核心节点简介,希望各位多多点赞: . 架构设计图展示 . nginx+iis构建服务集群 . redis存储分布式共享的session及共享session运作流程 . redis主从配置及Sentinel管理多个Redis集群 . 定时框架Task.MainForm提

分享在Linux下使用OSGi.NET插件框架快速实现一个分布式服务集群的方法

在这篇文章我分享了如何使用分层与模块化的方法来设计一个分布式服务集群.这个分布式服务集群是基于DynamicProxy.WCF和OSGi.NET插件框架实现的.我将从设计思路.目标和实现三方面来描述. 1 设计思路 首先,我来说明一下设计思路.我们先来看看目前OSGi.NET插件框架的服务.在这里,服务不是远程服务,它是轻量级的服务,由接口和实现类组成,如下图所示.服务契约插件定义了服务接口,服务实现插件向服务总线注册服务,服务调用插件利用服务契约(接口)从服务总线获取实现的服务并调用,服务实现

RabbitMQ集群化部署

压测环境上RabbitMQ主库采用三台集群化部署,部署在172.16.103.127, 172.16.103.138, 172.16.103.129三台机器上. 安装目录:/opt/rabbitmq/rabbitmq_3.6.2 集群化部署 1.设置hosts解析,所有节点配置相同 vi /etc/hosts 172.16.103.129 mq-n129172.16.103.128 mq-n128172.16.103.127 mq-n127 2.设置节点间认证的cookiescp /root/.

kairosdb+cassandra集群化安装

kairosdb (1)到/conf目录下,找到kairosdb.properties,修改datastore为cassandra (2)设置cassandra的连接方式 (3) 设置用户名密码 4. 启动:到/bin目录下,直接跑./kairosdb.sh start,最后会看到 KairosDB service started   这样一句话,就OK了 172.16.101.25:8080 kairosdb客户端 cassandra 修改cassandra配置文件 conf/cassandr

NTP POOL PROJECT:全球最大的免费NTP服务集群

pool.ntp.org项目是一个提供可靠易用的NTP服务的虚拟集群,它作为一个大的NP服务器可以支撑全球数百万客户端使用.该项目允许那些能提供NTP服务的服务器加入到该集群中,截止2012年8月份,该NTP服务集群内已有3400台NTP服务器(其中中国大陆加入该项目的NTP服务器只有11个.),但该数量还在持续增加中. 1. 那么,如何使用poor.ntp为我们提供NTP服务呢?(How do I use pool.ntp.org?)如果你只是需要同步您的计算机时钟网络,配置文件(Linux,