49-赵成的运维体系管理课

开篇词 | 带给你不一样的运维思考

你好，我是赵成，来自美丽联合集团，集团旗下两大主力产品是蘑菇街和美丽说，我目前负责管理集团的技术服务团队。

极客时间在 QCon 上海发布之前，我接到了极客时间团队的邀请，看是否可以做一个运维专栏，当时的第一反应是略感兴奋，这还真是个意外的邀请。但是接来下我的反应就是诚惶诚恐，因为我自己写公众号也有一段时间了，深知持续高质量输出这个事情的挑战之大，特别是在输出专业文章上更是如此，所以当时一直拿不定主意。

我写公众号文章，很大程度是因为之前有过很多次公开演讲和分享，后来发现演讲所面向的受众和时间有限，分享的内容无论是在沉淀、传播以及深度上，都会受到很大的限制。总之，讲得不过瘾，索性就把一些我觉得还值得更深入探讨的话题和内容完完整整地写出来。

后来，在上海跟极客时间团队见面之后，他们给了我一些建议，因为之前的文章更多是针对一个个观点延伸出去写作，而专栏文章可以尝试更系统地输出，能够把一个运维体系讲透。这个建议从一定程度上打开了我写专栏的思路，后来我把内容规划了一下，感觉还是可以输出一些更有价值的内容，就启动了这个专栏的策划。

谈谈运维的价值

我们在大学的软件工程中就学过，从软件生命周期的角度看，软件开发阶段只占整个生命周期的 20%~30% 左右，软件运行维护阶段是最长尾的，这条规律放在当前这个时代同样适用。

在软件生命周期中，我们可以很清晰地划分出“开发阶段”和“运维阶段”，这个分界点就从开发完成代码开发，测试验收通过后，交付到运维手上的软件包开始，自此之后的阶段就是软件的运行维护阶段了。

一个公司对于开发的诉求应该是全力实现业务需求，并将需求尽快发布上线以实现商业上的收益。但是，在一个公司里，除了专注于业务需求的开发和测试角色外，还会有另外一大类开发，比如我们常见的中间件开发、稳定性开发、工具开发、监控开发、IaaS 或 PaaS 平台开发，甚至专注于底层基础架构的内核开发、网络开发、协议开发等等。

这里请你跟我一起仔细思考下，我们会发现除了业务开发和测试外，前面所提到的那些技术岗位都是为软件生命周期中的运行维护阶段服务的，这些角色的作用就是提升研发效率和稳定性，进而降低成本。虽然他们并没有全部被定义为运维岗位，但是本质上他们是跟业务软件的运行维护阶段直接相关的。

所以，从运维的范畴上来讲，我认为，一个研发团队内，除去业务需求实现层面的事情，其它都是运维的范畴，这个范畴内的事情本质上都是在为软件生命周期中的运行维护阶段服务。

我之前在外部分享，一直表达的一个观点就是，运维能力是整体技术架构能力的体现，运维层面爆发的问题或故障，一定是整体技术架构中存在问题，割裂两者，单纯地看技术架构或运维都是毫无意义的。

但是，我们在绝大多数情况下，忽略了这个隐藏在软件生命周期中真正的运维范畴，而是简单直接地从软件生命周期分段的角度，生硬地给开发和运维划定了一条界限。

也正是这样一个简单直接的界限划定，让我们将运维仅仅局限在了服务器维护、网络设备配置、软件安装维护这些最末端的职责上，而我们又期望运维这个角色能够掌控全局，不要在这个阶段出现任何问题。这就很像临渴而掘井，是不现实的。

很显然，我认为，运维思路上的转变，远比单纯提升运维技术更有价值，而运维真正的价值应该跟研发团队保持一致，真正聚焦到效率、稳定和成本上来。

而这也正是我们很多公司和团队，当前所遇到的最大的痛点和问题。所以，在我的专栏里，我会针对这些痛点和问题分享一些我的思考。

专栏内容

我的专栏内容，会聚焦在分布式软件架构下的应用运维这个领域，更多的是我对运维的一些架构思考，主要有以下四个部分。

应用运维体系建设。这是我们做运维的基础，我会分享从标准化和应用生命周期开始，如何一步步建立运维技术体系和组织架构，以及整个过程中的沟通协作等方面；分享我们应该如何树立正确的运维建设思路。

效率和稳定性等方面的最佳实践。这些是运维价值的体现，我会围绕持续交付和稳定性建设两个方面，分享如何打造不需要任何运维参与的端到端交付过程，如何在实践中锤炼出稳定性保障体系。

云计算方面的思考和实践。云计算技术的蓬勃发展为我们的业务和技术提供了更多的可能性，利用好云这个平台将会是运维升级转型的必备要求。我会分享在混合云、云存储、静态化以及 CDN 上的实践经验，以及这些实践所带来的在成本和体验上的巨大收益。

个人成长与趋势热点分析。这一部分更多的会是我个人的一些思考，包括运维技术发展趋势、团队管理、个人成长、热门事件解析、观点碰撞等。

希望在这个专栏里，能够跟你有更多的互动和交流，希望我们在观点碰撞中共同进步。

最后，开卷有益，期望能够带给你不一样的运维思考。

01 | 为什么Netflix没有运维岗位？

众所周知，Netflix 是业界微服务架构的最佳实践者，其基于公有云上的微服务架构设计、持续交付、监控、稳定性保障，都为业界提供了大量可遵从的原则和实践经验。

Netflix 超前提出某些理念并付诸实践，以至于在国内众多互联网公司的技术架构上也可以看到似曾相识的影子。当然殊途同归也好，经验借鉴也罢，这都不影响 Netflix 业界最佳实践者的地位。

同样，在运维这个细分领域，Netflix 仍然是最佳实践的典范。所以专栏的开始，就让我们一起看看世界顶级的互联网公司是如何定义运维以及如何开展运维工作的。

Netflix 运维现状

准确一点说，Netflix 是没有运维岗位的，和运维对应的岗位其实是我们熟知的 SRE（Site Reliability Engineer）。但我们知道 SRE≠运维，SRE 理念的核心是：用软件工程的方法重新设计和定义运维工作。

也就是要改变之前靠人去做运维的方式，转而通过工具体系、团队协作、组织机制和文化氛围等方式去改变，同时将之前处于研发体系最末端的运维，拉回到与开发肩并肩的同一起跑线上。

但是 Netflix 的神奇和强大之处在于，连 Google 都非常重视和大力发展的 SRE 岗位，在 Netflix 却没有几个。按照 Netflix 一位技术主管（Katharina Probst）在今年 9 月份更新的博客中所描述，在 1 亿用户，每天 1.2 亿播放时长、万级微服务实例的业务体量下，SRE 人数竟然不超过 10 个，他们称这样的角色为 Core SRE。描述具体如下：

100+ Million members. 125+ Million hours watched per day. Hundreds of microservices. Hundreds of thousands of instances. Less than 10 Core SREs.

不可否认，Netflix 拥有强大的技术实力和全球最优秀的工程师团队。按照 SRE 的理念，完全可以打造出这一系列的工具产品来取代运维和 SRE 的工作。但是能够做到如此极致，就不得不让人惊叹和好奇，Netflix 到底是怎么做到的？

为什么 Netflix 会做得如此极致？

这确实是一个很有意思的问题，带着这样的疑问，阅读了大量的 Netflix 技术文章和公开的演讲内容之后，我想这个问题可以从 Netflix 的技术架构、组织架构、企业文化等几个方面来看。

1. 海量业务规模下的技术架构和挑战

前面我也提到，Netflix 在业务高速发展以及超大规模业务体量的驱动下，引入了更为灵活的微服务架构，而且已经成为业界的最佳实践典范。

引入微服务架构后，软件架构的细化拆分和灵活多变，大大提升了开发人员的开发效率，继而也就提升了业务需求的响应和迭代速度，我想这也正是微服务思想在业界能够被广泛接受和采用的根本原因。

但是这也并不是说没有一点代价和成本，随之而来的便是架构复杂度大大增加，而且这种复杂度已经远远超出人的认知能力，也就是我们已经无法靠人力去掌控了，这也就为后续的交付和线上运维带来了极大的难度和挑战。 ￼ 这时，微服务架构下的运维就必须要靠软件工程思路去打造工具支撑体系来支持了，也就是要求微服务架构既要能够支持业务功能，还要能够提供和暴露更多的在后期交付和线上运维阶段所需的基础维护能力。

简单举几个例子，比如服务上下线、路由策略调整、并发数动态调整、功能开关、访问 ACL 控制、异常熔断和旁路、调用关系和服务质量日志输出等等，要在这些能力之上去建设我们的运维工具和服务平台。

讲到这里，我们可以看到，微服务架构模式下，运维已经成为整体技术架构体系中必不可少的一部分，而且与微服务架构相关的体系是紧密相连不可拆分的。

我们现在看到很多跟 SRE 相关的文章或内容，对于 SRE 产生原因的解释，大多是说为了缓解开发和运维之间的矛盾，树立共同的目标，让双方能够更好地协作配合。这样理解也没有太大的问题，但是我认为不够充分，或者说以上这些只能算是结果，但不是背后的根本原因。

我理解的这背后最根本的原因是，微服务架构复杂度到了一定程度，已经远远超出单纯的开发和单纯的运维职责范畴，也远远超出了单纯人力的认知掌控范围，所以必须寻求在此架构之上的更为有效和统一的技术解决方案来解决复杂度认知的问题。进而，在这一套统一的技术解决方案之上，开发和运维产生了新的职责分工和协作方式。

目前业界火热的 DevOps 理念及衍生出来的一系列话题，我们可以仔细思考一下，其实也是同样的背景和逻辑。DevOps 想要解决的开发和运维之间日益严重的矛盾，究其根本，还是微服务架构背后带来的技术复杂度在不断提升的问题。

Netflix 带给我们的启示一：微服务架构模式下，我们必须换一个思路来重新定义和思考运维，运维一定要与微服务架构本身紧密结合起来。

2. 更加合理的组织架构和先进的工具体系及理念

我上面提到，在微服务架构模式下，运维已经成为整体技术架构和体系中不可分割的一部分，两者脱节就会带来后续一系列的严重问题。

从这一点上，不得不说 Netflix 的前瞻性和技术架构能力还是很强的。因为早在 2012 年，甚至更早之前，Netflix 就已经意识到了这个问题。在组织架构上，将中间件、SRE、DBA、交付和自动化工具、基础架构等团队都放在统一的云平台工程（Cloud and Platform Engineering）这个大团队下，在产品层面统一规划和建设，从而能够最大程度地发挥组织能力，避免了开发和运维的脱节。

当然，这个团队不仅没让大家失望，还给我们带来了太多惊喜。业界大名鼎鼎的 NetflixOSS 开源产品体系里，绝大部分的产品都是这个团队贡献的。

比如持续交付系统 Spinnaker；稳定性保障工具体系 Chaos Engineering，这里面最著名的就是那只不安分的猴子，也正是这套稳定性理念和产品最大程度地保障了 Netflix 系统的稳定运行；被 Spring Cloud 引入并得以更广泛传播的 Common Runtime Service&Libraries，而且大家选用 Spring Cloud 基本就是冲着 Spring Cloud Netflix 这个子项目去的。当然还有很多其它优秀的开源产品，这里我就不一一介绍了。

Netflix 带给我们的启示二：合理的组织架构是保障技术架构落地的必要条件，用技术手段来解决运维过程中遇到的效率和稳定问题才是根本解决方案。

3. 自由与责任并存的企业文化

上面讲了这么多，看上去好像就是 SRE 常见的理念和套路，只不过 Netflix 在开源和分享上更加开放和透明，让我们有机会更多地了解到一些细节。但是为什么 Netflix 会做的如此极致呢？好像我们一直没有回答到这个问题，那这里就不得不提 Netflix 的企业文化了。

Netflix 的企业文化是 Freedom & Responsibility，也就是自由和责任并存，高度自由的同时，也需要员工具备更强的责任心和 Owner 意识。

体现在技术团队中就是，You Build It，You Run It。工程师可以随时向生产环境提交代码或者发布新的服务，但是同时你作为 Owner，要对你发布的代码和线上服务的稳定运行负责。

在这种文化的驱使下，技术团队自然会考虑从开发设计阶段到交付和线上运维阶段的端到端整体解决方案，而不会是开发就只管需求开发，后期交付和维护应该是一个叫运维的角色去考虑。No，文化使然，在 Netflix 是绝对不允许这种情况存在的，你是开发，你就是 Owner，你就要端到端负责。

所以，短短两个英文单词，Freedom & Responsibility，却从源头上就决定了团队和员工的做事方式。

Netflix 带给我们的启示三：Owner 意识很重要，正确的做事方式需要引导，这就是优秀和极致的距离。

总结

通过上面的分析，我们可以看到，Netflix 在其技术架构、组织架构和企业文化等方面的独到之处，造就了其优秀的技术理念和最佳实践。从运维的角度来说，无论是 SRE 也好，还是 DevOps 也罢，都被 Netflix 发挥到了极致。

当然，Netflix 能做到这一点，是需要非常强大的技术实力和人才储备的。当前我们虽然没法直接套用，但是这并不妨碍我们在某些经验和思路上去借鉴和学习。

比如，现在很多公司在采用了微服务架构后，就没有充分考虑到后续基于微服务架构的运维问题。而且在运维团队设置上，仍然是脱离整个技术团队，更不用说将其与中间件和架构设计等团队整合拉通去建设，自然也就谈不上在产品层面的合理规划和建设了。

因此导致的问题就是运维效率低下，完全靠人工，线上故障频发，但是处理效率又极低，开发和运维都处于非常痛苦的状态之中，运维团队和成员也会遭遇到转型和成长的障碍。

以上这些问题都很棘手，亟待解决。

通过今天的分享，我们了解了 Netflix 的技术团队运作模式和思路，不知道给你带来了哪些启示呢？

如果今天的内容对你有帮助，也请你分享给身边的朋友。

欢迎你留言与我一起讨论。

02 | 微服务架构时代，运维体系建设为什么要以“应用”为核心？

今天我来讲一下微服务架构模式下的一个核心概念：应用。

我会从这几个方面来讲：应用的起源、应用模型和应用关系模型建模以及为什么要这样做。最终希望，在微服务的架构模式下，我们的运维视角一定转到应用这个核心概念上来，一切要从应用的角度来分析和看待问题。

应用的起源

我们知道，微服务架构一般都是从单体架构或分层架构演进过来的。软件架构服务化的过程，就是我们根据业务模型进行细化的过程，在这个过程中切分出一个个具备不同职责的业务逻辑模块，然后每个微服务模块都会提供相对应业务逻辑的服务化接口。

如果解释得简单点，就一个字，拆！如下图，从一个单体工程，拆分出 N 个独立模块。

这些模块可以独立部署和运行，并提供对应的业务能力。拆分后的模块数量与业务体量和复杂度相关，少则几个、十几个，多则几十、几百个，所以为了统一概念，我们通常称这些模块为应用。

为了确保每个应用的唯一性，我们给每个应用定义一个唯一的标识符，如上图的 APP-1、APP-2 等，这个唯一标识符我们称之为应用名。

接下来，这个定义为应用的概念，将成为我们后续一系列微服务架构管理的核心概念。

应用模型及关系模型的建立

上面我们定义出来的一个个应用，都是从业务角度入手进行拆分细化出来的业务逻辑单元。它虽然可以独立部署和运行，但是每一个应用都只具备相对单一的业务职能。如果要完成整体的业务流程和目标，就需要和周边其它的服务化应用交互。同时，这个过程中还需要依赖各种与业务无直接关系、相对独立的基础设施和组件，比如机器资源、域名、DB、缓存、消息队列等等。

所以，除了应用这个实体之外，还会存在其他各类基础组件实体。同时，在应用运行过程中，还需要不断地与它们产生和建立各种各样复杂的关联关系，这也为我们后续的运维带来很多困难。

那接下来，我们要做的就是应用模型以及各种关系模型的梳理和建立，因为只有模型和关系梳理清楚了，才能为我们后面一系列的运维自动化、持续交付以及稳定性保障打下一个良好的基础。

1. 应用业务模型

应用业务模型，也就是每个应用对外提供的业务服务能力，并以 API 的方式暴露给外部，如下图商品的应用业务模型示例：

这个业务模型通常都是业务架构师在进行业务需求分析和拆解时进行设计，更多的是聚焦在业务逻辑上，所以从运维的角度，我们一般不会关注太多。

而接下来的几部分，将是运维要重点关注的内容。

2. 应用管理模型

应用管理模型，也就是应用自身的各种属性，如应用名、应用功能信息、责任人、Git 地址、部署结构（代码路径、日志路径以及各类配置文件路径等）、启停方式、健康检测方式等等。这其中，应用名是应用的唯一标识，我们用 AppName 来表示。

这里我们可以把应用想象成一个人，通常一个人会具备身份证号码、姓名、性别、家庭住址、联系方式等等属性，这里身份证号码，就是一个人的唯一标识。

3. 应用运行时所依赖的基础设施和组件

资源层面：应用运行所必需的资源载体有物理机、虚拟机或容器等，如果对外提供 HTTP 服务，就需要虚 IP 和 DNS 域名服务；

基础组件：这一部分其实就是我们所说的中间件体系，比如应用运行过程中必然要存储和访问数据，这就需要有数据库和数据库中间件；想要更快地访问数据，同时减轻 DB 的访问压力，就需要缓存；应用之间如果需要数据交互或同步，就需要消息队列；如果进行文件存储和访问，就需要存储系统等等。

从这里我们可以挖掘出一条规律，那就是这些基础设施和组件都是为上层的一个个业务应用所服务的。也正是因为业务和应用上的需求，才开启了它们各自的生命周期。如果脱离了这些业务应用，它们自己并没有单纯存在的意义。所以，从始至终基础设施和组件都跟应用这个概念保持着紧密的联系。

理清了这个思路，我们再去梳理它们之间的关系就会顺畅很多，分为两步。

第一步，建立各个基础设施和组件的数据模型，同时识别出它们的唯一标识。这个套路跟应用管理模型的梳理类似，以典型的缓存为例，每当我们申请一个缓存空间时，通常会以 NameSpace 来标识唯一命名，同时这个缓存空间会有空间容量和 Partition 分区等信息。

第二步，也是最关键的一步，就是识别出基础设施及组件可以与应用名 AppName 建立关联关系的属性，或者在基础组件的数据模型中增加所属应用这样的字段。

还是以上面的缓存为例，既然是应用申请的缓存空间，并且是一对一的关联关系，既可以直接将 NameSpace 字段取值设置为 AppName，也可以再增加一个所属应用这样的字段，通过外键关联模式建立起应用与缓存空间的关联关系。

相应地，对于消息队列、DB、存储空间等，都可以参考上面这个思路去做。

通过上面的梳理，我们就可以建立出类似下图这样的以应用为核心的应用模型和关联关系模型了，基于这个统一的应用概念，系统中原本分散杂乱的信息，最终都被串联了起来，应用也将成为整个运维信息管理及流转的纽带。

真实的情况是怎么样的？

上面讲了这么多理论和道理，但是我们业界真实的现状是怎样的呢？

从我个人实际观察和经历的场景来看，大部分公司在这块的统筹规划是不够的，或者说是不成熟的。也就是软件架构上引入了微服务，但是后续的一系列运维措施和管理手段没跟上，主要还是思路没有转变过来。虽然说要做 DevOps，但实际的执行还是把开发和运维分裂了去对待，不信你看下面两个常见的场景。

场景一

这个场景是关于线上的缓存和消息队列的。

开发使用的时候就去申请一下，一开始还能记住自己使用了哪些，但是时间一长，或者申请得多了，就记不住了。久而久之，线上就存在一堆无用的 NameSpace 和 Topic，但是集群的维护者又不敢随意清理，因为早就搞不清楚是谁用的，甚至申请人已经离职，以后会不会再用也已经没人讲得清楚了，越往后就越难维护。

根本原因，就是前面我们讲到的，太片面地对待基础组件，没有与应用的访问建立起关联关系，没有任何的生命周期管理措施。

场景二

这个典型场景就体现了应用名不统一的问题。

按照我们前面讲的，按说应用名应该在架构拆分出一个个独立应用的时候就明确下来，并贯穿整个应用生命周期才对。

但是大多数情况下，我们的业务架构师或开发在早期只考虑应用开发，并不会过多地考虑整个应用的生命周期问题，会下意识地默认后面的事情是运维负责的，所以开发期间，只要将应用开发完和将服务注册到服务配置中心上就 OK 了。

而到了运维这里，也只从软件维护的角度，为了便于资源和应用配置的管理，会独立定义一套应用名体系出来，方便自己的管理。

这时不统一的问题就出现了，如果持续交付和监控系统这些运维平台也是独立去开发的，脱节问题就会更严重。

如下图所示，一个个的孤岛，无法成为体系，当这些系统需要对接时，就会发现需要做大量的应用名转化适配工作，带来非常多无谓的工作量，所谓的效率提升就是一句空话。

所以，今天一开头我就提到，微服务架构模式下的运维思路一定要转变，一定要将视角转换到应用这个维度，从一开始就要统一规划，从一开始就要将架构、开发和运维的工作拉通了去看，这一点是与传统运维的思路完全不同的。

当然，这里面也有一个经验的问题。虽然微服务在国内被大量应用，但是我们绝大多数技术团队的经验还集中在开发设计层面。微服务架构下的运维经验，确实还需要一个总结积累的过程。我自己也是痛苦地经历了上面这些反模式，才总结积累下这些经验教训。

这也是为什么我今天分享了这样一个思路，我们要转换视角，规划以应用为核心的运维管理体系。

不知道你目前是否也遇到了类似的问题，如果今天的内容对你有帮助，也请你分享给身边的朋友。

欢迎你留言与我一起讨论。

03 | 标准化体系建设（上）：如何建立应用标准化体系和模型？

今天我专门来讲讲标准化这个工作。可以说这项工作是运维过程中最基础、最重要的，但也是最容易被忽视的一个环节。

我做过多次公开演讲，每次讲到这个环节，通常会有单独的一页 PPT，就放四个字，字号加大加粗，重复三遍，这四个字就是“标准先行”，然后演讲过程中会大声说出“标准先行，标准先行，标准先行”，重要的事情说三遍，目的就是想反复强调这件事情的重要程度，一定不要忽视。

我们运维工作的开展常常不知从何下手，或者上来就冲着工具和自动化去了，却始终不得章法，工具做了一堆，效率却并没有提升。其实绝大多数情况下，问题和原因就是标准化这个基础工作没做扎实。

首先，让我们来看看为什么标准化这个事情如此重要。

为什么要做标准化？

标准化的过程实际上就是对运维对象的识别和建模过程。形成统一的对象模型后，各方在统一的认识下展开有效协作，然后针对不同的运维对象，再抽取出它们所对应的运维场景，接下来才是运维场景的自动化实现。

这有点像我们学的面向对象编程的思想，其实我们就是需要遵循这样一个思路，我们面对的就是一个个实体和逻辑运维对象。

在标准化的过程中，先识别出各个运维对象，然后我们日常做的所有运维工作，都应该是针对这些对象的运维。如果运维操作脱离了对象，那就没有任何意义。同样，没有理清楚对象，运维自然不得章法。

比如我们说扩容，那就要先确定这里到底是服务器的扩容，还是应用的扩容，还是其它对象的扩容。你会发现，对象不同，扩容这个场景所实施的动作是完全不一样的。

如果把服务器的扩容套用到应用的扩容上去，必然会导致流程错乱。同时对于对象理解上的不一致，也会徒增无谓的沟通成本，造成效率低下。自然地，这种情况下的运维自动化不但不能提升效率，还会越自动越混乱。

这就是为什么我每次都会连续强调三遍“标准先行”的原因。虽然这个事情比较枯燥和繁琐，但是于纷繁复杂中抽象出标准规范的东西，是我们后续一系列自动化和稳定性保障的基础。万丈高楼平地起，所以请你一定不要忽略这个工作。

好，总结一下标准化的套路：

第一步，识别对象；

第二步，识别对象属性；

第三步，识别对象关系；

第四步，识别对象场景。

接下来我们就按照上面这个思路，一起来分析从基础设施层面和应用层面应该识别出哪些运维对象。

基础设施层面的标准化

基础设施层面的运维对象应该不难识别，因为都是一个个物理存在的实体，我们可以进行如下分析。

第一步，识别实体对象，主要有服务器、网络、IDC、机柜、存储、配件等。

第二步，识别对象的属性，比如服务器就会有 SN 序列号、IP 地址、厂商、硬件配置（如 CPU、内存、硬盘、网卡、PCIE、BIOS）、维保信息等；网络设备如交换机也会有厂商、型号、带宽等信息。

第三步，识别对象之间的关联关系，比如服务器所在的机柜，虚拟机所在的宿主机、机柜所在 IDC 等简单关系；复杂一点就会有核心交换机、汇聚交换机、接入交换机以及机柜和服务器之间的级联关系等，这些相对复杂一些，也就是我们常说的网络拓扑关系。

把以上信息梳理清楚，通过 ER 建模工具进行数据建模，再将以上的信息固化到 DB 中，一个资源层面的信息管理平台就基本成型了。

以服务器为例简单展示一下，我们的视角就是下面这样的：

但是，信息固化不是目的，也没有价值，只有信息动态流转起来才有价值。接下来我们需要做的事情，就是识别出针对运维对象所实施的日常运维操作有哪些，也就是识别出运维场景是什么。

第四步，还是以服务器为例，我们针对服务器的日常操作有采购、入库、安装、配置、上线、下线、维修等等。另外，可能还会有可视化和查询的场景，如拓扑关系的可视化和动态展示，交换机与服务器之间的级联关系、状态（正常 or 故障）的展示等，这样可以很直观地关注到资源节点的状态。

完成了这些工作，接下来才是对上述运维场景的自动化开发。所以你看，在真正执行去做工具和自动化平台之前，其实是需要先做好大量的基础准备工作的。我要再次强调这一点，一定不能忽视。

应用层面的标准化

下面我们再一起看一个逻辑上的对象，就是我们前面经常提到的运维的核心：应用。对这个逻辑对象的建模会相对复杂一些，不过我们依然可以按照上面的套路来。

第一步，识别对象。

我们前面讲过，这个识别过程是在做微服务架构设计或拆分的时候就确定下来的。所以严格地讲，它不应该是运维阶段才被识别出来的，而是在之前设计阶段就被识别和确认下来，然后延伸到运维这里才对。

第二步，识别对象属性。

一个应用是业务的抽象逻辑，所以会有业务和运维两个维度的属性。业务属性在业务架构时确定，这主要是需要业务架构师去识别的，但是它的运维属性就应该由运维来识别了。

下面我们一起来看一下，一个应用应该具备哪些基本的运维属性。

* 应用的元数据属性，也就是简单直接地描述一个应用的信息，如应用名、应用 Owner、所属业务、是否核心链路应用以及应用功能说明等，这里的关键是应用名；

* 应用代码属性，主要是编程语言及版本（决定了后续的构建方式），GitLab 地址；

* 应用部署模式，涉及到基础软件包，如语言包 Java、C++、Go 等；容器如 Tomcat、JBoss 等；

* 应用目录信息，如运维脚本目录、日志目录、应用包目录、临时目录等；

* 应用运行脚本，如启停脚本、健康监测脚本；

* 应用运行时的参数配置，如运行端口、Java 的 JVM 参数 GC 方式、新生代、老生代、永生代的堆内存大小配置等。

从应用属性的视角，应该是下面这样一个视图（简单示例，不完整）：

第三步，识别对象关系。

也就是应用与外部的关系，概括起来有三大类：

第一类是应用与基础设施的关系，包括应用与资源、应用与 VIP、应用与 DNS 等等的关系；

第二类是平行层面的应用与应用之间的关系，这里再细分下去就是应用服务或 API 与其它应用服务和 API 的依赖关系。如果你有相关的经验，应该会联想到全链路这样的工具平台了，没错，这样的平台就是用来处理应用间关系管理的。

第三类是应用与各类基础组件之间的关系，比如应用与缓存，应用与消息、应用与 DB 等等之间的关系。

第四步，识别应用的运维场景。

这个就会比较多了，比如应用创建、持续集成、持续发布、扩容、缩容、监控等；再复杂点的比如容量评估、压测、限流降级等。

好，这里我们先收一下，聚焦到标准化的层面，通过基础设施和应用层面标准化的示例，我想你应该可以掌握基本的建模思路了，这样的思路可以应用到其它的运维对象上 。

同时，通过上面这些内容，你应该可以比较清晰地看到，我们的每一个运维操作都是针对某个运维对象的，这一点在规划运维体系时非常重要。

而在这些对象中，应用又是重中之重，是微服务架构下的核心运维对象。

从应用标准化的过程中我们也可以看到，针对应用的识别和建模，明显复杂很多。所以，后面我还会从理论和实践的角度来继续强化和分析这个概念。

最后，给你留两个小问题。

1. 标准化部分我们提到，在规划和设计一个运维技术方案时，一定要找到对象主体，那请你思考以下问题：我们现在经常听到一些高大上的词汇，如水平扩展、弹性伸缩和自动化扩缩容等，你能否说一说这些技术手段的主体是谁，也就是是谁的水平扩展？弹性伸缩的是什么？同时，这些名词之间又有什么关系？

2. 在对象属性识别过程中，我们进行了一些关键项的举例，但是如果换一个对象，有没有好的方法论来指导我们进行准确和全面的识别，而不至于遗漏？从我们今天的内容中，你有没有发现一些规律呢？

如果今天的内容对你有帮助，也请你分享给身边的朋友。

欢迎你留言与我一起讨论。

04 | 标准化体系建设（下）：如何建立基础架构标准化及服务化体系？

前面我们一起讨论了为什么要做标准化，标准化的套路是什么，并按照套路进行了基础设施和应用的标准化示例。我想这些内容可以帮助我们举一反三，尝试着应用到实际工作中了。

今天，我继续跟你聊基础架构标准化的问题，但是今天我计划不谈如何进行架构标准化的细节，而是想强调一下基础架构标准化的重要性，因为从我个人的经历和我实际观察到的情况来看，这块的问题会更普遍一些，而这一部分又影响着后续一系列效率和稳定性平台的建设方案。

同时，如果说上次我们讲的基础设施和应用标准化是运维团队职责的话，那今天的内容就是架构、开发和运维共同的职责。

常见的分布式基础架构组件

让我们先一起列一下，微服务的分布式架构下，涉及到的主要基础架构组件有哪些。

分布式服务化框架，业界开源产品比如 Dubbo、Spring Cloud 这样的框架；

分布式缓存及框架，业界如 Redis、Memcached，框架如 Codis 和 Redis Cluster；

数据库及分布式数据库框架，这两者是密不可分的，数据库如 MySQL、MariaDB 等，中间件如淘宝 TDDL（现在叫 DRDS）、Sharding-JDBC 等。当前非常火热的 TiDB，就直接实现了分布式数据库的功能，不再额外选择中间件框架；

分布式的消息中间件，业界如 Kafka、RabbitMQ、ActiveMQ 以及 RocketMQ 等；

前端接入层部分，如四层负载 LVS，七层负载 Nginx 或 Apache，再比如硬件负载 F5 等。

上面是几类主要的基础架构组件，为了便于理解我以开源产品举例。但在实际场景中，很多公司为了满足业务上的个性化需求，会自己研发一些基础组件，比如服务化框架、消息中间件等，这个情况在有一定技术实力的公司里比较常见。不过大部分情况下，我们会基于这些开源产品做一些封装或局部的改造，以适应我们的业务。

基础架构组件的选型问题

关于基础架构组件，业界可供我们选择的解决方案和产品非常多，但是选择多了就容易挑花眼，反而不知道从何入手。我们大概都会遇到同样的问题，是自研还是选择开源产品？有这么多的开源产品到底该选哪一个？

按正常的思路，一定是先组织选型调研，然后进行方案验证和对比，最后确认统一的解决方案。

但是，由于开源产品的便利性，以及开发同学对技术探索的好奇心，实际情况往往是，整个大的技术团队中，不同的开发团队，甚至不同的开发人员，会根据开发的需要或个人喜好，选择不同的开源产品，在没有严格限制的情况下，甚至会尝试去自研。

按照我的观察，这个问题特别容易出现在微服务架构引入初期。在这个阶段，团队组织架构按照业务领域进行切分，产生一个个与业务架构匹配的小规模技术团队。

每个小团队所负责的业务相对独立，自主权就会变大，如果这个时候整个团队中没有一个强有力的架构师角色去做端到端的约束，就极其容易出现上面的这个问题，并且会一直扩散蔓延下去。

相比之下，成规模的大公司在这一点上做得就相对严格一些，当然也可能是因为之前尝过苦头，所以后来变得越来越规范了。所以这一点也是每个技术团队在引入微服务架构时要提前关注的。

我们以分布式服务化框架为例，我之前遇到的一个实际情况就是，整个大的技术团队选型时以 Java 技术栈为主，毕竟这块有很多的业界经验和产品可以借鉴参考。但是有的团队对 PHP 特别精通熟悉，就想用 PHP 去做微服务，有的团队对 Go 感兴趣，就想尝试 Go 的微服务。

从单纯的技术选型上来看，选择什么语言并没有严格的标准。而且在技术团队中，我们也应该鼓励技术多样性和尝试新技术。不过这里要有个度，我暂时先不细说这个度在哪里，我们先来看看，假设没有统一标准的约束会带来什么问题。

技术的应用，一般都会随着应用场景的逐步深入和业务体量的增长，逐步暴露出各种各样的问题，我们分两个层面来看。

1.开发层面

业务开发同学将大量的精力投入到基础组件和开源产品的研究、研发以及规模化之后的运维上，再加上产品形态的不统一，导致需要在技术层面的协作上做大量适配工作，而且经验还无法互通。

好不容易在一个产品上摸索了很长时间，踩了很多坑，积累了宝贵的经验，结果发现另外一个产品也要经历同样的一个过程，积累的经验依然不能互通和传递。

2.运维层面

当我们考虑建设一个统一的效率和稳定体系时，发现基础组件不统一，这个时候就需要做大量的针对不同组件的适配工作。

比如我们要在发布系统中做服务上下线处理，就要针对多个微服务化框架做适配。再举个稳定性上全链路跟踪的例子，为了在分布式复杂调用场景下的链路跟踪和问题定位，我们会在服务化框架中统一做打点功能，这样才不需要侵入业务逻辑。

就这样一个工作，如果服务化框架不统一，就需要到每个框架里都去开发一遍。不过现实中遇到的实际问题是，整个链路就是会有这样那样的情况而串联不起来。

如果你有过类似的经历，一定深有感受。其实各种各样奇葩的问题还远不止这些，继续演化下去，就是我们所说的架构失控了。

当我们把业务开发资源消耗在与业务开发无关的事情上，业务开发就很难聚焦于业务架构，并能够更快、更多、更好地完成业务需求，这就与公司对业务开发的诉求背道而驰了。

同时还会出现维护投入不足，那就必然导致故障频发等一系列问题，团队内部也会因为问题定位不清楚而形成扯皮推诿的不良氛围。

所以，这个时候我们需要做的，就是对基础架构有统一的规划和建设。原则上，每种基础组件只允许一种选型，至少就能满足 90% 甚至更多的应用场景。

比如数据库就只允许使用 MySQL，然后版本统一，同时配套的中间件也必须统一，其它的关系型数据库没有特殊情况坚决不允许使用，如果遇到特殊情况具体分析。

这里就举个特殊的小例子。

为了更好地满足业务个性化需求，我们的消息中间件在早期选择了自研，业务上也要求各个应用使用我们统一的服务。但是对于大数据的业务来说，很多开源产品如 Spark，都是原生与 Kafka 配套的，同时很多的新特性也都是基于 Kafka 去做的，在这种情况下就不能很生硬地要求大数据业务必须按照我们的标准来，这里还是得遵守大数据生态本身的标准才可以。

所以选型问题还是要看具体的业务和应用场景，这里只介绍大致的原则，至于具体应该如何标准化，你可以参考我们前面讲到的标准化套路去尝试梳理，先看看你梳理出来的标准化体系是什么样的，后面我也会针对案例进行分享。

基础架构的服务化

我们对基础架构组件做了统一标准之后，下一步要做的就是服务化。因为这些组件都只提供了简单的维护功能，还有很多都是命令行层面的维护，这时我们要做的就是把这些组件提供的维护 API 进行封装，以提供更加便捷的运维能力。

这里以 Redis 缓存为例。

创建和容量申请；

容量的扩容和缩容，新增分片的服务发现及访问路由配置；

运行指标监控，如 QPS、TPS、存储数据数量等等；

主备切换能力等等。

以上这些，假设都依赖 Redis 提供的原生能力来做，基本是不可维护的。所以必须要基于这些原生能力进行封装，结合运维场景，将能力服务化，这样就大大提升了使用方的便利性。

同时，我们也可以看到，这个服务化的过程其实就是 PaaS 化的过程。换言之，如果我们能把基础架构组件服务化完成，我们的 PaaS 平台也就基本成型了。

运维的职责是什么？

总结上面的过程，我们要做的事情，可以归纳为两步：第一步是基础架构标准化，第二步是基础架构服务化。

所以这个时候，运维必须要有意识去做的两件事情。

参与制定基础架构标准，并强势地约束。在这里运维作为线上稳定的 Owner，发挥约束作用有可能会比业务架构师这样的角色更为有效。另外，由于历史原因或其他种种因素造成的已有架构标准不统一的问题，是需要开发和运维共同合作去改造的。这里面如何保持良好的协作，制定统一的路线图也是非常重要的。所以这里强制约束是一方面，同时也要提供工具化的手段来支持开发的改造，也就是下面这个动作。

基础架构的服务化平台开发，目标是平台自助化，让开发依赖平台的能力自助完成对基础组件的需求，而不是依赖运维的人。这个事情是驱动运维转型和改进的动力，也是运维能够深入了解架构组件细节的有效途径。同时，要注意到，如果不朝着服务化方向发展，运维将始终被拖累在这些基础组件的运维操作上。

今天我们讨论的这个话题，我也和很多同行、专家交流过，发现大家都有相同的痛点，但是业界的架构资料和图书中很少涉及到这一部分的内容。我觉得根本上还是经验意识上的缺失，所以结合自己的经验专门整理出来，也很期待听到你的经验和想法。

如果今天的内容对你有帮助，也请你分享给身边的朋友。

欢迎你留言与我一起讨论。

05 | 如何从生命周期的视角看待应用运维体系建设？

还记得上周我们在讲标准化体系建设（上）的最后，我留了两个小问题，其中一个是这样的：

在对象属性识别过程中，我们进行了一些关键项的举例，但是如果换一个对象，我们有没有好的方法论来指导我们进行准确和全面的识别，而不至于遗漏？从我们今天的内容中，你有没有发现些规律呢？

这个问题的答案其实就是我们今天要讨论的内容，那就是从“应用生命周期管理”的角度分阶段去梳理。

简单理解下来就是，对于一个对象，既然有生命周期，就会有不同的生命周期阶段，那这个对象在不同的阶段，可能就会具备不同的属性、关系和场景。只要我们把一个对象的生命周期阶段理清楚了，顺着这条主线分阶段进行分解，就可以分析得更加清晰、明确和具体了。

怎样理解生命周期

谈到生命，首先就会联想到我们自己，所以这里以人做一个简单的类比。我们人类从出生到死亡，就是一个生命周期，在这个周期的每一个阶段，我们都会有不同的属性、关系和所要面对的场景。

比如从人的学生时代开始，作为学生，我们就会具备学生的属性，会有所属学校、所属年级、所属班级、所属学号等等。这个时候我们周边的关系更多的是同学关系和师生关系。我们面临的场景可能就是读书、做作业和考试。当然学生时代细分下去还会有小学生、中学生、大学生以及研究生等阶段，每个阶段里面又会有不同的细分属性以及所要面临的场景，比如大学生毕业，就面对求职的场景等。

当一个学生毕业走入职场之后，这个时候就开启了生命周期里的另一个阶段，那就是职场生涯。这个时候我们身上的属性又发生了变化，具备所属公司、所谓职位、所谓层级等。这个时候的关系也更为复杂，如同事关系、上下级关系以及各种各样的社会关系。我们所面临的场景也变得复杂，要完成工作、晋升考核、领取薪酬以及离职跳槽、再次面试等等。

再往后，我们到了一定年纪，成为老年人，又会有老年人的属性、关系和场景，这里就不详细列举了。

围绕着人类的生命周期，我们国家和社会提供的解决方案，就必须要有一系列对应的教育体系、职业体系、医疗体系、养老体系等。目的就是针对人生的不同阶段，提供不同形式的保障和支持，让每个人在社会体系下都够正常生存并发挥出自己的价值。

从上面的分析我们可以看到，人这个对象，在不同的生命周期阶段中，会有不同的角色属性和外部关系，同时要面对的社会和生存场景也不一样。所以，当我们谈论人这个对象的时候，一定是把这个对象放到具体的某个生命周期阶段中，才会有意义。

应用的生命周期分析

回到我们运维对象的生命周期上来，我们所面对的这些对象就相对规范、标准很多。

当一个场景下有多个对象时，就一定要找到那个核心的运维对象，这个核心对象的生命周期就会涵盖其它附属运维对象的子生命周期。结合我们前面讲过的内容，微服务架构下，一切要以应用核心。因此，我们就找到了整个运维体系，或者说软件运行阶段的核心对象，那就是应用。

应用就类似于我们社会中的人，凡事都会以人为本，这里就是要以应用为本。那接下来按照上面我们对一个人的生命周期的阶段分解，我们也可以对应用的生命周期阶段进行分解，大致分为五个部分，应用的创建阶段、研发阶段、上线阶段、运行阶段和销毁阶段。我们依次来分析看一下。

1. 应用的创建阶段

这个阶段，最重要的工作，是确认应用的基础信息和与基础服务的关系，要同时固化下来，从应用创建之初，就将应用与各类基础服务的生命周期进行挂钩。

应用的基础信息，可以参考之前我们讲标准化的部分，基本上已经涵盖了比较全的信息，你可以按照生命周期的思路，再理解一下并做梳理。

对于同一类的应用，只需要做一次标准化即可，后续完全可以形成模板固化到工具平台上。

同时，另外一个很重要的工作，就是要开启与应用相关的各类基础服务的生命周期。比如这个应用需要用到缓存、消息队列和 DB 等，也可能需要域名 DNS 服务、VIP 配置等，这些就要从应用创建这个动作延伸出去，启动这些关联基础服务的创建，比如需要缓存就去申请容量空间，需要消息队列要申请创建新的 Topic 等等。

当然一个应用使用到哪些基础服务，应该是在架构设计和编码阶段就确定下来的，这里做的事情，就是把这些信息通过应用关联起来，与应用的生命周期挂钩。

2. 应用的研发阶段

应用的研发阶段主要是业务逻辑实现和验证的阶段。针对业务逻辑层面的场景就是开发代码和质量保证，但是这个过程中就会涉及到代码的提交合并、编译打包以及在不同环境下的发布部署过程。同时，开发和测试在不同的环境下进行各种类型的测试，比如单元测试、集成测试以及系统测试等等，这整个过程就是我们常说的持续集成。

所以，这个阶段，我们要做的最重要的一个事情，就是为研发团队打造完善的持续集成体系和工具链支持，在后面我们会有专门一个部分讲解这个过程。

3. 应用的上线阶段

这是个过渡阶段，从应用创建过渡到线上运行。创建阶段，应用的基础信息和基础服务都已经到位，接下来就是申请到应用运行的服务器资源，然后将应用软件包发布上线运行，这个动作在下面的运行阶段也会持续迭代，我们直接看下面这个阶段。

4. 应用的运行阶段

这是应用生命周期中最重要、最核心的阶段。

从运维角度来看，应用在线上运行起来之后就已经变成一个线上运行的进程，那这个进程形态的应用应该有什么样的属性呢？你可能已经联想到，这个时候需要应用线上运行的各种指标的输出。所以这个阶段，应用最重要的属性就是应用本身以及相关联的基础服务的各项运行指标。

这里，我们就需要制定每个运维对象的 SLI、SLO 和 SLA，同时要建设能够对这些指标进行监控和报警的监控体系。

从业务角度看，应用是线上业务逻辑的执行载体，但是我们的业务需求是在不断变化和迭代的，所以就需要不断地去迭代更新我们的线上应用，这里仍然会依赖到上述应用研发阶段的持续集成过程，并最终与线上发布形成持续交付这样一个闭环体系。

从运行阶段应用的关系看，除了它跟基础服务之间相对固化的关系外，应用跟应用、以及应用包含的服务之间的调用关系也非常重要，而且这个关系可能随时都在变化，这个时候，我们应用之间依赖管理和链路跟踪的场景就出现了。

同时，应用线上运行还会面临外部业务量的各种异常变化，以及应用自身所依赖的基础设施、基础服务以及应用服务的各种异常状况。比如“双 11”大促，外部流量激增；微博上热点事件带来的访问量剧增；或者服务器故障、IDC 故障，DB 故障；再或者服务层面 API 的报错等等。这时就出现了线上稳定性保障的场景，比如流量激增时的限流降级、大促前的容量规划、异常时的容灾、服务层面的熔断等等。

通过上面的这个分析过程，我们可以看到，日常接触到的各种技术解决方案，都是在解决应用生命周期不同阶段中应用自身或者应用与周边关系的问题，或者是所面对的场景问题。

5. 应用的销毁阶段

这一部分就不难理解了。如果应用的业务职责不存在了，应用就可以下线销毁了。但是这里不仅仅是应用自身要销毁，我们说应用是整个运维体系的核心，所以围绕着某个应用所产生出来的基础设施、基础服务以及关联关系都要一并清理，否则将会给系统中造成许多无源（源头）的资源浪费。

我们在日常工作中，经常见到的缓存系统中，很多 NameSpace 不知道是谁的，消息系统中有很多 Topic 不知道是谁的，但是又不敢随意乱动，就只能让它无端占用着系统资源。

执行应用的销毁这一步动作，其实是取决于最前面应用与基础服务的关系模型分析和建设是否做得足够到位。

总结

今天我们分析了应用的生命周期，再结合之前讲的标准化内容，我们就找到了做运维架构的切入点，套路也就有了，总结一下就是：

从生命周期入手，划分阶段，提炼属性，理清关系，固化基础信息，实现运维场景。

同理，这个思路还可以运用到基础设施和基础服务对象的生命周期管理中，虽然它们只是子生命周期，但是具体到每个基础服务上面，同样需要这个管理手段和过程。

我已经介绍了很多和应用相关的内容，很大一部分的原因是希望能够帮助你梳理好思路，在思考问题和设计解决方案的时候，一定要从实际出发、从问题出发、从基础出发，理清自己的需求和痛点，然后再去寻求解决方案。

借鉴业界思路，千万不要一上来就去套用别人的解决方案。因为别人的思路和解决方案往往是建立在一个非常稳固的基础之上的，而这些基础，往往又因为太基础、太枯燥、太不够酷炫，所以常常是一带而过，甚至是略去不讲的。一旦忽略了这一点，再优秀的解决方案也是无源之水，无本之木，是实现不了的。

独立思考非常重要，共勉！

如果今天的内容对你有帮助，也请你分享给身边的朋友。

欢迎你留言与我一起讨论。

07 | 聊聊CMDB的前世今生

我们前面在讲标准化的时候，对关键的运维对象做了识别，主要分为两个部分：

基础设施层面：IDC 机房、机柜、机架、网络设备、服务器等；

应用层面：应用元信息、代码信息、部署信息、脚本信息、日志信息等。这两部分是整个运维架构的基础部分，运维团队是维护的 Owner，需要投入较大的精力去好好地规划建设。

当我们识别出运维对象和对象间的关系，并形成了统一的标准之后，接下来要做的事情就是将这些标准固化，固化到某个信息管理平台中，也就是我们常说的配置管理，专业一点就叫作 CMDB（Configuration Management DataBase）。

其实，如果我们找准了需求和问题在哪里，你会发现技术手段和平台叫什么就真的不重要了，只要是内部能够达成一个统一共识的叫法就好。

关于如何打造 CMDB 和应用配置管理，我之前有一篇公开的文章《有了 CMDB，为什么还需要应用配置管理》，写得已经比较细致了，会在下一期发布出来，但不占用我们专栏的篇幅。

今天我主要来聊一聊 CMDB 的前世今生，帮助你更加深刻地理解这个运维核心部件，对我们后面开展 CMDB 的建设大有裨益。

CMDB 源起

CMDB 并不是一个新概念，它源于 ITIL（Information Technology Infrastructure Library，信息技术基础架构库）。而 ITIL 这套理论体系在 80 年代末就已经成型，并在当时和后来的企业 IT 建设中作为服务管理的指导理论得到广泛推广和实施。但是为什么这个概念近几年才被我们熟知？为什么我们现在才有意识把它作为一个运维的核心部件去建设呢？

我想主要有两个因素，一个起了限制作用，一个起了助推作用。

CMDB 这个概念本身的定义问题，限制了 CMDB 的实施；

互联网技术的发展驱动了运维技术的发展和演进，进而重新定义了 CMDB。

传统运维思路下的 CMDB

我们先来看下第一个原因，按照 ITIL 的定义：

CMDB，Configuration Management DataBase，配置管理数据库，是与 IT 系统所有组件相关的信息库，它包含 IT 基础架构配置项的详细信息。

看完上面这个描述，我们能感觉到，这是一个很宽泛的概念描述，实际上并不具备可落地的指导意义。事实上也确实是这样，稍后我们会讲到。

同时，CMDB 是与每个企业具体的 IT 软硬件环境、组织架构和流程强相关的，这就决定了 CMDB 一定是高度定制化的体系。虽然我们都知道它不仅仅是一个存储信息的数据库那么简单，但是它的具体形态是什么样子的，并没有统一的标准。

从传统 IT 运维的角度来看，运维的核心对象是资源层面，所谓的基础架构也就是网络设备和硬件设备这个层面；各种关联和拓扑关系，基本也是从服务器的视角去看。所以更多地，我们是把 CMDB 建设成为一个以设备为中心的信息管理平台。

这也是当前绝大多数公司在建设运维平台时最优先的切入点，因为这些运维对象都是实体存在的，是最容易被识别的和管理的；像应用和分布式中间件这种抽象的逻辑对象反而是不容易被识别的。

这种形态，如果是在软件架构变化不大的情况下，比如单体或分层架构，以服务器为中心去建设是没有问题的。因为无论设备数量也好，还是申请回收这些变更也好，都是很有限的，也就是整个 IT 基础设施的形态变化不大。

我没有专门调研过国外的实施情况，但就国内的情形，谈下我的经历。

早期，大约是在 2009~2013 年，我接触了一个省级运营商的全国性项目。2012 年的时候日 PV 就到了 5 亿左右，日订单创建接近 2000 万。分层的软件架构，不到千台服务器，对于资源的管理，仍然是用 Excel 表格来记录的。

运维基于这样一个表格去管理和分配各种资源，问题也不算太大。究其根本，就是基础设施层面的架构形态相对稳定，有稳定的软件模块数量和架构。但是发展到后来，这样的软件架构无法满足业务的快速迭代，还是做了架构上的拆分，这就是后话了。

这里我想表达的是，在那个时期，即使是在 IT 架构相对先进的运营商体系下面，我也没有太多地听说过 CMDB 这个概念，包括运营商自身，以及为运营商提供整体技术解决方案的厂商，还有来自方方面面的资深架构师和咨询师等，在做系统架构和运维架构设计时，没有人提及过 CMDB，也没有人提出把它作为核心部件去建设，更多的都是从 ITIL 管理服务的流程体系去给出咨询建议；在落地实施的时候，我们最终见到的大多是一条条的流程规范和约束，后来增加的也多是流程和审批，甚至是纸质的签字审批。

这也从一个侧面说明，CMDB 在那个时期更多的还是停留在概念阶段，甚至是无概念状态，也没有什么最佳实践经验的传承，CMDB 这个概念本身并不具备实践意义，管理的方式方法也就停留在原始的 Excel 表格中。

高大上的 ITIL 体系更多的是被当做流程规范来落地的，真正体现在技术方案和技术产品上的落地并不多。我想这是实施过程中对 ITIL 理解和运用的一大误区。

接下来，我们看第二个原因，也就是互联网运维的助推力。

互联网运维体系下的 CMDB

值得庆幸的是，进入到互联时代，随着互联网运维力量的崛起，CMDB 这个概念也真正地得到了落地实践，从理论概念的方法论阶段过渡到了具备具体技术方案的可实施阶段，而且得到了业界的持续分享和传播。我们现在能够看到的 CMDB 经验分享，基本上都是中大型互联网公司的运维最佳实践。

不过，值得注意的是，“此 CMDB”已经非“彼 CMDB”。我们前面提到，传统运维阶段，我们更多是以设备为核心进行管理，但是到了互联网技术阶段，这个核心就变了，变成了应用这个核心对象。

至于原因，我们前面已经讲过，主要还是互联网技术的快速发展，大大推进了微服务技术架构的落地和实践，这种场景下，应用各维度的管理复杂度、应用的复杂度就逐渐体现出来了，所以我们的很多运维场景就开始围绕着应用来开展。

与此同时，云计算技术也在蓬勃发展，逐步屏蔽了 IDC、网络设备以及硬件服务器这样的底层基础设施的复杂度，有公有云或私有云厂商来专注聚焦这些问题，让我们的运维不必再花过多的精力在这些基础设施上面；同时，单纯以硬件为核心的 CMDB 形态也被逐步弱化。

所以，此时的 CMDB，仍然可以叫做配置管理数据库，但是这个配置管理的外延已经发生了很大的变化。之前所指的简单的硬件资源配置管理，只能算是狭义的理解；从广义上讲，当前的应用以及以应用为核心的分布式服务化框架、缓存、消息、DB、接入层等基础组件，都应该纳入这个配置管理的范畴。

所以在这个时期，我们提到的运维自动化，远不是自动化的服务器安装部署交付或网络自动化配置这种单一场景，而是出现了持续交付、DevOps、SRE 等更适合这个时代的对运维职责的定义和新的方法论。

到了这个阶段，传统运维思路下的 CMDB，因为管理范围有限，可以定义为狭义上的 CMDB；而互联网运维思路下的 CMDB 外延更广，我们称它为广义的 CMDB。新的时期，对于 CMDB 的理解也要与时俱进，这个时候，思路上的转变，远比技术上的实现更重要。

CMDB 进行时

如果我们仔细观察，会发现一个很有意思的现象。CMDB 源于 80 年代末的 ITIL，源于传统 IT 运维阶段，但真正让它发扬光大的，确是新兴的互联网运维行业，而且现在很多的传统行业也在向互联网学习运维技术。

与此同时，在中大型的互联网公司中，比如阿里和腾讯，也越来越重视流程规范的管控，开始更多地将严格的流程控制与灵活的互联网运维技术结合起来，以避免在过于灵活多变的环境下导致不可控的事件发生。

所以，从这里我们可以看到，并不是说 ITIL 的重流程体系就一定是过时老旧的，也不是说互联网运维技术就一定代表着最先进的技术趋势，而是在这个过程中，不同体系相互借鉴、相互学习、共同进步和发展，在碰撞的过程中，催生出更适合这个时代的技术体系。

这确实是一个充满了机遇和挑战、但又不乏乐趣的新时代。

今天我们讲了 CMDB 的前世今生，我所讲到的对 ITIL 以及其定义下的 CMDB 的理解，更多的是根据我个人的早期经历，还有和业界同行交流的经验所得，我自己并没有完整系统地学习过，所以理解上和见识上会有一定的局限，也期望你能批评指正，我们一起讨论、共同进步。

如果今天的内容对你有帮助，也请你分享给身边的朋友，我们下期见！

08 | 有了CMDB，为什么还需要应用配置管理？

今天我们分享的主题是：有了 CMDB，为什么还需要应用配置管理？

你不妨先停下来，思考一下这个问题。

我抛出的观点是： CMDB 是面向资源的管理，应用配置是面向应用的管理。

请注意，这里是面向“资源”，不是面向“资产”，资源 ≠资产。

CMDB 是面向资源的管理，是运维的基石

我们一起来梳理一下，在建设运维的基础管理平台时通常要做的事情。

第 1 步，把服务器、网络、IDC、机柜、存储、配件等这几大维度先定下来；

第 2 步，把这些硬件的属性确定下来，比如服务器就会有 SN 序列号、IP 地址、厂商、硬件配置（如 CPU、内存、硬盘、网卡、PCIE、BIOS）、维保信息等等；网络设备如交换机也会有厂商、型号、带宽等等；

第 3 步，梳理以上信息之间的关联关系，或者叫拓扑关系。比如服务器所在机柜，虚拟机所在的宿主机、机柜所在 IDC 等简单关系；复杂一点就会有核心交换机、汇聚交换机、接入交换机以及机柜和服务器之间的级联关系；

第 3.5 步，在上面信息的梳理过程中肯定就会遇到一些规划问题，比如，IP 地址段的规划，哪个网段用于 DB，哪个网段用于大数据、哪个网段用于业务应用等等，再比如同步要做的还有哪些机柜用于做虚拟化宿主机、哪些机柜只放 DB 机器等。

以上信息梳理清楚，通过 ER 建模工具进行数据建模，再将以上的信息固化到 DB 中，一个资源层面的信息管理平台就基本成型了。

但是，信息固化不是目的，也没有价值，只有信息动态流转起来才有价值（跟货币一样）。接下来我们可以做的事情：

第 4 步，基于这些信息进行流程规范的建设，比如服务器的上线、下线、维修、装机等流程。同时，流程过程中状态的变更要同步管理起来；

第 5 步，拓扑关系的可视化和动态展示，比如交换机与服务器之间的级联关系、状态（正常 or 故障）的展示等，这样可以很直观地关注到资源节点的状态。

至此，从资源维度的信息梳理，以及基于这些信息的平台和流程规范建设就算是基本成型了。这个时候，以服务器简单示例，我们的视角是下面这样的： ￼￼

￼

应用配置管理是面向应用的管理，是运维的核心

上面说明了 CMDB 的基础信息部分，如果从传统的 SA 运维模式，这些信息已经足够，但是从应用运维的角度，这些就远远不够了。

这时我们就需要一个非常非常重要的句柄：应用名，或者叫应用标识。至此，应用运维里面最最重要的一条联系也就产生了：“应用名 -IP“的关联关系（这里也可以是定义的其它唯一主机标识，如主机名、容器 ID 等等，因为我们使用的方式是 IP，所以这里就以 IP 示例）。

之所以说“应用名”和“应用名 -IP 关联关系”非常重要，是因为它的影响力不仅仅在运维内部，而是会一直延伸到整个技术架构上。后面我们会介绍到的所有平台和系统建设，都跟这两个概念有关。

CMDB 是 IP 为标识的资源管理维度，有了应用名之后，就是以应用为视角的管理维度了。首先看一下应用会涉及到的信息：

应用基础信息，如应用责任人、应用的 Git 地址等；

应用部署涉及的基础软件包，如语言包（Java、C++、GO 等）、Web 容器（Tomcat、JBoss 等）、Web 服务器（Apache、Nginx 等）、基础组件（各种 agent，如日志、监控、系统维护类的 tsar 等）；

应用部署涉及的目录，如运维脚本目录、日志目录、应用包目录、临时目录等；

应用运行涉及的各项脚本和命令，如启停脚本、健康监测脚本；

应用运行时的参数配置，如 Java 的 jvm 参数，特别重要的是 GC 方式、新生代、老生代、永生代的堆内存大小配置等；

应用运行的端口号；

应用日志的输出规范；

其他。

上面的梳理过程实际就是标准化的过程。我们梳理完上述信息后就会发现，这些信息跟 CMDB 里面的资源信息完全是两个维度的东西。所以从信息管理维度上讲，把资源配置和应用配置分开会更清晰，解耦之后也更容易管理。

好了，按照上面 CMDB 说的套路，梳理完成后，就是要进行信息的建模和数据的固化，这时就有了我们的“应用配置管理”。再往后，就是基于应用配置管理的流程规范和工具平台的建设，这就涉及到我们经常说的持续集成和发布、持续交付、监控、稳定性平台、成本管理等等。

从应用的视角，我们配置管理，应该是下面这样一个视图（简单示例，不是完整的）：

￼ 好了，有了资源配置信息和应用配置信息，这两个信息应该怎么统一管理起来呢。直接看图：

至此，CMDB 和应用配置管理的分层分解就完成了，应用名关联着应用配置信息，IP 关联着资源信息，二者通过“应用名 -IP”的对应关系，联系到一起。

总结

CMDB 是运维的基石，但是要发挥出更大的价值，只有基础是不够的，我们要把更多的精力放到上层的应用和价值服务上，所以我们说应用才是运维的核心。

你可以看到，如果仅仅基于 CMDB 的资源信息作自动化，最多只能做出自动化的硬件资源采集、自动化装机、网络 - 硬件拓扑关系生成等资源层面的工具，这些工具只会在运维层面产生价值，离业务还很远，就更谈不上给业务带来价值了。

但是基于应用这一层去做，就可以做很多事情，比如持续集成和发布、持续交付、弹性扩缩容、稳定性平台、成本控制等等，做这些事情带来的价值就会大大不同。

以上就是我抛出的观点，CMDB 是面向资源的管理，应用配置是面向应用的管理。希望能够抛砖引玉，听到更多你的观点和反馈。

如果今天的内容对你有用，也希望你分享给身边的朋友，我们下期见！

09 | 如何在CMDB中落地应用的概念？

我们前面讲了应用是整个微服务架构体系下运维的核心，而 CMDB 又是整个运维平台的基石。今天我就讲讲在 CMDB 中如何落地应用这个核心概念，以及如何建立应用集群分组的思路。

如何有效组织和管理应用

微服务架构下会有很多应用产生出来，少则十几、几十个，多则上百甚至上千个。这时我们面临的第一个问题就是如何有效地组织和管理这些应用，而不是让它们在各处散乱，命名方式和层次结构可能还不统一。

你可能接触过“服务树”的概念，这个提法是小米在早期互联网运维实践的分享中传播出来的。我第一次听到这个概念是在 13 年阿里技术嘉年华大会上听小米运维的分享。再往前，这个概念应该是从百度的运维体系中借鉴出来的。

这里的服务实际对应的就是我们前面提到的应用这个概念。据我了解，在阿里和腾讯都是叫作应用，现在业界比较通用的叫法也是应用。其实叫什么并不重要，关键还是要学习到对这个概念的管理方式。

从服务树这个名字中，我们就可以了解到，有效组织和管理应用的方式，就是把它组织成一个树形的层次结构。这种管理模式，无论是在 BAT，还是在其它的互联网公司，基本都是一样的思路和模式，所以叫法虽然不同，但是思路上却是相通的，可谓异曲同工。

基于业务维度的拆分，对应产生了我们的应用拆分原则。比如对于电商公司，大的维度会有电商、支付、广告、流量和搜索等业务领域；进一步，电商业务领域里最典型的会有用户、会员、商品、交易、商家、店铺以及物流等；这里面还可以再进一步细分，比如商品会有详情、SKU、SPU、库存、评价、标签等。

讲到这里，我们再看一下技术团队的组织架构，基本上是对应着整个业务技术架构的拆分的。也就是业务架构决定了技术架构，而技术架构又决定了一个研发团队的组织架构，这个组织架构中不同的团队单元分别承担着对应业务的需求开发和实现职责。

上面这个组织架构建设的逻辑和思路，也是我们在组建团队和职责划分时可以参考的。

这样一个逻辑讲下来，我们的应用管理思路其实也就明晰了：产品线 - 业务团队 - 应用。

这里举个电商商品的例子就是：电商技术 - 商品团队 - 商品中心 - 商品详情等。

￼

当然因为每个公司对组织架构定义的方式不同，也可以用一、二级部门这样的方式来指代。但是具体团队的分工和职责，一定是来自于业务架构决定的技术架构，只有这样，各业务团队才会职责清晰，配合协作才会顺畅起来。

对于应用名定义，要设定规范，比如：

应用名必须以大小写英文字母以及下划线组合；

应用名长度不超过 40 个字符，尽量简单易懂；

不允许出现机房代号和主机名称这样的信息。

简单举例，商品中心命名为 itemcenter，商品详情命名为 detail。

这里做个小结：到了软件运维阶段，运维工作是否可以高效地组织开展，很大程度上，在前面的业务架构拆分阶段就决定了。也就是业务架构拆分得是否合理、职责是否明晰，决定了后续团队组织架构是否合理、团队职责是否明晰。如果这点没做好，到了运维阶段必然就是混乱的。

这一点我在开篇词中也提到过，运维能力的体现，一定是整体技术架构能力的体现，割裂两者单独去看，都是没有意义的。同时，对于当前仍然把运维割裂建设的研发团队，也需要去思考一下在组织架构建设上的合理性了。

应用的集群服务分组建设

上述讲到的是应用的组织管理，看上去逻辑思路相对清晰，组织起来也不复杂，但是再往下，应用的集群服务分组建设就会相对复杂了。

为什么会有集群服务分组呢？我们一起来看这么几个需求场景。

场景一：多环境问题。

我们常见的环境会有开发联调环境、集成测试环境、预发环境、线上环境等等。后面我们讨论持续交付时会讲到，实际场景下所需要的环境会更多。

场景二：多 IDC 问题。

对于大型互联网业务，会做业务单元化，或者有海外业务拓展需求的场景，我们会在多个 IDC 机房部署应用，应用代码是相同的，但是配置可能会不同。

场景三：多服务分组问题。

这个场景就跟具体业务场景相关了。举个例子，比如商品中心 IC 这样一个核心应用，对外会有商品详情、交易下单、订单、购物车、评价、广告、秒杀活动、会场活动、商家、店铺等一系列应用依赖它，但是这些依赖它的应用优先级是不一样的。

核心应用和非核心应用：比如交易支付链路上的应用属于核心应用，任何时候都必须要优先保障，但是对于评价、商家和店铺这些应用优先级就低一些。反过来理解就是一个应用出现故障，是不是会影响业务收入，如果影响就属于核心应用，如果不是或者影响非常小，那就属于非核心应用。所以 IC 这个应用下面，就会有 IC 的交易分组，IC 的广告分组、IC 的电商分组等，这些分组就会相对固定和静态。

场景因素决定。这个对于电商就会比较典型，比如大促时的秒杀场景，对于参加秒杀活动的商品，瞬时的访问量就会非常大，而不参加活动的商品就不会有这么大的访问量。所以这时为了隔离较大的流量，就需要有多个不同的秒杀 IC 分组，从资源层面进行隔离；同时上层秒杀活动的应用在配置中心配置依赖时，就要配置到对应的秒杀 IC 集群分组上，这样即使秒杀 IC 出现问题，也不会影响正常的商品 IC 访问。所以根据场景，不同阶段就会有 IC 的大促秒杀分组，这种类型的分组就需要根据实际的业务场景来决定，是个动态调整的过程，需要开发和运维一起来讨论和验证。

一般情况下，集群服务分组会有以上三个维度中的一个或多个来决定。还是以商品中心 IC 为例，按照上面的介绍，就会对应如下关系：

￼

至此，“应用 - 集群服务分组 - 资源”的对应关系就建立起来了。这里我们叫它“应用树”或者“服务树”都可以，不管叫什么，这个信息是 CMDB 中最为关键和核心的信息。为什么是最关键和核心的呢？

CMDB 在基础服务体系中的核心位置

这里我们以应用为核心来看，CMDB 中会保存“应用 - 分组 - 资源”的对应关系，这个关系对于周边系统来说都是需要的，举例如下。

1.监控系统。

我们需要以上的对应关系，监控到每个应用、每个集群以及每台机器上的关键信息。

2.发布系统。

我们需要将每个应用对应的代码进行编译打包，然后发布到对应集群的主机上，也需要这个对应关系，这一点我在后面的持续交付中还会讲到。

3.服务化框架。

需要依赖应用和集群分组两个信息，其中主要是对应用名和集群分组名的依赖，对于服务化框架来说，更多的是通过其配置管理中心注册的应用名，来实现应用的服务和 API 管理，这里要做到与 CMDB 统一。同样，像 LVS 和 Nginx 这样的四七层负载，以及 ZK 这样的开源分布式配置管理，凡是涉及服务注册、服务发现以及服务上下线的基础服务，都是类似思路。

4.基础服务中。

如分布式 DB、分布式缓存和消息等，就需要应用的应用名，以及应用与资源 IP 的对应关系，或者集群分组与 IP 的对应关系。

应用名，是因为要建立应用与分布式服务实例之间的关系。如应用与缓存 NameSpace 的对应关系，应用与消息 Topic 的对应关系等，以便于这些基础服务的生命周期管理和自动化开发。

应用与资源的对应关系，是因为有些核心资源是要做 ACL 访问控制的。比如对于用户、交易或支付这样非常敏感的数据，它们对应的数据库就不允许随意连接，而应该是仅限于授权过的应用访问。这时就要针对应用对应的 IP 地址进行白名单配置。一方面，可以通过分布式 DB 中间件进行配置；另一方面，也可以通过在 DB 层面进行设置，比如 MySQL 就可以直接配置白名单策略；同时也可以在机器的 iptables 上配置，至于如何配置就看具体需求了，但是无论怎样，应用与资源的对应关系是非常重要的。

5.稳定性保障平台，或者叫服务治理平台。

针对系统的稳定性，我们会在应用中做很多的降级限流和开关预案策略，这些都是跟应用直接关联的。而且按照我们前面介绍的，不同的集群分组，策略可能会有不同，所以又会跟集群分组相关。同时，这些策略最终下发到具体服务器上运行的应用实例上，所以这里就会需要应用、集群分组以及对应的资源关系。

总结一下，简单示意图如下：

总结

通过上述的分析，我们可以看到基于以应用为核心的 CMDB 中，又衍生出“应用 - 集群服务分组 - 资源”这样一个运维体系中的核心关系。经过这三部分的分析，我们之前所说的基于应用为核心的运维视图就可以建立出来了，我们再次示意如下：

￼

今天我们讨论的内容提到了，监控、发布、基础服务以及稳定性平台会依赖 CMDB 中“应用、集群服务分组 - 资源”的对应关系信息，但是当 CMDB 中的这些关系信息发生变化，比如新增一个 IP，或者下线一个 IP，这些信息是如何传递到其它平台的呢？这些平台又是如何查询这些关键信息的呢？欢迎你留言与我一起讨论。

如果今天的内容对你有帮助，也请你分享给身边的朋友，我们下期见！

10 | 如何打造运维组织架构？

前面几周，我们介绍了 Netflix 为什么没有运维岗位、应用运维标准化、基础服务标准化以及从应用生命周期的角度如何进行运维建设等内容。这一周我们就来聊聊在组织架构和运维转型方面的话题。

Netflix 给我们的启示

专栏的第一篇我们就介绍了 Netflix 的云平台组织架构，你应该可以发现，Netflix 其实已经给我们提供了一个非常好的思路和方向，就是在提供基础服务能力的同时，提供对应的自助化运维能力。也就是说，开发人员可以在这样一个平台上完成自己想要做的任何运维操作，而不再依赖运维的人。

我们最应该学习和借鉴的，也恰恰是我们绝大多数团队都会忽略的，就是要做好运维和整个技术架构体系的融合，一定不要割裂两者。同时，还要注意不仅仅是促进组织架构层面的融合，最重要的是要促进职能协作上的融合。

应该怎么理解呢？

我先撇开组织架构，大致说一下我的思路。开篇词中我提到，运维能力的体现，一定是整体技术架构能力的体现。所以，要想做好运维就一定要跳出运维这个框框，从全局的角度来看运维，要考虑如何打造和体现出整个技术架构的运维能力，而不是运维的运维能力。这一点是根本，一定要注意。如果我们仍然片面地从运维的角度看运维，片面地从运维的角度规划运维，是无法走出运维低价值的困局的。

从价值呈现的角度看运维

当我改变了这个认知后，我的出发点就回归到了效率、稳定和成本这三个对于研发团队来说最重要的目标上来。从运维的角度来说，能够与这三个点契合的事情，我总结了以下五个。

1. 运维基础平台体系建设

这块主要包括我们前面提到的标准化体系以及 CMDB、应用配置管理、DNS 域名管理、资源管理等偏向运维自身体系的建设。这一部分是运维的基础和核心，我们前面讲到的标准化以及应用体系建设都属于这个范畴。

2. 分布式中间件的服务化建设

在整个技术架构体系中，分布式中间件基础服务这一块起到了支撑作用。这一部分的标准化和服务化非常关键，特别是基于开源产品的二次开发或自研的中间件产品，更需要有对应的标准化和服务化建设。这也是我们无意识地割裂运维与技术架构行为的最典型部分，这里容易出现的问题，我们前面讲过，你可以回去再复习一下。

3. 持续交付体系建设

持续交付体系是拉通运维和业务开发的关键纽带，是提升整个研发团队效率的关键部分。这个部分是整个软件或应用的生命周期的管理体系，包括从应用创建、研发阶段的持续集成，上线阶段的持续部署发布，再到线上运行阶段的各类资源服务扩容缩容等。开发和运维的矛盾往往比较容易在这个过程中爆发出来，但是这个体系建设依赖上面两部分的基础，所以要整体去看。

4. 稳定性体系建设

软件系统线上的稳定性保障，包括如何快速发现线上问题、如何快速定位问题、如何快速从故障中恢复业务、如何有效评估系统容量等等。这里面还会有一些运作机制的建设，比如如何对故障应急响应、如何对故障进行有效管理、如何对故障复盘、如何加强日常演练等等。同样，这个环节的事情也要依赖前两个基础体系的建设。

5. 技术运营体系建设

技术运营体系也是偏运作机制方面的建设，最主要的事情就是确保我们制定的标准、指标、规则和流程能够有效落地。这里面有些可以通过技术平台来实现，有些就需要管理流程，有些还需要执行人的沟通协作这些软技能。

最终通过这样一个规划，我把团队以虚拟形式重新规划了不同职责，分别负责基础平台体系、分布式中间件服务化体系、持续交付体系和稳定性体系，基本就是上述的前四件事情。

对于最后一个技术运营体系，这一点作为共性要求提出。我要求团队每个成员都要具备技术运营意识。具体来说，就是要能够有制定输出标准的意识和能力，能够有规范流程制定的能力，同时能够将标准和流程固化到工具平台中，最后能够确保承载了标准和规范的平台落地，也就是平台必须可用，确实能给运维团队或开发团队带来效率和稳定性方面的提升。这些对个人的要求还是比较高的，要有一定的规划、设计和落地能力，能具备一整套能力的人还是少数，目前这块还是靠团队协作来执行。

运维协作模式的改变

上面的这几件事情，并不是由运维团队内部封闭来做。还是我们反复强调的那个思路，要站在怎么能够打造和发挥出整个技术架构体系运维能力的视角，而不仅仅是发挥运维团队的运维能力。所以这些事情的执行可以理解为是由运维团队发起，与周边技术团队协作配合来完成的。

所以这些事情都需要跨团队协作。一方面运维团队要主动出击，去沟通，去推进；另一方面，必须能得到上级主管甚至是更高层技术领导的支持，所以这里要求技术管理者必须要有这个意识，促进这样的组织协作方式变革，如果技术管理者意识不到或者支持不到位的话，运维在后续的推进工作中将会遇到非常大的阻力。

下面来分享下我们目前正在尝试的一些调整。

我们运维所在的平台技术部门，包括了分布式中间件、虚拟化技术、稳定性工具平台以及大数据几个子部门。当我们发起并推进上述工作时，就需要与这些团队联合协作，朝着某个目标共同执行。下面我们来看看细分的情况。

1. 运维基础平台建设

这块大多数的工作会由运维来完成，因为这是运维的基础，也属于整个技术架构比较关键的基础平台之一，这一点我们在讲应用和集群服务管理时已经介绍过。

2. 分布式中间件服务化建设

这个部分我们就需要分布式中间件团队的配合。我们可以一起制定各种使用标准、规范和流程；中间件团队负责提供运维服务能力的接口；运维团队根据用户使用的场景进行场景化需求分析，并最终实现场景，同时负责标准和自助化工具平台的推广和落地。

3. 持续交付体系建设

这一部分也会涉及多个团队的协作。在资源使用上，我们前期会用到 KVM，那么如何快速交付 KVM 资源，就需要与虚拟化技术团队协作。现在我们在尝试容器方案，涉及到镜像制作、网络配置以及对象存储这些底层技术，一样会与虚拟化团队配合，在资源交付效率和利用率上都有很大提升。同时，还会与中间件团队协作，因为在应用发布和扩容缩容过程中，就会涉及服务上下线，这就要与服务化框架配合，服务化框架提供底层运维服务能力，而运维要做的就是通过中间件运维能力的封装整合，进而实现用户使用的场景化需求。

4. 稳定性体系建设

这里会涉及一些链路埋点、限流降级、以及开关预案等一些技术方案需求，通常会有这样一个专门的稳定性工具团队，对外输出一些稳定性保障能力，比如一些稳定性通用 SDK 的开发，后台日志采集分析以及数据计算等等，这些事情会对技术能力的要求比较高，需要具备较强开发能力的人来做。所以，运维在这里发挥的作用一个是上述提到的场景化实现能力，再一个就是稳定性能力的落地，或者说是运营能力。稳定性工具提供的多是能力和支持，最终要在业务层面真正执行，就需要运维和业务开发共同来执行。比如一个应用上线，是否具备关键接口的限流降级能力，是否具备熔断能力，是否满足上线的性能及容量要求，这个工作是需要运维深入每个业务，根据不同的业务场景和实现情况，一个个具体落地才行。所以，整体上对运维技术运营能力的要求就会非常高。

运维在这个过程中要发挥的最关键作用就是通过用户使用场景的分析，将各项基础服务封装并友好地提供出来，并确保最终的落地。方式上，或者是通过工具平台的技术方式，比如分布式中间件基础服务；或者是通过技术运营能力，比如稳定性能力在业务层面的落地。

运维在这个过程中，就好像串起一串珍珠的绳子，将整个平台技术的不同部门，甚至是开发团队给串联起来，朝着发挥出整体技术架构运维能力的方向演进。

运维的组织架构

上面是我们从团队需求和运维价值呈现层面成立的虚拟组织，从实际的人员管理以及技能维度来划分的话，我们和其它互联网公司的运维团队差别不大，基本会分为如下几个岗位：

基础运维，包括 IDC 运维、硬件运维、系统运维以及网络运维；

应用运维，主要是业务和基础服务层面的稳定性保障和容量规划等工作；

数据运维，包括数据库、缓存以及大数据的运维；

运维开发，主要是提供效率和稳定性层面的工具开发。

这个实体的组织架构，相当于是从技能层面的垂直划分。基础运维更擅长硬件和操作系统层面的运维；应用运维可能更擅长业务稳定性保障、疑难问题攻关以及技术运营等；数据运维就不用多说了，DBA 本身就是专业性极高的一个岗位；运维开发则是支持上述几个岗位日常运维需求的，是否能将人力投入转换成工具平台支持，就看这个团队的能力。

而前面所说的从价值呈现层面进行的虚拟团队划分，则是将上述几个实体团队技能上的横向拉通，让他们重新组织，形成技能上的互补，从而发挥出更大的团队能力。

实体组织架构，相当于一个人的骨骼框架，但是价值呈现层面的虚拟组织，就更像是一个人的灵魂，体现着这个人的精神面貌和独特价值。

这个过程中，必然会对运维的技能模型有更新、更高的要求。

总结

今天我为你介绍了我们正在实践的一些运维组织架构方面的内容。后来当我翻阅《SRE：Google 运维解密》这本书时，发现如果按照书中的章节目录进行分类的话，基本上都可以与前面我介绍的部分对应起来，这也更加坚定了我们要按照这套组织模式运作下去的信心。

同时，我们也要明白，业界没有一劳永逸的组织架构，也没有放之四海而皆准的组织架构标准，更没有万能的可以解决任何问题的组织架构设计，这里的关键是我们如何能够发挥出团队整体的能力和价值，而这一点又需要我们不断地与自己所在团队和业务特点去匹配和契合，这是一个不断变化的过程，也是需要持续调整的过程。

所以这对技术管理者要求会比较高，应该如何不断地去匹配和契合这个最佳价值点，同时如何统筹调度好团队中不同类型的技术资源并形成合力，是非常重要的。

你的团队在实际过程中遇到过哪些问题，你有怎样的经验和观点，欢迎你留言与我一起讨论。

如果今天的内容对你有帮助，也请你分享给身边的朋友，我们下期见！

11 | 谷歌SRE运维模式解读

前面我和你分享了一些关于运维组织架构和协作模式转型的内容，为了便于我们更加全面地了解先进的运维模式，今天我们再来谈一下谷歌的 SRE（Site Reliability Engineer）。同时，也期望你能在我们介绍的这些运维模式中找到一些共通点，只有找到这些共通点，才能更深刻地理解，并借鉴到真正对我们有用的东西。

专栏的第一篇文章我们介绍了 Netflix 的 NoOps 模式。这个模式并不意味着不存在任何运维工作，只是 Netflix 将这些事情更紧密地融入到了日常的开发工作中，又做得非常极致，所以并没有很明显地体现出来。

但是，谷歌的 SRE 却是一个真实具体的岗位，也有明晰的岗位职责。从借鉴意义上来讲，SRE 可以给我们提供更好的学习思路和样板。

SRE 这个概念，我应该是 2014 年下半年的时候听到的。当时可接触的资料和信息有限，只知道是谷歌对运维岗位的定义，负责稳定性保障，就没有更多其他的认识了。

后来，有越来越多在谷歌工作或接触过这个岗位的专家开始在公开演讲中分享这个概念。同时，《SRE：Google 运维解密》，这本由多名谷歌 SRE 亲笔撰写的图书也开始在国内广泛流传，让我们对很多细节有了更加细致的了解。

SRE 岗位的定位

首先，SRE 关注的目标不是 Operation（运维），而是 Engineering（工程），是一个“通过软件工程的方式开发自动化系统来替代重复和手工操作”的岗位。我们从 SRE 这本书的前面几个章节，可以看到谷歌不断强调 SRE 的工程能力。我简要摘取几段：

Common to all SREs is the belief in and aptitude for developing software systems to solve complex problems.
所有的 SRE 团队成员都必须非常愿意，也非常相信用软件工程方法可以解决复杂的运维问题。

By design, it is crucial that SRE teams are focused on engineering.
SRE 模型成功的关键在于对工程的关注。

SRE is what happens when you ask a software engineer to design an operations team.
SRE 就是让软件工程师来设计一个新型运维团队的结果。

与之相对应的，还有一个很有意思的地方，整本书中提到 Operation 的地方并不多，而且大多以这样的词汇出现：Operation load，Operation overload，Traditional/Manual/Toil/Repetitive Operation Works。你可以仔细体会一下，这些大多就是传统的纯人工操作模式下的一些典型词汇。

我们可以看到，从一开始，谷歌就没把 SRE 定义为纯操作类运维的岗位，也正是谷歌换了一个思路，从另外一个维度来解决运维问题，才把运维做到了另一个境界。

SRE 岗位的职责

书中对 SRE 的职责定义比较明确，负责可用性、时延、性能、效率、变更管理、监控、应急响应和容量管理等相关的工作。如果站在价值呈现的角度，我觉得可以用两个词来总结，就是“效率”和“稳定”。

接下来，详细说下我的理解和分析。

SRE 的能力模型，不仅仅是技术上的，还有产品设计、标准规范制定、事后复盘总结归纳这些技术运营能力，同时还需要良好的沟通协作能力，这个就属于职场软技能。

SRE，直译过来是网站稳定性工程师。表面看是做稳定的，但是我觉得更好的一种理解方式是，以稳定性为目标，围绕着稳定这个核心，负责可用性、时延、性能、效率、变更管理、监控、应急响应和容量管理等相关的工作。

分解一下，这里主要有“管理”和“技术”两方面的事情要做。

管理体系上，涉及服务质量指标（SLI、SLA、SLO）、发布规则、变更规则、应急响应机制、On-Call、事后复盘机制等一系列配套的管理规范和标准制定等。

技术体系上，以支持和实现上述标准和规范为目标，涉及自动化、发布、监控、问题定位、容量定位，最终以电子流程串联各个环节，做到事件的闭环。

可以看到技术上的平台和系统是用来支撑管理手段的。谷歌的运维其实并没有单独去提自动化、发布、监控等内容，而是通过稳定性这个核心目标，把这些事情全部串联在一起，同时又得到了效率上的提升。

我们来看几个主要的系统。

自动化。是为了减少人为的、频繁的、重复的线上操作，以大大减少因人为失误造成的故障，同时提升效率。比如谷歌内部大名鼎鼎的 Borg 系统，可以随时随地实现无感知的服务迁移。现在，它的开源版本，已然成为业界容器编排体系标准的 Kubernetes。

持续交付。谷歌非常重视持续交付。由于它的需求迭代速度非常快，再加上是全球最复杂的分布式系统，所以就更加需要完善的发布系统。

问题定位。这块跟监控相关但又有不同。我看到谷歌 SRE 这本书中并没有提到太多 Tracing 的内容，更多的是讲监控和问题管理层面的跟踪机制。其实，关于问题定位，谷歌的 Dapper 大名鼎鼎，功能很强大，国内外很多跟踪系统和思路都参考了 Dapper 的理论。这块也是为了能够快速定位问题，保障稳定而产生的，国内分享的大多关于全链路跟踪和分析、限流降级、开关和预案系统、强弱依赖等都属于这个范畴，我认为这块应该更准确地定义为分布式服务治理相关的内容。

各类分布式系统。如分布式锁、分布式文件、分布式数据库，我们熟知的谷歌三大分布式论文，就是这些分布式系统的优秀代表，也正是这三大论文，开启了业界分布式架构理念的落地。

这些系统大都是以稳定性为导向，同时带动了日常运维效率的大幅度提升，有了监控和全链路这样的问题发现和定位手段，也大大提升了我们对故障处理和问题定位的效率。容量管理，不仅仅可以保障容量充足，还能最大程度地保障资源分配的合理性，尽可能减少浪费，对于成本管控也大有好处。所以，围绕着稳定性这个核心目标，不仅达到了稳定的目的，还获得了高效的运维效率。

所以，SRE 的理念通过稳定性这个核心点，将整个运维体系要做的事情非常系统紧密地整合起来，而不是一个个孤立的运维系统。所以，SRE 是一个岗位，但更是一种运维理念和方法论。

如何借鉴和落地

在国外，SRE 岗位的薪资，和 SWE 软件开发工程师相比，要平均高出 25%。从实际的岗位要求上看，SRE 的技能要求也要比 SWE 更高、更全面，所以这样的人才是比较紧缺的。即使在国外，除了谷歌、Facebook 以及 Netflix 这样超一流的科技公司能够招聘到，或者内部培养出较多这样的人才，其它公司的 SRE、PE 或者应用运维也无法完全达到上面的要求。

在国内，就更难一些，那怎么做呢？一个思路就是我们之前讲组织协作模式转型时提到的，就是要依靠团队的力量、发挥团队的力量，如果是单个团队不能完成的事情，就跨团队协调完成。所以，SRE 岗位的要求很高，但是我们可以靠团队中具备不同能力的人协作，共同达成 SRE 的职责和目标。

最后，还是我反复强调的观点，要想做好运维，就得跳出运维的局限，要站在全局的角度，站在价值呈现的角度，站在如何能够发挥出整体技术架构运维能力的角度，来重新理解和定义运维才可以。

通过今天的内容，你对于 SRE 有什么新的理解或者疑问？结合前面的内容，你能够挖掘出哪些共通点呢？欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

12 | 从谷歌CRE谈起，运维如何培养服务意识？

2016 年 10 月，谷歌云平台博客（Google Cloud Platform Blog）上更新了一篇文章，谷歌宣布了一个新的专业岗位，CRE（Customer Reliability Engineering），直译过来就是客户稳定性工程师。我看了介绍后，发现还是一个挺有意思的岗位设置，搜索之后发现，针对这个岗位国内还没有太多的解读。下面我们就来尝个鲜，一起来看一看。

CRE 产生的背景

这个岗位出现的主要背景，还是越来越多的用户选择在云上开展自己的业务，很多企业和用户将业务从原来传统的自运维 IDC 机房迁移到云上。这样做其实就是选择相信公有云平台，但同时也就放弃了对底层基础设施的把控，甚至把企业最为核心的数据也放到了云上。说简单点，就是一个公司的身家性命都交给公有云了。

虽然绝大多数的公有云都宣称自己的稳定性多么高多么好，但是我们知道实际情况并非如此。

其实，我们可以看下 Netflix，虽然业务在相对稳定的 AWS 上，但是自从在 AWS 上遇到过几次严重故障后，就开始自己做稳定性保障的功能，我们熟知的 Chaos Monkey 这只猴子就是这么来的，进而发展到后来的 Chaos Engineering 这样一整套体系。

可以看到，Netflix 秉承 Design For Faliure，从一开始就选择在变化多端且自己不可控的环境里，加强自己系统的健壮性和容错能力，而不是依赖任何云厂商的承诺。

不过，并不是任何企业都具备 Netflix 这样的技术能力把自己打造得这么稳定。所以，当云上不稳定的情况发生时，公有云客户通常是手足无措的。因为他并不了解出了什么状况，不知道是自己的问题还是云上基础设施或基础服务的问题，也不知道自己应该从哪里入手恢复业务，所以时间长了必然就会感到非常焦虑，各种不放心。

CRE 岗位的职责

CRE 出现的根本目的，就是消除客户焦虑，真正地站在客户的角度去解决问题，同时对客户进行安抚、陪伴和关怀。

通常的售后支持，都是你问什么问题，我就回答什么问题，能马上解决的就马上解决，不能解决的就转到后端处理，然后让客户等着，承诺多长时间内给出答复。这种流程标准，严格执行 SLA 规范，对于一般问题还好，但要是真的出现大问题就不行了。

业务挂了，我都火烧眉毛了，你还跟个机器人一样，我问啥你说啥；或者你排查下对我说跟你没关系，让我自己再检查下，再或者转给后端处理，让我先等着，这个体验就非常差了。

所以，CRE 这个角色一定是站在客户角度解决问题。加入客户的“作战室”（War Room），和客户一起排查，问题不解决，自己不撤退；还会随时通报进展，必要的时候会将故障升级到更高的级别，寻求更专业的资源投入以共同解决；同时根据客户的不同反应进行不同方式的安抚。

CRE 还会发挥谷歌多年积累下来的非常宝贵的线上运维经验，在日常就跟客户沟通传递一些稳定性保障的知识。CRE 可以按照谷歌总结出来的类似 SRE 的标准规范，对客户线上系统进行稳定性标准评审，并给出专业的建议。如果客户同意遵守这样的标准规范执行，在后续出现故障时，CRE 就完全可以按照非常成熟的 SRE 的运作模式去协作用户处理故障，这样就会大大提升 CRE 和客户的协作效率，为故障快速处理赢得更多宝贵时间。同时 CRE 也可以发挥更大的专业作用，而不是之前的对客户系统不熟悉，空有一身绝世武功，却使不上劲。

所以，CRE 这个角色，既具备良好的专业技术能力，又有非常强的问题解决能力，同时还要具有优秀的客户沟通和关怀能力。背后还有谷歌多年的全球最佳运维实践 SRE 的经验和方法论支持，让 CRE 这个角色发挥出更加独特的作用，这一点可能是其它公有云厂商难以达到的。

从 CRE 谈谈做运维为什么要有服务心态

上面花了些篇幅对 CRE 做了一个整体的介绍。我个人的整体感受，CRE 更多的是一个服务性质的岗位，最终是要对客户的满意度负责，所以我们可以看到他的职责里面处处充满了紧贴客户需求和痛点的工作内容。

我们可能一下子达不到 CRE 这么高大上的水平，但是日常工作中我们要不断提升自己的服务意识还是很有必要的。而且我观察下来，有时候我们日常工作中出现的很多沟通问题、协作问题甚至是技术问题，都是因为服务意识不够而导致的。

我总结了一下，是不是有服务心态，表现在我们的做事方式上，就是我们是否能够站在对方的角度考虑问题、解决问题。

具体怎么做，可以有很多方式，这里我给出我个人的几个建议。

1. 多使用业务术语，少使用技术术语

与合作部门沟通协作，特别是对于非技术类的业务部门，尽量多使用业务语言来表达。在讨论一个需求时，如果表达的都是 API、缓存、数据库、消息队列等等这些专业术语，估计业务部门的同学肯定是跟不上我们的思路的，这样的沟通通常无法正常地进行下去，所以就会经常出现业务同学说业务的事情，技术同学说技术的事情，两边不能达成一致，矛盾就产生了。

这里需要强调的一点是，对于绝大多数的公司来说，业务一定是最重要的，技术是实现业务功能的一种手段和方式，所以一定是从业务角度出发考虑技术解决方案，而不是从技术角度出发让业务来适配技术。

那怎么从业务角度出发呢？就是我刚说的尝试用业务语言去沟通，用对方能够听得懂的表达方式去表达你的技术观点。为了让业务人员理解你的想法，就自然会用业务的思路去思考和解决问题了。这个需要一点点改变，可以先从尝试开始。

2. 学会挖掘问题背后的真正诉求

外部提出的一个问题，可能并不一定是真正的问题，而是问题的一个解决方案。

先举个之前我遇到的例子，有个部门给我们提了一个在服务器上安装翻墙软件的需求，结果我们的工程师就照着这个需求去做了，最后发现软件怎么调都启动不了，中间还牵扯到网络同事的配合，需要检查网络上的配置，最后就差动网络设备了。

后来我就去问，为什么要安装翻墙软件呢？一问才知道，有个业务需求是需要爬取 Twitter、Instagram 和 Facebook 上一些时尚达人的时间线信息的，需要部署一个这样的应用，然后能够对外访问，但是部署在我们机房内部发现不行（肯定不行啊），所以就建议尝试装一个翻墙软件看看是不是能访问出去。

这么一问，就发现安装翻墙软件不是真正的需求，真正的需求是能够访问到海外站点。看问题的角度不同，解决方案也就不一样了。

因为我们有公有云的海外节点，这样的需求，我们直接将应用部署在海外节点就可以了，然后从申请资源、部署上线到调测通过，30 分钟搞定。

这种情况非常常见，也是日常团队协作中最容易出现的问题，很多矛盾都是因为这种原因导致的。如果按照上述不假思索的方式去做，极有可能是没有结果，或者是结果无法让人满意。如果你很努力很认真地做了很多事情，但却无法得到对方的认可，那就太令人沮丧了。

遇到类似问题，可以不着急动手做，先多问自己和对方几个问题，比如：

为什么要这样做？

谁要求做这件事情的？

这样做的目的是什么？

这样做是为了解决什么问题？

这一点其实也是站在对方角度去考虑，去思考对方要解决的问题是什么，而不是解决我们的问题。通常情况下，两三个问题后，一般就会暴露出背后最原始的那个需求了。正所谓“磨刀不误砍柴工”，问题和背景搞清楚了，思路和方案就是顺其自然的事情了。

3. 解决问题的时候关注目标，而不是聚焦困难

我尝试写了一段话想来分享我的观点，但是读来读去感觉有点太鸡汤。所以还是上一张图，这个是我 16 年去腾讯交流的时候，在腾讯办公区拍到一张照片，对我启发很大。

两种不同的思考问题的方式，带给人的感受也是完全不一样的。

道理还是需要我们自己悟明白的，所以文字也好，图片也罢，期望对你也有所启发。

近些年，随着云计算技术的深入发展，公有云事业也不断拓展，运维领域的分工也在不断地精分细化，而每个细分领域对专业技术的要求也越来越高，专业的服务化程度也越来越高。我想这是一个好现象，让原来非常模糊的运维行业范畴变得越来越清晰、越来越具体。

对于我们运维来说，这样的发展既是机遇，也是挑战。一方面我们要不断提升自己的技术能力，另一方面也要注意自身服务意识的培养，让自己的能力得以发挥，创造更大的价值，获得更好的回报。

对于今天的内容你有怎样的共鸣和思考，欢迎你留言与我一起讨论。

如果今天的内容对你有帮助，也请你分享给身边的朋友，我们下期见！

16 | 持续交付知易行难，想做成这事你要理解这几个关键点

前面几篇文章，我们介绍了非常基础的运维建设环节。如果我们想要这些运维基础建设发挥出更大的作用和价值，就需要针对运维场景进行场景化设计和自动化，让效率和稳定性真正提升上来。也就是说，把基础的事情做好之后，我们就要进入效率提升的运维场景自动化阶段了。

在这一阶段，我个人的经验和建议是，首先要把持续交付做好。

为什么要先做持续交付？如果说我们完成了一些运维职责范围内的自动化工具，提升的是运维效率的话，那么，做持续交付就是提升整个研发体系效率的关键。

做持续交付的价值表现在哪里？

持续交付覆盖了应用的整个生命周期，涉及产品、开发、测试、运维以及项目管理等相关方面。从生命周期出发，自然就会牵出整个自动化的全貌，就会有从全局着眼的规划设计，这时无论是在开发还是运维过程中存在的问题，都会完完整整地暴露出来。那么，应该以什么样的主线开展？各方应该如何配合？应该以怎样的优先级明确任务？这些问题就都清楚了。同时，也避免了各个环节只把注意力放在各自职责范围内的事情上，而忽略了整体的配合。所以，做好持续交付，对于整个研发体系意义重大。

我们面临的实际场景是怎样的？

我们知道，随着业务复杂度的升高，不管是分层架构，还是微服务架构，都会带来一个最明显的变化，那就是应用数量增多，有时甚至多达几十个、上百个。不同的应用就有不同的代码、依赖和配置，为了协同多应用之间的在线发布，我们还要做到服务能够平滑地进行上下线切换。同时，为了最大限度地降低发布风险，我们还需要进行多环境下的验证，以及上线后的灰度策略等等。

应对这一切，如果只是手工维护，或者利用简单的工具脚本进行维护，都不能保证正常运作。这个时候，我们必须有一系列的流程、机制和工具链来支持和保障。

由杰斯·赫布尔（Jez Humble）、戴维·法利（ David Farley）编著，乔梁老师翻译的《持续交付：发布可靠软件的系统方法》（Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation）这本书，针对持续交付的过程、方法和指导建议几个方面做了非常详细的描述。我向你强烈推荐这本书，不过，这本书的内容并不仅仅针对于微服务架构。

接下来我就分享如何把持续交付的理念和实践相结合，讲一讲在实践过程中，做好持续交付最关键的几步是什么，以及具体应该怎么做。

什么是持续交付？

我们现在经常会接触到这些名词，比如持续交付、持续集成、持续部署、持续发布、DevOps 和敏捷开发等等。大多有关持续交付的分享或文章中，这些名词经常会同时出现。它们之间到底有什么区别？我自己之前也弄不清楚，直到看到乔梁老师的这张图。

这里我重点解释一下持续交付这个概念，通俗地说，持续交付代表着从业务需求开始到交付上线之后的端到端的过程。后面我们会针对这个过程的关键环节进行分享。

受篇幅所限，其它名词就先不作过多解释了，你可以看图自己体会，都不难理解。后面针对某些概念我们还会提到。

持续交付的关键点

可以说，这一部分也是我们后面将要分享内容的提纲。

从前面那张图来看，做持续交付需要端到端考虑，同时还要有一些非常关键的准备工作。我把这些工作大致分为以下几个部分。

1. 配置管理

这一部分会利用到我们前面讲过的标准化和 CMDB 打下的基础，同时还会有更大的外延，比如环境配置、代码配置以及依赖管理等等。

配置管理是非常关键的基础工作。有一点值得注意，那就是标准化是一个持续的过程。我们不太可能在一开始就把所有运维对象、属性和关系全部都考虑清楚，面面俱到是不太现实的，所以，一定要具备标准化的意识，在开展运维工作的过程中，持续不断地用这个思路去标准化新出现的对象。先标准，再固化，然后自动化。

2. 需求拆解

需求拆解这个工作跟业务需求部门和业务开发有更直接的关系。在这里，运维需要做的是，明确需求拆解的粒度和我们最终发布上线的粒度相匹配。

3. 提交管理

需求拆解完成后，就进入到开发阶段，开发完成后向代码库中提交代码，这个过程中代码分支的合并策略选择就是提交管理。

4. 构建打包

这一部分是指将提交后的代码编译成可发布的软件包。

5. 自动化测试

自动化测试包括功能测试和非功能性测试。对于运维来说，会更注重非功能方面的特性，所以后面我会着重讲非功能性相关的测试环节。

6. 部署发布

这一部分是指发布到不同的环境，如开发环境、预发环境、线上 Beta 以及线上全量环境。针对不同的环境，发布策略和注意事项也会不同。

以上是一个完整的持续交付过程中最重要的几个环节，后面我们分篇进行详细介绍。

从我自己的实践经验来看，配置管理、提交管理、构建和部署发布是持续交付的重中之重，是关键路径，是从开发代码开始，到发布上线的必经之路。当时，因为这几个环节出现了问题，不能解决，运维同学经常做手工发布，这样效率就跟不上，还经常出现各种问题。

后来，我们就是先从这几个环节入手，把阻塞的问题解决掉，然后在这个主流程上不断增加外围能力，让整个流程的功能更加丰富和全面。整个系统也从原来的只具备持续部署发布功能的平台，逐步演进为具有持续交付能力的平台。由此可见，我们实现持续交付的过程，也不是一蹴而就的，而是在摸索中逐步演进完善的。

最后，给你留两个思考题。

先放下持续交付的概念，你所理解或经历的从开发完代码到发布到线上这个过程中，会有哪些环节？和我列出来的这几部分是否有相同之处？

持续交付是谁的持续交付，它的主体是谁？或者有哪些主体？

欢迎你留言与我讨论。

如果今天的内容对你有用，也欢迎你分享给身边的朋友，我们下期见！

17 | 持续交付的第一关键点：配置管理

今天我们来看持续交付的第一个关键点：配置管理。按照持续交付的理念，这里所说的配置管理范围会更广，主要有以下几个部分。

版本控制

依赖配置

软件配置

环境配置

讲持续交付，一上来就先讲配置管理，主要还是想强调：配置管理是基础，是关键。我们后面将要讲的每一个持续交付环节，都对配置管理有很强的依赖。这个基础工作做不好，也就谈不上的持续交付的成功。勿在浮沙筑高台，我们做工具平台或系统，一定要重视基础的建设。

同时，这里还有一个前提，就是一定要做到代码和配置的分离。不要让配置写死在代码里，需要依靠严格的规范和约束。同时，对于那些因历史原因遗留在代码中的配置，要多花些时间和精力把配置剥离出来，做这项工作没有什么好的方法或经验，只能多上心，多投入些精力。

配置管理中，对于版本控制和依赖配置目前都有比较成熟的工具体系支持，也有丰富的实践经验供我们参考学习，下面我会做一个简要的介绍。

对于软件配置和环境配置管理，这两项配置跟我们自身的业务软件特性强相关，是整个持续交付过程的关键，我会结合我们自身的实践经验进行重点介绍和分享。

版本控制

版本控制的主要作用是保证团队在交付软件的过程中能够高效协作，版本控制提供了一种保障机制。具体来说，就是团队在协作开发代码的情况下，记录下代码的每一次变更情况。

说到这里，你是不是想到了 SVN 和 Git 这样的版本管理工具？对，其实我们每天都在接触，每天都在不停地做这个事情，所以目前看来这是一件很平常的事情。

关于这一部分我在后面的文章里会介绍关于提交阶段的实践经验。这里我们只要知道，版本控制及其工具是必不可少的，因为这是开发团队协作最基础的工具。现在应该很少有团队不采用版本控制的管理机制吧？

依赖管理

这里以 Java 为例，我们使用 Java 进行开发，必然会依赖各种第三方的开源软件包。同时，内部还会有不同组件的二方包。这些三方包和二方包就是一个应用编译和运行时所依赖的部分。

有过开发经验的同学肯定都知道，即使运行一个非常简单的 Web 应用，都会有大量的 jar 包依赖。如果人工去管理这些依赖，基本上是不可能的，所以就需要有依赖管理的工具。

对于 Java 来说，我们熟知的依赖管理工具有 Ant、Maven 和 Gradle。当然这些工具不仅仅提供依赖管理这样单一的能力，一般都具备以下几个能力：

二方包、三方包的仓库（Repository）管理；

依赖管理；

构建打包。

下面介绍下我自己的实践经验。因为我们的经验基础都在 Maven 上，再加上 Maven 周边有一些优秀插件和业界经验可以借鉴，比如后面将要介绍到的 AutoConfig，所以我们选取了 Maven 作为主力构建工具。

大致用法是建立一个本地 Maven 源，构建时会优先从本地源中获取依赖包，本地源中没有对应的依赖时，会从公网上下载，同时缓存到本地。这也是业界绝大多数公司采用的一种通用方案。具体如何构建打包呢？这个内容会在构建阶段进行分享。

软件配置

这里我把软件配置细化为两类：一类是代码配置，一类是应用配置。

1. 代码配置

我们可以这样理解，代码配置是跟代码运行时的业务逻辑相关的。比如应用的服务接口、并发线程数、超时时间等这些运行时参数；还有类似于业务或技术上的开关，比如商品评论是否开放、优惠时间段设置等等。

2. 应用配置

还记得我们在标准化文章中提到的应用吗？应用配置就是应用这个对象的属性和关系信息。我们把应用配置放到持续交付这个场景中进行分析，对于这个配置可以细分为：

应用构建时配置，比如它的编程语言、Git 地址以及构建方式等；

应用的部署配置，源代码目录、应用日志目录、Web 日志目录、临时目录、脚本目录等；

应用的运行配置，应用启停、服务上下线方式、健康监测方式等；

应用运行时与基础组件的关联关系，比如其依赖的 DB、缓存、消息以及存储的 IP 地址、域名、端口、用户名或 Token 等。

从上面这种分类方式中，应该可以体会到，我们对于配置的分类，也是基于应用生命周期的不同阶段进行分解和分析的。所以，标准化的过程也是一个持续迭代的过程。不同的场景下，一个应用可能会具备不同的属性。这个时候，如果我们无法在一开始就把这些属性梳理得清清楚楚，具备标准化的意识和思路就显得更为重要。这样，当我们遇到新场景的时候，随时可以对它做标准化分析和建模。

3. 代码配置和应用配置的区别

从上面的分析中，你有没有找出两者的区别？这里建议你暂停一下，花一分钟时间自己先想想代码配置和应用配置有什么区别，再往下看。

从区别上讲，我们可以认为代码配置是跟业务或代码逻辑相关的，动一下就会改变系统执行状态，是运行时的配置，但不依赖周边环境。而应用配置，是跟业务和代码逻辑无关的，不管你怎么动，业务逻辑是不会改变的，但是它跟环境相关。

与环境相关，按阶段分又大致可以分为两个阶段、三种情况。

第一种，软件在交付过程中，环境会不一样。比如我们正式发布软件前，会历经开发测试环境、预发环境和生产环境等等。那开发测试环境访问的 DB，跟线上访问的 DB 就不能是同一套。同时这个环境中的应用，依赖的大多是本环境内的基础组件和应用，但不是必然，原因我们后面会讲到。还有日志级别也可能不同，比如测试环境可以开 Debug 级别，但是线上是绝对不允许开 Debug 的。

第二种，软件交付上线后，线上可能会存在多机房环境，特别是有海外业务的公司，一个站点可能会在中国、北美、欧洲以及东南亚等不同区域建立当地访问的分站点；或者大型网站做了单元化，在国内也会分多机房部署，这个时候每个机房的环境配置必然不同。

第三种，软件交付后，一套软件可能交付给不同的客户，分别独立运行，比如类似 ERP、CRM 这样的软件，或者私有部署的 SaaS 服务等。不同客户的基础环境是不一样的，有的可能是 Linux，有的是 Unix，还有的可能是 Windows，这时应用配置中的各种目录、用户名等信息可能也是不一样的，软件的交付模式就取决于最终的客户环境。

对于平台类的产品，遇到第一、二种情况的可能性更大，这两种情况更多的是对周边依赖的配置不同，比如不同的服务注册中心、DB、缓存或消息等等。对于一些针对不同客户进行私有部署的产品，可能更多的是第三种情况，这种情况就是应用的基础配置比如目录、用户名以及基础软件版本等会有不同。

我们回到代码配置和应用配置之间的区别这个问题上来。

对于代码配置，我们一般会通过 Config Server 这样专门的配置管理服务进行动态管理，在软件运行过程中可以对其进行动态调整。之所以增加这些配置，主要是让开发能够以更灵活的方式处理业务逻辑。当然，也有一些为了稳定性保障而增加的配置，比如限流降级、预案开关等等。对于前者运维不必关注太多，而后者是运维关注的重点，这个内容我们后面讲到稳定性部分会重点分享。

对于应用配置，是我们在构建软件包时就需要面对的问题。这个配置取决于环境，所以就延伸出持续交付过程中非常重要的一个配置管理：环境配置管理。解释一下就是，不同环境中的应用配置管理。

环境配置是我们在持续交付过程中要关注的重中之重，也是最为复杂的一部分。我们自己的团队在做多环境发布和管理的时候，遇到最头疼的问题就是环境配置管理，我们下一期就着重来聊聊环境的配置管理。

今天我和你分享了做持续交付的第一步：配置管理，主要包括版本控制、依赖配置、软件配置和环境配置四个部分。关于今天分享的内容，你有怎样的思考或疑问，欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友。我们下期见！

18 | 如何做好持续交付中的多环境配置管理？

上一篇内容中，我们讲到软件配置中的代码配置和应用配置，这两种配置之间最大的区别就是看跟环境是否相关。由此，就引出了持续交付过程中最为复杂的环境配置管理这个问题，准确地说，应该是不同环境下的应用配置管理。

今天我就结合自己的经验和你聊一聊环境管理的解决方案。

多环境问题

上篇内容我们介绍了应用配置的三种情况，今天我们稍微聚焦一下，以上篇文章中提到的前两种应用配置场景为主进行介绍，也就是平台类的业务。我们一起来看同一套软件在持续交付过程中和交付上线后，多环境情况下的配置管理问题。

我们先从生命周期的角度，对环境做个简单说明，主要包括：

开发环境，主要是在应用或软件开发过程中或完成后，开发人员对自己实现的代码进行单元测试、联调和基本的业务功能验证；

集成环境，开发人员完成代码开发并自验证通过后，将应用软件发布部署到这个环境，测试人员再确保软件业务功能可用，整个业务流程是可以走通的；

预发环境，在真实的生产数据环境下进行验证，但是不会接入线上流量，这也是上线前比较重要的一个验证环节；

Beta 环境，也就是灰度环境或者叫金丝雀发布模式。为了整个系统的稳定性，对于核心应用，通常会再经历一个 Beta 环境，引入线上万分之一，或千分之一的用户流量到这个环境中；

线上环境，经历了前面几个阶段的业务功能和流程验证，我们就可以放心地进行版本发布了，这个时候就会将应用软件包正式发布到线上 。

以上是一个持续交付体系中必须要有的几个环境。环境建设，又是一个比较大的话题，我们后面会专门来讲，今天就聚焦在环境配置管理上。

不同环境下的应用配置管理

我们前面提到，环境配置管理，解释得更准确一点，应该是不同环境下的应用配置管理，所以这里的核心是应用配置管理。因为有多个环境，所以增加了其管理的复杂性。持续交付过程中涉及到应用配置管理的属性和关系如下：

应用属性信息，比如代码属性、部署属性、脚本信息等，你可以参考之前我们对这块的细分，这里就不细讲了；

应用对基础组件的依赖关系。这个也不难理解，应用对 DB、缓存、消息以及存储有依赖，不同的环境会有不同的访问地址、端口、用户名和密码。另外，在分布式架构中，一个应用必然要依赖一个环境中的其它应用，这时对于应用的服务注册、服务发现也要求必须在本环境中完成。举一个最简单的例子，我们肯定不允许一个线上应用服务注册到线下环境中去，让线下业务测试的服务调用影响到线上服务运行，要不然就会导致线上的业务故障了。

讲到这里，你应该会发现，对于我们假设的平台类业务场景，应用的基础属性信息是不会随着环境的变化而发生变化的，但是应用依赖的基础设施和依赖这个关系是会随环境不同而不同的。所以，我们可以再进一步理解，环境配置管理主要是针对应用对基础设施和基础服务依赖关系的配置管理。

如果是针对不同的客户进行私有化部署的软件，那么应用的基础属性信息可能也会发生变化，但是这样的场景就更会更加复杂一些，但是配置管理上的解决思路上是一样的，所以这里我们还是简化场景。

环境配置管理解决方案

上面详细讲解了环境和应用配置之间的管理，下面就结合我自己团队和业界的一些方案，来看看这个问题应该怎样解决。

我们的示例尽量简化场景，重点是讲清楚思路。所以我们假设现在有三个环境：

开发环境

预发环境

线上环境

继续假设某应用有配置文件：config.properties，里面存储了跟环境相关的配置，简化配置如下：

缓存地址：cache.app.url

消息地址：message.app.url

数据库地址：db.app.url

支付调用地址：pay.url

支付调用 Token：pay.app.token

很明显，不同的环境，配置是不完全相同的。我们看以下几个解决思路。

方案一，多个配置文件，构建时替换。

这是一个比较简单且直接有效的方式，就是不同环境会分别定义一个配置文件，比如：

开发环境 dev_config.properties

预发环境 pre_config.properties

线上环境 online_config.properties

这几个配置文件中的配置项保持相同，但是配置的值根据环境不同是不一样的，不过都是固定的实际信息。比如开发环境配置文件中的缓存地址：

cache.app.url=10.88.77.66

而线上环境配置文件中：

cache.app.url=10.22.33.44

然后在构建时，我们会根据当前所选定的环境进行替换。比如，我们现在构建开发环境的软件包，这时就会选择 dev_config.properties 作为配置文件，并将其文件名替换为 config.properties 打包到整个软件包中。

我们看下这种方案的优缺点：

优点，就是简单直接。在环境相对固定且配置项变化不大的情况下，是最为简便的一种环境配置管理方式。

缺点，也比较明显。首先是在实际的场景中，我们的环境可能会更多，且交付上线后可能还会有线上多环境。这时每多出一个环境，就要多一个配置文件，这时配置项的同步就会成为大问题，极有可能会出现配置项不同步，配置错误这些问题。特别是如果配置项也不断地增加和变化，管理上会变得非常繁琐。再就是，这里需要针对不同环境进行单独的构建过程，也就是要多次打包，这一点是跟持续发布的指导建议相悖的。

方案二，占位符（PlaceHolder）模板模式。

这种方案在 Maven 这样的构建工具中就可以很好地支持，直接示例如下：

cache.app.url=${cache.app.url}

我们可以看到，这种模式下，配置项的值用变量来替代了，具体的值我们可以设置到另外一个文件中，比如 antx.properits（这个文件后面在 autoconfig 方案中我们还会介绍），这里面保存的才是真正的实际值。

这时我们只需要保留一个 config.properties 文件即可，没必要把值写死到每个不同环境的配置文件中，而是在构建时直接进行值的替换，而不是文件替换。这个事情，Maven 就可以帮我们做，而不再需要自己写脚本或逻辑进行处理。

不过，这个方案仍然不能很好地解决上面第一种方案提到的问题，配置文件是可以保留一个了，但是取值的 antx.properties 文件是不是要保留多个？同时，对于配置文件中配置项增加后，antx.propertis 文件中是否同步增加了配置，或者配置项名称是否完全匹配，这一点 Maven 是不会帮我们去检查的，只能在软件运行时才能验证配置是否正确。

最后，这个方案还是没有解决只打包一次的问题，因为 Maven 一旦帮我们构建完成软件包之后，它并没有提供直接针对软件包变更的方式。所以，针对不同的环境，我们仍然要打包多次。

方案三，AutoConfig 方案。

AutoConfig 是阿里开源的 Webx 框架中的一个工具包，在阿里的整个持续交付体系中被广泛应用，它继承了 Maven 的配置管理方式，同时还可以作为插件直接与 Maven 配合工作，针对我们上面提到的部分问题，它也针对性地进行了加强和改进，比如：

配置校验问题。AutoConfig 仍然是以上述第二种方案的模板模式为基础，最终通过 antx.properties 文件中的配置值来替换，但是它会做严格校验；同时也可以自定义校验规则，来检查配置项是否与模板中的设定严格匹配，如果不匹配，就会在构建时报错，这样就可以让我们提前发现问题，而不是软件包交付到环境中运行时才发现。

只打包一次的问题。AutoConfig 不需要重新构建就可以对软件包，比如 war 包或 jar 包的配置文件进行变更，所以它很好地解决了针对不同环境需要重复构建的问题。但是，比较遗憾的是，它的 Maven 插件模式并没有解决这个问题，还需要与 AutoConfig 工具模式配合才可以。

讲到这里，我们可以看到 AutoConfig 的方案已经相对完善了，也可以满足我们的大部分需求，但是它仍然没有解决多环境配置值管理的问题，我们是通过多个 antx.properties 文件来管理，还是有其它方式？

这里，我们就需要基于 AutoConfig 做一下二次开发了，也就是我们要把这些配置项做到一个管理平台中，针对不同环境进行不同值的管理，然后根据 AutoConfig 的规则，在变更后生成对应不同环境的配置文件，然后再结合 AutoConfig 针对配置管理文件的能力，这样就可以很方便地做多环境的软件包构建了。

这样的配置项管理平台，AutoConfig 自己也没有做，所以需要我们自己开发。同时，对于比较敏感的配置信息，特别是涉及用户名、Token、核心 DB 地址等信息，还是不要放到配置文件中，最好是放到管理平台中，进行受控管理。同时，这里也要特别强调，密码信息一定不允许放在配置文件中出现，更不允许以明文的方式出现，这一点是需要开发、运维和安全共同来保障的。

总结

今天我们针对多环境的配置管理进行了分享，这里更多的还是思路和方案上的引导。如果你对 Maven 和 AutoConfig 不熟悉的话，建议自行查询资料进行学习了解，甚至是自己动手尝试一下。

另外，对于文章中的方案，我是尽量简化了场景来分享的，虽然思路上是相通的，但是实际情况下各种细节问题会更繁琐，要具体问题具体分析。

你在这个过程中遇到过什么问题？有什么好的解决方案？或者还有什么具体的疑问？欢迎你留言与我一起讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

19 | 开发和测试争抢环境？是时候进行多环境建设了

在上一期文章里，我们介绍了多环境下的应用配置管理问题，从这期开始，我们会分两期文章详细聊聊多环境建设的问题：就是我们到底需要哪些环境？这些环境都有什么作用？环境建设的思路和方式是怎样的？

今天我就结合自己的经验和理解与你聊一聊持续交付中的线下多环境建设。

环境分类

通常，我们主要按照环境所起到的作用，将环境分为两大类：

线下环境：测试验收用。

线上环境：为用户提供服务。

从建设角度来说，线下环境和线上环境，在网段上是要严格隔离的。这一点在做环境建设时就要确定网络规划，同时在网络设备或者虚拟网络的访问策略上要严格限定两个环境的互通，如果限制不严格，就极易引起线上故障，甚至是信息安全问题。

如果你维护过这样两套环境，我想你一定在这方面有过深刻的感受，甚至是痛苦的经历。

所以，从规划上，线上环境和线下环境是两套独立的区域，所有的应用、基础服务都是全套独立部署的。但是线下环境所需的资源往往是要少于线上环境，毕竟只有负责开发测试的少数人使用，不会有线上流量进来。如下图所示：

但是，在实际情况中，这两个环境远远满足不了我们日常开发、测试和运维方面的需求。从保障软件质量和系统稳定的角度出发，我们在实际操作中还需要在这两个大的环境区域中，建立细分的小环境，来满足不同阶段和不同角色的工作需求。

线下环境分类建设

线下环境最初建设的时候，主要是提供给测试使用，帮助其建立一个模拟环境，在软件发布上线前进行需求功能验证，保障业务流程顺畅，以确保应用在上线前达到最低质量要求。

所以，我们在线下环境区域内，建设的第一个环境就是集成测试环境。甚至在一开始，线下环境 = 集成测试环境，这个环境下的应用和各类基础服务必须跟线上保持一致，但是集群规模不用这么大（如我们上图所示）。

所以，集成测试环境极其重要，这个环境中的应用有严格的发布标准，并且要求环境稳定，不能随意发生变更，否则将会大大影响测试的效率。

不过，随着集成测试环境建设起来，业务需求迭代越来越快，应用和开发人员数量也越来越多，软件发布和变更也会更加频繁，这个时候就会出现开发和测试人员争抢集成测试环境的问题。

比较典型的场景就是，测试人员正在验证一个功能，突然发现应用停止运行了，原来开发为了验证和尽快发布新功能，更新了代码，这样就阻塞了测试的正常工作，但是不更新代码，开发的工作又会停滞下来。

后来这个矛盾越来越严重。这时，我们就需要考虑多建设一套给开发用的环境来解决这个问题。

于是，我们就开始建设线下的第二套环境：开发测试环境。这个环境主要是让开发同学能够尽快发布自己开发完的代码，并在一个具备完整业务应用和基础服务的环境下，验证自己的代码功能。

但是，是否需要跟集成测试环境一样，再建设一套独立完整的线下环境出来呢？答案是否定的。因为这时的应用变化范围相对独立，变化也较小，周边依赖需要同时变化的应用也不会太多，就像上面说的，只要能把它们放到一个完整的环境中进行验证即可。

所以，这个环境只要按照最小化原则建设即可，如果有依赖，可以直接访问到集成测试环境。在这里，我们以简单的模型展示开发测试环境跟集成测试环境的关系：

再往后，开发测试环境上，又会出现开发和测试的冲突和争抢，因为从场景上，业务开发团队可能要同时承担多个并行项目的研发，而且可能会有多个业务开发团队一起参与进来。

比如对于电商来说，到了年底，就集中会有“双 11”、“双 12”、“双旦节”以及“年货节”等等这样的大型营销项目，因为时间非常紧凑，所以就必须多项目并行。

这个时候，分解下来，对于我们的应用软件来说，有可能是存在多个开发分支的。到了项目联调和验证环节，就必然会存在同一个应用有多个版本需要同时发布和测试的情况，但是开发测试环境却只有一个，这就必然导致双方激烈的争抢。

所以这个时候，就必须建立解决冲突的方案，开始建设线下的第三套环境：项目环境。

项目环境可能有多套，一个项目对应一套环境，但是无论从资源成本还是维护成本方面考虑，项目环境仍然不会像集成测试环境那样形成一套完整的开发测试体系。

所以项目环境同开发测试环境一样，仍然是以最小化为原则来建设，也就是说，在这个环境里面，只部署同一项目中涉及变更的应用，而对于基础服务和不涉及项目需求变更的应用不做重复建设。如果对项目环境中不存在的应用有依赖，那么访问集成测试环境中对应的应用就可以了。

在这里，我们同样以简单的模型展示多个项目测试环境、开发测试环境与集成测试环境的关系：

不过，如果说随项目的增加就需要分别建设对应的项目环境，那么这对于开发、测试和运维来说都会有非常大的维护负担。所以通常情况下，我们会严格限制建设项目环境的起步线。

比如只有公司级大促、公司战略级的项目，或者超过一定人日的跨团队项目，才允许建立独立的项目环境。一般情况下，还是引导优先使用开发测试环境。

环境建设上的关键技术点

线下环境细分出集成测试环境、开发测试环境以及多个项目环境之后，带来的最大的成本其实不在资源上，而是在管理和维护上，而且单单就线下维护的工作量来说，甚至要超过线上维护的工作。

复杂度和涉及到的技术点有以下四个方面。

第一是网段规划。每个环境都要有独立的网段，比如整个线下环境要独立占用一个 B 段，项目环境和开发测试环境相对较小，可以独立占用一个 C 段。虽然不需要做网络策略上的隔离，但是为了便于管理，如分配回收资源以及部署应用，还是要在逻辑上区分出来。同时，网段规划也是为下面的单元化调用做准备。

第二是服务化框架的单元化调用。这一点需要服务化框架支持，比如上面我们提到的项目环境，到了联调阶段就需要一组应用单独联调，而不能跨项目环境调用。同时，对于项目中依赖的未变化的应用，就需要调用集成测试环境中稳定版本的应用。这个服务调用的基本规则就是基于上述网段的规划来建立的，规则要放到服务化的注册中心，也就是 ConfigServer 这个部件中保存，同时需要服务化框架支持规则调用，优先支持本单元调用，本单元不存在可以调用集成测试环境单元。

第三是环境的域名访问策略。这么多的环境 ，内外部 DNS 域名是保持一套还是多套，比如访问蘑菇街主页（www.mogujie.com），首页域名就一个，但是怎么能确保访问到我们所期望的环境上呢。这里有几种方式：

第一种，DNS 服务保持一套，域名，特别是外部域名多套，每个环境分别配置一个不同的域名，比如开发测试环境，dev.mogujie.com。但是如果这样，下层的二级域名和二级目录等等都要跟着变动，而且对于项目环境来说，数量不固定，每次都换一个也不方便记忆和管理，所以这个方案基本不可行。

第二种，DNS 服务保持一套，域名保持一套，但是做域名的 hosts 绑定，也就是自己来设置要访问域名所对应的环境。这样一来，如果相对固定的开发测试环境和集成测试环境所对应的 hosts 相对固定，那么只需要绑定一次就可以通用。但是项目环境始终在不断的变化中，绑定规则可能随时在变化，所以这种方案的复杂度在于对 hosts 配置的管理上。

第三种，DNS 服务多套，也就是不同的环境中配置独立的 DNS 服务，这样可以减少繁琐的 hosts 绑定，但是也会提高多套 DNS 服务管理上的复杂度，而且对于项目环境有可能依赖集成测试环境中的服务，这时仍然会涉及本地 DNS 服务的 hosts 绑定。

第四种，对于公网域名，可以直接通过无线路由劫持的方式访问，可以在无线路由器上配置多个接入点，这样一来，连接不同的接入点，就会自动对应到不同环境的域名 IP 地址上去。

通常，对于公网域名来说，如果具备稳定的环境，如集成测试环境，直接通过第四种劫持方式指定到对应环境中去，这样最方便，这种方案在后续线上多环境建设中还会使用。

对于内部域名，则有多种方案，没有优劣，主要看场景和管理成本。我们选择的是第二 种，即绑定 hosts 的方式。每个环境会对应一套 hosts 配置，当选择不同环境进行联调或访问时，就将 hosts 配置下发到对应部署应用的主机上。

在这里，我们仍然以模型展示第二、四种方案和多种线下环境之间的运行逻辑：

但是，无论采取哪种方式，我们可以看到，这个管理过程仍然是比较复杂繁琐的，必须要非常仔细地规划和部署，同时还需要配套的自动化工具支持，否则靠人管理是不现实的，所以最后一点就是自动化的配套。

第四是自动化管理。按照我们之前分享的管理模式，这里虽然有这么多的线下环境，但我还是会把它们以应用为核心给管理起来，即应用的开发测试环境，应用的集成测试环境，应用的项目环境。这样一来，上面提到的不同环境的网段信息、配置信息、资源分配回收以及软件部署发布，都能够以应用为出发点去做，这一点我们在后面的文章会详细分享。

总结

最后，不知道你有没有感受到，单单一个线下环境就要如此复杂和繁琐，整个持续交付体系建设是多么的有挑战性，就可想而知了。

我们对线下环境稍微做个总结：

集成测试环境，主要供测试使用，这个环境会最大程度与线上版本保持同步。作为对应用的功能、需求、业务流程等在正式发布上线进行验证的主要环境，集成测试环境的稳定性和可测试需要加强保障，进行全套建设。同时，作为整个线下环境的中心节点，也要为开发测试环境和项目环境提供部分依赖服务。

开发测试环境，主要供开发人员使用，针对偏日常的需求开发、联调和功能验证，以最小化原则进行建设，但是一般情况下不对资源进行回收。

项目环境，供开发和测试共同使用，针对多团队多人员协作的项目型场景，可以同时存在多个项目环境，在这个环境中针对项目需求进行独立开发、联调和验证。测试也需要提前介入这个环境进行基本功能的验收，并遵循最小化的建设原则，但是要有生命周期，即项目启动时分配资源，项目结束回收资源，不能无限期占用。

最后，在实际操作中，仍然会很多细节问题，这些问题会跟业务场景有关，针对这些场景又有可能有不同的建设要求，比如消息的消费问题会涉及全业务流程验证等等。

所以，留几个问题给你思考：在线下环境的建设过程中，你通常会遇到哪些问题？会有哪些独立环境？或者你有什么更好的经验和建议分享？

欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

20 | 线上环境建设，要扛得住真刀真枪的考验

前面几期我们分享了一些线下环境建设方面的内容，我们可以感受到，整个线下环境的建设是比较复杂的，那经过线下环境的验证，是不是就可以直接发布到线上生产环境了呢？答案同样是否定的，由线下正式交付到线上之前，我们仍然会做很多的验证和稳定性保障工作。

今天我们就一起来看一下线上环境是如何建设的。

下面，我们就生产环境、Beta 环境、预发环境、办公网生产环境这四种线上环境分别展开讨论。

生产环境

我们还是进入到现实场景中。最初我们的软件代码开发完成后，就可以发布到生产环境，也就是可以正式接入用户流量，承载真实的业务场景。

在最早期，我们业务复杂度不高，用户量不大，集群规模小，软件架构也相对简单。在这种情况下，其实这一个环境就足够了，真有问题，也可以快速回退掉。退一步讲，即使有问题也回退不了的话，影响范围也有限。

所以，这个时候，线上环境 = 生产环境。

我们知道，随着业务量增大和业务复杂度升高，我们的软件架构、部署模式、集群规模等等也相应变得复杂和庞大起来。同时，业务产品在用户和业界的影响力也在变得越来越大。

这个时候，任何一个小的变更或一个不起眼的小问题，都有可能导致非常严重的故障，从而造成公司资损甚至是恶劣的产品口碑影响。

比如，我们假想一下，如果国内某个大型电商平台不可用，或者某即时通讯软件不可用，会造成何等严重的后果，就不难想象了。

所以，这时就需要我们非常严肃而谨慎地应对生产环境的变更。

我想你可能跟我一样，会想到一个问题：就是我们不是已经在线下环境经过了很多轮不同形式的验证测试环节，为什么到了生产环境还会有验证不到的严重问题？

这里涉及一个用户和业务场景的概念，就是线下和线上的用户场景是完全不同的：线下是我们模拟出来的，线上却是真实的用户场景，这两者之间会存在巨大的差异，有差异，系统的表现状况就会不一样。

所以线下我们只能尽可能地确保业务功能和业务流程是正常的，但是没法百分之百模拟线上场景，特别是一些异常特殊场景方面。这一点后面的文章我们还会再分享，这篇文章我们只要知道存在差异即可。

这个时候，我们的第一个思路就是：即使有影响，也要把它控制在小范围内，或者是在萌芽状态时就发现。这样就可以提前处理，而不是全量发布到生产环境后才发现问题，影响全局。

所以，线上的第二个环境，Beta 环境就产生了。这个环境也可以叫做灰度环境，包括我们常提到的金丝雀发布，也是基于这个环境的发布模式。

Beta 环境

这个环境的建设，我们简单理解，就是从生产环境的集群中，再建立一个独立集群。看过我们之前介绍 CMDB 应用和服务分组的文章的读者应该不难理解，针对应用，就是再建立一个分组，独立出一个集群出来，但是这个集群中服务器数量 1-2 台即可，主要还是针对小规模真实业务流量。如何做到小规模呢？这就要在负载均衡策略上做工作了，主要两种方式：

调用 RPC，在服务化框架的复杂均衡策略中，将其权重或者流量配比降低；

调用 HTTP，在四层 VIP 或者七层权重上，将权重降低。

这个环境同样不会全量建设，通常只针对核心应用，比如交易链路上的各个应用。同时，除了承担的流量比重不同外，其它与生产环境的应用没有任何差别。

后面的部署发布环节，我们会看到，针对核心应用，必须要经过 Beta 发布环节，才允许正式发布到生产环境。

有了 Beta 环境之后，上面说到的影响范围的问题从一定程度上就可控了。但是在 Beta 环境上我们仍然会有两个问题无法很好的解决：

影响范围再可控，其实也已经影响到了部分真实用户，特别是当访问量特别大的时候，即使是千分之一、万分之一，也是不小的数量。

之前经历的线下环境毕竟是一个模拟环境，一方面，在数据规模、分布特点、多样性以及真实性方面，跟生产环境的数据场景还是会有很大的区别，所以有很多跟业务逻辑相关性不大，但是跟数据相关性特别强的场景功能，在线下环境就很难验证出来；另一方面，对于一些第三方的系统，特别是商家、支付和物流这样的体系，在线下环境极有可能是 Mock 出来的，所以验证的时候并不能代表真实场景，但是等到了线上再去发现问题，就可能就会造成真实的业务影响。业务访问失败可以重试，但是造成商家真实的销售数据错误，或者用户真实的支付资金错误，这样就会非常麻烦了。所以，从线下直接进入 Beta 环境，还是会给生产环境，特别是数据层面造成影响。

当业务复杂度和系统规模发展到一定程度后，上面两个问题就会非常突出，所以单纯的 Beta 环境是无法满足要求的。

这时，线上第三套环境，预发环境，就产生了。

预发环境

预发环境在建设上，有以下几个规则要求：

状态基础服务共用，如 DB、KV、文件存储以及搜索类的数据服务。这里基本就是真实的生产环境的基础了，我们上述的问题在这个基础上就可以很好地解决了。除有状态服务外，其他都需要在预发环境上进行全套建设，但是资源使用上，一般是一个应用部署一个实例即可，所以规模比生产环境要小很多。

网络隔离上，预发环境做独立网段的划分，不承担线上真实流量，独占一个 B 段，同时在网络上进行逻辑隔离。业务调用必须本环境内闭环，预发不允许跨环境进行应用服务调用，如预发应用调用生产环境应用，反之亦然。

要保证一定的稳定性。预发环节就是基于线上真实环境进行功能和业务流程的最终验证，所以对于版本质量要求是要高于线下环境，所以不允许反复频繁地变更部署，出现异常或警告也必须要以较高优先级处理。

上述环境的搭建，使用的技术方案，跟我们上篇文章讲到的方案是通用的，如服务单元化调用、绑定 hosts 以及网络策略隔离等等。预发环境与生产环境的关系如下图：

预发环境正式使用后的另一用途，就是在生产环境出现问题，但是线下复现不了时，就可以在预发环境上复现，这样对于问题定位会带来很大帮助。如果是在生产环境上做调试和问题定位，有时候会影响到正常用户访问，但是预发环境的影响就可控一些。

不过，定位问题可以，但是绝对不可以通过预发环境去做下面两件事：

与数据订正和变更相关的事情。因为这是由业务流程触发，而不应该由调测触发。而且要时刻牢记，在这个环境做的任何事情都是会对生产环境产生直接影响的，所以这里必要要靠强调意识、事先培训等方式进行避免。

阻塞他人工作。在定位问题的过程中，如果发现有其他应用依赖，这时要停下来，优先保证环境稳定性，而不是阻塞依赖方发布前的准备工作。

形象一点描述，预发环境就像是球类运动员，他们平时可以在训练场进行训练，但是正式比赛前，一定是要到正式比赛场地提前适应场地或者热身。一方面是为了了解现场的实际情况，做针对性的准备和调整；另一方面也是为了调动赛前兴奋度和氛围。

预发环境搭投入使用之后，有很多问题在这个阶段被发现，而且是开发和测试同学目前强依赖的一个环境，所以确实进一步保障了业务的稳定性。

然而，在这个环境中仍然存在一个问题。下面我还是以电商为例。

电商每年大促，一般都是提前几个月准备，有可能开发团队在大促活动正式开始前 3-4 周左右，业务功能都已经开发完成，但是这个时候是不能上线的，或者上线了也要有入口开关控制，绝对不能让用户流量提前进来。

与此同时，运营侧的招商、报名以及商品上架这些工作也会提前完成，所以这时线上实际已经具备了真实的大促环境，只是因为时间点不到，暂时只能等着。

但是，如果有一个只让员工访问，让员工们体验和反馈问题的环境，那么，在这个阶段我们是可以提前暴露很多问题，并进行很多优化改进的。这样做就更进一步保障了大促的系统问题和用户体验。

不过，上述 Beta 环境和生产环境是无法满足要求的。预发环境能满足一部分要求，但是因为这个环境主要还是供开发和测试验证功能使用，在访问的便捷性和功能体验方面，不能完全保证达到真实用户访问的要求和体验。

为了满足上述需求，我们会再单独建设一个环境出来，于是，线上环境的第四套环境，办公网生产环境，就应运而生了。

办公网生产环境

办公网生产环境建设的技术方案与预发环境一致，但是在要求上又有所不同：

访问用户是办公网内的员工用户，所以必须连接指定的办公网 wifi 接入点。于是，员工会通过 wifi 被劫持到这个环境上，这时用户就可以在这个环境中提前体验新版本软件的功能，比如我们之前说的大促活动等。

稳定性要求上，办公网生产环境相当于生产环境，虽然不是外部用户访问，但是一个公司内的员工也算是真实用户了，他们发现的问题等同于线上问题，但是级别上会降低一级处理。

建设规模上，公司有上千、上万名员工，他们的频繁访问行为，也产生一定的业务量，所以综合上述稳定性要求，办公网生产环境在规模上会根据应用容量进行相应的资源分配，这里至少每个应用应该以两个实例做冗余。

所以这个环境，从建设规模和稳定性要求上，就相当于一个小号的生产环境，所以我们内部又把它简称为“小蘑菇”环境。

总结

我们简单构建一张模型图来对线上环境作个展示：

我在这两期文章中介绍了这么多环境，我们可以看到，环境建设是一项异常繁琐复杂的工作，这些工作不是一蹴而就，而是根据实际的场景和问题催生出来的，所以是个逐步渐进的过程。

而且，因为不同的业务类型和场景，以及业务发展的不同阶段，场景和问题可能都是不一样的，而且其建设需求也不一样，所以在实际操作中，一定要切合具体情况进行建设。

再就是，环境管理是复杂的，多一个环境就多一份管理成本。所以环境并不是越多越好，反而是越精简越好。这个时候也需要各位读者能够有一定的 ROI 评估，毕竟能带来最大价值的投入才是有意义的，而不是盲目地建设和投入。

最后，给你留几个问题思考：

我们分别介绍了线下环境和线上环境的建设，这两个环境在持续交付体系中，分别对应哪些理念和指导思想？

我们建设了这么多的环境，都是为了解决不同场景下的问题，那么还有哪些问题是上述这些环境仍然解决不了的？

欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

21 | 人多力量大vs.两个披萨原则，聊聊持续交付中的流水线模式

在前面 5 期文章中，我们分别详细介绍了持续交付体系基础层面的建设，主要是多环境和配置管理，这些是持续交付自动化体系的基础，是跟我们实际的业务场景和特点强相关的，所以希望你一定要重视基础的建设。

本期文章是我们持续交付系列的第 6 篇文章，从本期开始，我们进入到交付流水线体系相关的内容介绍中。

持续交付流水线简要说明

从一个应用的代码提交开始，到发布线上的主要环节，整个流程串起来就是一个简化的流水线模式。如下图所示：

我们前面介绍了持续交付的多环境以及配置管理，而流水线模式的整个过程正是在这个基础上执行，所以它的某些环节和要素与我们的多环境是有一些交叉的。比如，功能测试会在线下相关的几个环境上完成，比如我们前面介绍到的开发联调环境、项目环境和集成测试环境。

但是，它们要达成的测试目的是不同的：对于非功能验收，我们会在线上的预发环境完成，因为预发环境更接近真实场景，所以像容量、性能、安全这些跟线上稳定性相关的能力验收，越接近真实环境，效果越好。

后面几期文章，我会结合我们的实践，分环节来介绍。本期文章我们先看项目需求分解和开发模式选择。

项目需求分解

持续交付我认为更多的是针对应用层面，所以项目需求分解这一部分，这里我们就不展开讲了。这里我们的工作重点，就是将项目管理中的需求与持续发布中的应用这二者很好地关联起来。

比较通用的做法，就是要求业务架构师在做需求分析和功能设计时，要针对一个需求进行拆分，最终拆分成一个个的功能点，这些功能点最终落实到一个个对应的应用中，对应的逻辑体现就是应用代码的一个 feature 分支。

如下图所示：

举个简单的例子，比如我们要做大促的优惠活动，同一店铺商品购满 500 元，可以使用 10 元店铺内优惠券，同时还可以使用 10 元全站优惠券。

这样一个需求最终拆解下来，可能需要店铺应用支持多优惠活动的叠加，同时下单应用和购物车应用在计算价格时也要设定相关的优惠逻辑，这一个需求可能就拆出三四个功能点。

这样做的好处就是，从一开始的需求管理维度，就确定了最终多个应用联调、测试以及最终发布的计划和协作方式，从而就会让我们明确同一个项目环境中到底需要部署哪些应用，这些应用的发布顺序怎样安排。

比如，如果 A 应用依赖 B 应用，那么 B 应用就必须优先发布。所以，上述这个过程对于项目进度管理、团队协作以及最终的发布计划都是有帮助的。

讲到这里，你是不是又进一步感受到了运维的重要性呢？

当然，每个公司都有不同的项目管理方式，这里我们只要明确做好需求拆分与应用功能的对应即可。

提交阶段之开发模式选择

在代码提交阶段，我们遇到的第一个问题，就是分支管理问题。这反映出研发团队协作模式的问题。

我们所熟知的开发协作模式有以下三种：

主干开发模式。这也是极限编程里提倡的一种模式，每一次代码提交都是合并到 master 主干分支，确保 master 随时是可发布状态。但是它对代码开发质量以及持续集成自动化和完善程度要求非常高，通常一般的团队很难做到。

gitflow 开发模式。因为 git 的流行，gitflow 是专门基于 git 代码管理的工作流工具，它的特点是在 master 分支之外，会有一条常驻 develop 开发分支，所有功能开发和缺陷修复都在这个分支上再建立分支。发布时合入一个从 master 分支中签出的 release 分支，最终发布的是 release 分支代码，然后 release 分支再合并回 master 和 develop 分支。如下图所示：

分支开发模式。相对于 gitflow 模式，分支开发模式会简单清晰很多。它的特点是，功能开发或缺陷修复从 master 签出独立的一个 feature 或 bug 分支，发布前从 master 分支签出一个 release 分支，并将要发布的 feature 或 bug 分支合入。发布完成后，release 分支合入 master 分支。如下图所示：

开发模式的选型原则

上面我分别介绍了三种开发模式的特点，那么，在实际操作中，我们选择哪一种比较好呢？

这里的选型原则就是：一看这几种模式的适用场景；二看我们实际的使用场景是怎么样的。

下面，我们分别看看主干开发和 gitflow 开发这两种模式。

主干开发模式。它的特点是，所有的代码变更直接提交到 master 分支，这种情况比较适合规模较大的应用，这类应用自身集中了所有的需求功能点，且需求串行开发，需要多人协作共同完成同一个需求，发布时间点明确、统一。

这种模式最简单，且便于管理，不需要再建立各种分支。我们之所以在极限编程中提倡这种模式，也是因为这种模式最简单，最便捷，也最高效。因为我们的软件架构在早期还是单体结构且分层架构的，代码相对集中，所以，主干开发模式也是适用的。

但是，在现实场景下，需求总是层出不穷的，所以就需要需求并行开发。这就会产生这样一种情况：同一应用会有多个团队在同时提交不同需求的代码，且每个需求发布的时间点是不同的。

所以如果采用主干开发模式，就可能会将还没有经过测试验证的代码发布到线上。这时，我们就需要在代码里预设很多功能开关配置，这样一来，在应用正式上线前，代码可以发布，但是功能不开放，而这样也必然会增加代码的复杂度。

所以，就有了gitflow 开发模式。

gitflow 开发模式能够适应并行开发，解决上述我们所说的问题，而且 gitflow 工具能够从技术层面帮我们解决各种分支合并问题。

通过上面 gitflow 的图示，我们可以看出，gitflow 开发模式带来的分支的管理代价还是比较高的，且随着分支增加，开发人员之间的沟通协作成本也会随之提高。

同时，gitflow 开发模式还是在代码相对集中的应用场景中更加适用，因此，基于这个应用完成较多的并行需求，就需要通过多个分支来管理。

在现实场景中，尽管我们日常需求非常多，但是这些需求拆解下来的功能都是集中在某个或某几个应用上的吗？

其实不然。我们从原来的单体或分层架构演进到微服务架构后，带来的一个好处就是每个应用的职责更加明确和独立，与此同时，针对应用的开发，团队也更加自制，规模更小，符合“两个披萨原则”。

所以，一个需求拆解出功能，对应到每个应用上，这样可以很好地控制并行的功能点数量，大大降低开发协作的沟通复杂度，即使有合并冲突问题，往往内部沟通一下就可以很快解决。

而实际上，我们设想的这种复杂的 gitflow 场景，在微服务架构下的组织架构中极少存在。

在此，经过对主干开发模式和 gitflow 开发模式这二者的综合对比，结合前面我对分支开发模式的介绍，我们可以看出，分支开发模式简单清晰，在实际操作中更适合我们使用。

最后，留个问题给你：你对于开发协作模式是如何选择的？存在哪些问题？有什么更好的建议？

欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

22 | 持续交付流水线软件构建难吗？有哪些关键问题？

上期文章我们介绍了需求分解与应用对应的管理方式，以及提交环节的开发协作模式，今天我们详细介绍一下提交阶段的构建环节，也就是我们经常提到的代码的编译打包。

构建环节

由于静态语言从过程上要比动态语言复杂一些，代码提交后，对于 Java 和 C++ 这样的静态语言，我们要进行代码编译和打包。而对于 PHP 和 Python 这样的动态语言，就不需要编译，直接打包即可。

同时，编译过程就开始要依赖多环境以及多环境下的配置管理，并根据不同的环境获取不同的配置，然后打包到最终的软件发布包中。

下面我就结合自己的实践经验，以 Java 为例，对构建环节做下介绍。

构建过程中我们要用到以下4 种工具：

Gitlab，代码管理工具，也是版本管理工具；

Maven，依赖管理和自动化构建工具，业界同类型的工具还有 Gradle 等；

Docker，用来提供一个干净独立的编译环境；

自动化脚本和平台，自动化构建的任务我们使用 Python 脚本来实现代码获取、编译执行、软件包生成等。

具体整个构建过程图示如下：

我们以 Java 为例描述如下。

1. 首先准备好 JDK 的编译镜像，这个镜像环境与线上运行环境保持一致，比如 OS 版本、内核参数以及 JDK 版本等基础环境。当需要启动一个构建任务时，就创建一个对应的 Docker 实例，作为独立的编译环境。

2. 构建任务会根据应用配置管理中的 Git 地址，将代码克隆下来放到指定的编译目录。Docker 实例启动后，将编译目录挂载到 Docker 实例中。

3. 执行 mvn package 命令进行编译打包，最终会生成一个可发布 war 的软件包。同样的，对于 C++、Go、Node.js，也会准备好类似的编译镜像。不同的是，打包时，对于 C++ 中的 cmake 和 make，Go 中的 go install 等等，最终也会生成一个可发布的软件包。

4. 构建完成后，生成软件包放到指定构件库目录，或者直接发布到 maven 的构件库中管理，然后将 Docker 实例销毁。

上述就是一个完整的构建过程。在这里，你一定会有一些疑问，那么，我先回答几个比较常见的问题，欢迎你留言和我继续讨论。

几个关键问题

1. 配置文件如何打包？

这个问题，我们在前面持续交付的多环境配置管理文章中，已经详细介绍过。这里我们结合构建过程，再介绍一下。

在上述第 3 个步骤中，我们要进行代码编译。按照持续交付理念，软件只需打包一次就可以各处运行，这对于代码编译是没有问题的，但是对于一些跟环境相关的配置就无法满足。

比如，我们前面讲到，不同的环境会涉及到不同的配置，如 DB、缓存。而且，其他公共基础服务在不同环境中也会有不同的地址、域名或其他参数配置。

所以，我们就需要建立环境与配置之间的对应关系，并保存在配置管理平台中，至于如何来做，大家可以参考前面多环境配置管理的文章。

这里我们回到打包过程上来。

在做构建时，我们是可以确认这个软件包是要发布到哪个环境的。比如，按照流程，当前处于线下集成测试环境这个流程环节上，这时只要根据集成测试环境对应的配置项，生成配置文件，然后构建进软件包即可。如果是处于预发环境，那就生成预发环境对应的配置文件。

在我们的实际场景中，多个环境需要多次打包，这与我们持续交付中只构建一次的理念相悖。这并不是有意违背，而是对于 Java 构建出的交付件，最终无论生成的是 war 包，还是 jar 包，上述提到的跟环境相关的配置文件，是要在构建时就打入软件包中的。

而且在后续启动和运行阶段，我们是无法修改已经构建进软件包里的文件及其内容的。这样一来，配置文件无法独立发布，那么就必须跟软件包一起发布。所以，在实际场景下，我们要针对不同环境多次打包。

那么，我们如何确保多次打包的效果能够和“只构建一次”理念的效果相一致呢？

这就还是要依赖我们前面介绍的各个环节的建设过程，主要有以下 3 个方面：

代码提交。通过分支提交管理模式，每次构建都以 master 为基线，确保合入的代码是以线上运行代码为基础的。且前面的发布分支代码未上线之前，后续分支不允许进入线上发布环节，确保发布分支在多环境下是同一套代码。

编译环境统一。上述过程已经介绍，编译环境通过全新的 Docker 容器环境来保证。

配置管理。前面介绍到的多环境配置管理手段， 通过模板和 auto-config 的配置管理能力，确保多环境配置项和配置值统一管理。

至此，一个完整的软件构建过程就完成了。可以看到，如果充分完善前期的准备工作，在做后期的方案时就会顺畅很多。

2. 为什么用 Docker 做编译环境的工具？

Docker 容器很大的一个优势在于其创建和销毁的效率非常高，而且每次新拉起的实例都是全新的，消除了环境共用带来的交叉影响。而且对于并发打包的情况，Docker 可以快速创建出多个并行的实例来提供编译环境，所以无论在效率上还是环境隔离上，都有非常好的支持。

你可以尝试一下我的这个建议，确实会非常方便。

3. 为什么不直接生成 Docker 镜像做发布？

在使用 Docker 容器做编译的过程中，我们最终取得的交付件模式是一个 war 包，或者是一个 jar 包，这个也是我们后续发布的对象。

可能有读者会问：为什么不直接生成 Docker 镜像，后续直接发布镜像？

这确实是一个好问题。如果单纯从发布的维度来看，直接发布镜像会更方便，更高效。不过，在现实场景下，我们应该更全面地看问题。

早期我们曾有一段时间使用 OpenStack+Docker 的模式进行物理机的虚拟化，以提升资源利用率。这实际上是将容器虚拟机化。

也就是说，虽然 Docker 是一个容器，但是我们的使用方式仍然是虚拟机模式，要给它配置 IP 地址，要增加很多常用命令比如 top、sar 等等，定位问题需要 ssh 到容器内。

这里一方面是因为基于 Docker 的运维工具和手段没有跟上，当时也缺少 Kubernetes 这样优秀的编排工具；另一方面，我们之前所有的运维体系都是基于 IP 模式建设的，比如监控、发布、稳定性以及服务发现等等，完全容器化的模式是没有办法一步到位的。

所以，这里我们走了个小弯路：容器虚拟机化。那为什么我们不直接使用虚拟机，还能帮我们省去很多为了完善容器功能而做的开发工作？所以一段时间之后，我们还是回归到了 KVM 虚拟机使用方式上来。

这样也就有了上述我们基于虚拟机，或者更准确地说，是基于 IP 管理模式下的持续交付体系。

经过这样一个完整的持续交付体系过程后，我们总结出一个规律：

容器也好，虚拟机也罢，这些都是工具，只不过最终交付模式不一样。但是前面我们所讲的不管是标准化、多环境、配置管理等等这些基础工作，无论用不用容器都要去做。而且，容器的高效使用，一定是建立在更加完善和高度标准化的体系之上，否则工具只会是越用越乱。

关于持续交付流水线软件构建方面的内容，我们今天先分享到这里，欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

23 | 持续交付中流水线构建完成后就大功告成了吗？别忘了质量保障

上期文章我结合自己的实践经验，介绍了持续交付中流水线模式的软件构建，以及在构建过程中的 3 个关键问题。我们可以看出，流水线的软件构建过程相对精简、独立，只做编译和打包两个动作。

但需要明确的是，在持续交付过程中，我们还要做很多与质量保障相关的工作，比如我们前面提到的各类功能测试和非功能测试。

所以，今天我们聊一聊在流水线构建过程中或构建完成之后，在质量保障和稳定性保障方面，我们还需要做哪些事情。

首先，我们回顾一下之前总结的这张流程图：

可以看出，在流水线构建过程中，我们尤其要重视以下 3 个方面的工作内容。

依赖规则限制

主要是对代码依赖的二方包和三方包做一些规则限制。比如，严格限定不允许依赖 snapshot 版本；不允许引入有严重漏洞的版本，如 struts2 的部分版本；检测 jar 包冲突，如我们常用的 netty、spring 相关的包；限定某些软件包的最低版本发布，如内部提供的二方包，以确保版本收敛，降低维护成本。

过滤规则上，通过 maven 构建软件包过程中生成的 dependency:list 文件，将 GroupID 和 ArtifactID 作为关键字，与我们设定的版本限制规则进行匹配。

两个示例如下（真实版本信息做了修改）：

检测 jar 包冲突：

[WARNING] 检测到 jar 包冲突: io.netty:netty-all, 版本: 4.0.88.Final, 当前使用: 4.0.22.Final

限定最低版本：

[WARNING] 检测到 mysql:mysql-connector-java, 版本 5.0.22, 版本不符合要求, 需要大于等于 5.0.88。旧版存在已知兼容性 bug，导致连不上数据库, 请在 2018-01-15 00:00:00 前升级完成, 否则将被禁止发布，如有疑问，请联系 @发布助手

jar 包依赖以及维护升级，通常是一件令我们比较头疼的事情，特别是在运行时出现的冲突异常，更是灾难性的。为了从技术角度更好地进行管理，我们需要做好隔离，这一点可以利用 JVM 类加载机制来实现。

如果你有兴趣，可以在网上参考阿里的潘多拉（Pandora）容器设计资料，这里我们就不作详细介绍了。

功能测试

包括单元测试、接口测试、联调测试和集成测试。这里的每个测试环节起到的作用不同，联调测试和集成测试依赖的主要手段还是手工验证，所以这里我们分享下可以通过自动化手段完成的单元测试和接口测试。

这里主要用到的几个工具：

JUnit 和 TestNG，分别做单元测试和接口测试；

Maven 插件，maven-surefire-plugin，用来执行 JUnit 或 TestNG 用例；

JaCoCo，分析单元测试和接口测试后的代码覆盖率；

Jenkins，自动化测试任务执行，报表生成和输出，与 Maven、JUnit、Gitlab 这些工具结合非常好。

关于上述这几种工具，我在此就不展开详细介绍了，你可以自行上网查询和学习。

下面，我们分析一下功能测试中的两个重要环节：单元测试和接口测试。

单元测试，由开发完成测试用例的开发，对于需要连接 DB 的用例，可以用 DBUnit 这样的框架。用例的自动执行，每次代码开发完成，开发执行 mvn test 在本地进行自测通过，然后提交到 Gitlab。可以在 Gitlab 中设置 hook 钩子，和回调地址，提交的时候在 commitMsg 增加钩子标识，如 unitTest，这样提交后就触发回调自动化单元测试用例执行接口，确保提交后的代码是单元测试通过的，最终可以通过 JaCoCo 工具输出成功率和代码覆盖率情况。

接口测试，用例编写上使用 TestNG，这个测试框架相比 JUnit 功能更全面，也更灵活一些。但是过程上与单元测试类似，当然也可以不通过 hook 方式出发，可以通过手工触发进行测试。

上述自动化测试环节结束，软件包就可以发布到我们之前说的项目测试环境或集成测试环境进行功能联调和测试了，这时就需要部分人工的介入。

非功能测试

在功能验证的同时，还需要并行进行一些非功能性验证，包括安全审计、性能测试和容量评估 。分别介绍如下：

安全审计，由安全团队提供的源代码扫描工具，在构建的同时，对源代码进行安全扫描，支持 Java 和 PHP 语言。可以对源代码中的跨站脚本、伪造请求、SQL 注入、用户名密码等敏感信息泄露、木马以及各类远程执行等常见漏洞进行识别，对于高危漏洞，一旦发现，是不允许构建出的软件包发布的。而且实际情况是，不审不知道，一审吓一跳，我们前面几次做代码扫描时，各种漏洞触目惊心，但是随着工具的支持和逐步改进，基本已经将这些常见漏洞消灭在萌芽状态。

下面是扫描结果的简单示例（目前扫描工具已经开源，请见文末链接）：

性能和容量压测，主要针对核心应用，进行发布前后的性能和容量比对，如果出现性能或容量差异较大，就会终止发布。关于这一点，我在后面稳定性保障的文章中会详细介绍到。这个验证工作，会在预发或 Beta 环境下进行验证，因为这两个环境是最接近线上真实环境的。

下图是一张发布前后的效果比对示意图，正常情况下，性能曲线应该是基本重叠才对，不应该出现较大的偏差。

最后

到这里，我们稍作一个总结。

关于持续交付中的流水线模式，我们在前面两期文章以及本期的分享中，相对完整地介绍了从需求分解开始，到代码提交、软件构建，再到功能和非功能测试验证的整个过程。这个过程就是我们常说的持续集成。

之所以我没有在一开始引入这个概念，是因为，如果我们将注意力集中到这一过程中具体的动作和问题上，会更有利于我们理解，而不是一开始就被概念性的术语和框架束缚住。

流水线模式功能测试和非功能测试的整个过程可以总结如下：

同时，我们在上面持续集成的过程中，要基于前面介绍的各类环境和基础配置管理，比如功能验证就需要在线下环境中的开发环境、项目环境以及集成测试环境上进行验收。

而非功能验证的性能和容量评估，就需要在线上环境里的预发或 beta 环境中完成。这里就已经涉及到了软件的部署发布。

下一期文章，我将分享线上发布的整个过程，并对整个持续交付体系内容做一个收尾。欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

附：源代码安全审计工具 https://github.com/wufeifei/cobra

24 | 做持续交付概念重要还是场景重要？看“笨办法”如何找到最佳方案

上期文章中我们讲到，在经过严格的依赖规则校验和安全审计之后，构建出的软件包才可以部署发布。

在开发环境、项目环境、集成测试环境以及预发环境下，我们还要进行各类的功能和非功能性测试，最后才能发布到正式的生产环境之上。

通常状况下，做一次软件版本发布，必须经过以下几个环境（如下图所示）。需要明确的是，项目环境和“小蘑菇”（内部叫法）环境，只有特殊版本才会配备，这里我们不做强制。

上述这些环境我们在之前都介绍过。而历经如此多的环境，高效的自动化持续部署和发布就变得尤为重要。

特别是最后的线上发布环节，还需要确保业务连续稳定、无间断，所以，在复杂的微服务架构环境下，我们对软件的发布策略选择、自动化程度和稳定性要求就更高了。

今天，我们一起看看整个流水线软件部署和发布的细节。

软件的持续部署发布

这里，我们直接以生产环境的发布过程来讲解。软件的部署发布，简单来说就是：

将构建完成和验证通过的应用软件包，发布到该应用对应环境下的 IP 主机上的指定目录下，并通过应用优雅上下线，来实现软件最新版本对外提供服务的过程。

这个过程会包含的环节，我以图示整理如下：

我们可以看到，软件部署发布，听上去就是把软件部署一下，然后启动起来。这样的操作方式对于单体架构软件没有问题，但是在微服务架构下就满足不了要求了。

单体架构软件启动起来就可以提供服务，但是对于微服务应用，无论停止还是启动，都需要考虑到对周边其它依赖和被依赖应用的影响才可以，考虑的点也就相对较多。

我们针对单机发布，分环节来看一下：

1. 从 CMDB 中，拿到线上生产环境下的应用主机 IP 列表去对应关系，目的是要将软件包发布到应用对应的 IP 主机上。

2. 检查每台机器上的服务是否正常运行，如果是正常服务的，说明可以发布，但是服务本身异常，就要记录或跳过。

3. 下载 war 包到指定目录。这里要依赖前期我们介绍的应用配置管理，在这一步要获取到该应用的源代码目录。

4. 关闭该应用在这台主机上的监控，以免服务下线和应用终止产生线上错误告警。

5. 优雅下线。RPC 服务从软负载下线，如果该应用还提供了 http 的 Web 调用，就需要从 Nginx 这样的七层负载下线，下线动作均通过 API 接口调用方式实现。

6. 下线后经过短暂静默，重启应用。对于 Java 应用来说，重启时可以自动解压，启停命令等还是之前从应用配置管理中获取响应路径和命令脚本名称。

7. 优雅上线，进行健康监测，检查进程和应用状态是否正常，如果全部监测通过，则开始上线服务，开启监控。

上述是一个应用的单机发布过程，过程比较长，但是可以看出，每个环节并不复杂。这里我们需要注意两个关键点：

针对场景，进行细分，这样就可以化整为零，把一个乍看上去很复杂的过程，分解成一个个可执行的步骤。

与服务化的软负载和注册中心进行交互，确保应用是可以优雅上下线的，而不是简单粗暴地启动和停止。

发布策略

上述过程是针对单机的操作步骤。但是，如果我们有上百台主机，甚至一些大的集群有上千台主机，这时应该怎么发布呢？这里就涉及到发布策略问题。

业界常见的几种模式，如蓝绿发布、灰度发布（金丝雀发布）、滚动发布等等，这几种模式网上资料丰富，在这里我们就不逐一展开详细介绍了。

这里，我们主要以灰度发布和滚动发布的组合方式为例，详细分析一下这种发布模式。

前面介绍的线上 Beta 环境，选择的就是金丝雀发布模式，我们内部称之为灰度发布或 Beta 发布。后来国外 Netflix 持续交付经验传播比较广，所以我们经常可以听到金丝雀发布这种方式，而其本质上还是灰度发布模式。

Beta 环境下，我们会保留 1-2 台应用主机，引入较少的线上真实用户流量。发布到这个环境上时，对于核心应用和大规模的集群，我们会静默较长时间，以观察应用的新版本运行状态。

如果没有严重的报错或崩溃，静默期过后，我们认为软件质量和稳定性是没有问题的，接下来就会发布到正式的生产环境上。

因为生产环境上大的集群可能会有上百台甚至上千台主机，如果每台主机逐一单独发布，这样会导致发布效率过低；但是一次性发布数量太多，又会对线上应用容量大幅度缩减，极有可能会导致服务雪崩或业务中断。

所以我们选择的方式就是滚动发布，或者可以理解为分批次发布：即每批次发布 10 台或 20 台，升级完成后，再启动下一批次发布。这样每次发布的机器数量可以自行设定，但是必须低于 50%。

至此，一个应用的滚动发布流程就结束了。根据我们实践的具体情况，这种灰度加滚动的发布模式，相对平稳和可控。相比于蓝绿发布，不需要额外再独立一个环境出来，且不需要每次发布都要做一次整体的流量切换，避免产生较大的操作风险。

对于回滚，我们会根据上个版本的 war 包名称记录，在发布过程中或发布后出现严重情况时，直接快速回滚。因为这个操作是在紧急和极端的情况下才执行，所以提供一键操作，过程跟上述的发布过程相似，在此也不再赘述。

持续交付体系的收益

持续交付体系运作起来后，整个流水线过程完全自助发布，运维无需介入，达到了 DevOps，或者说是 NoOps 的效果。如下图所示：

总结

至此，我们整个持续交付体系的内容就全部介绍完了。对于整个过程的总结，你可以参考本专栏“持续交付”主题的第一篇文章《持续交付知易行难，想做成这事你要理解这几个关键点》，我在文中对整个持续交付体系进行了比较完整的梳理。

细心的你应该可以发现，到本期文章为止，我并没有提到太多 DevOps 相关的内容，而这个恰恰是当前业界非常火热的概念。在写作过程中，我也没有特别强调持续交付是什么，持续集成是什么，而这些又是当前 DevOps 里面特别强调的部分。

我之所以这样做是因为，概念都是一个个名词或者 Buzzword（时髦名词），它们所表达的意思也都非常泛，每个人，每个团队或每个组织对它们的理解以及解读都是不一样的。

就拿 DevOps 举例，有谁能说清楚它到底是什么，到底代表什么意思？估计一千个人会有一千种理解，不同的团队对它的实践模式也不一样。

所以，如果直接从概念出发，反而容易让我们迷失方向，忘记想要解决的问题，让我们脱离所处的实际场景，把精力都放在了各种所谓的工具和技术上。这一点也恰恰与我所一直强调的，要从实际问题和业务场景出发来考虑解决方案相违背。

在我们“持续交付”主题的分享中，你可以看到，有很多的解决方案并没有标准化的模式，也没有哪一个工具或技术能够直接解决这些问题。

我们所采取的手段，其实都是些笨办法：即找到问题，分析问题，调研解决方案，讨论碰撞，然后慢慢摸索和实践，找出最合适我们的方式。

希望我的分享能够给你带来启发，就像我们开篇词提到的：思路上的转变远比技术上的提升更为重要。

欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

31 | 极端业务场景下，我们应该如何做好稳定性保障？

从今天开始，和你分享我对微服务和分布式架构下的稳定性保障的理解。

稳定性保障需要一定的架构设计能力，又是微服务架构比较核心的部分。在陈皓老师的“左耳听风”专栏，以及杨波老师的“微服务架构核心 20 讲”专栏都有非常详细的介绍。所以在我的专栏里，我会结合特定的场景，并着重从运维和技术运营的角度来分享。

我们所面对的极端业务场景

首先，看一下我们当前所面对的极端业务场景，我把它大致分为两类。

1.可预测性场景

什么是可预测性？简单来说，就像电商每年的大促，如 618、双 11、双 12 等等。这类业务场景是可预测的，业务峰值和系统压力峰值会出现在某几个固定的时间点，我们所做的所有准备工作和稳定性应对措施，都是针对这些固定时间点的，比如零点时刻。

峰值压力可预测，就意味着可以提前评估用户访问模型，并根据模型进行压测调优。发现系统中的瓶颈就调优或者扩容，调整完成之后，继续压测，继续调整，直至系统容量达到原来设定的目标。由此可见，在可预测的场景下，与后面的不可预测场景相对比，从准备过程上来说会更加从容。

但是，我们的优化或扩容是有限度的，也就是不会无限度地投入成本，来满足零点这个峰值时刻，让所有用户都能够正常访问。从成本和收益角度来说，这样做是不现实的。

所以，在峰值那个时间点上，当用户流量远远大于系统容量时，我们所采取的措施绝不是再去扩容或优化，因为无论是从时效性、系统稳定性还是成本收益上看，这样做都已经无法满足要求了。

那我们该采取什么策略呢？这里我们采取的策略是在系统承诺容量内，保证系统的核心功能能够正常运行。以电商为例，就是要确保整个交易链路是正常的，用户可以正常登陆，访问商品，下单并最终支付。对于非核心功能，就会通过预案执行功能降级。对于超出系统承诺容量的部分进行流量限流，并确保在某些异常状况下能够熔断或旁路，比如缓存故障，就要马上限流并将请求降级到数据库上。

所以，我们在 618，双 11 和双 12 的零点峰值时刻去访问各大电商网站，很大概率上都会提示系统正忙，请稍后再试，短则 2~3 分钟，长则 5~10 分钟，再去访问，网站功能就一切正常了。这并不代表各大电商网站宕机了，而是其在瞬时超大流量访问压力下采取的一种保护措施，这一点反而说明这些电商网站的大促预案非常完善。

2.不可预测性场景

我刚刚提到的电商大促场景，其实已经非常复杂了，没有一定的整体技术能力，想做好从容应对也并非易事。我们这两年做大促模拟压测，动辄上百号人通宵投入，说到底还是在这方面的经验以及各类工具平台的积累不够，体系的完善需要一定的周期和过程。

那不可预测的场景就更为复杂。社交类业务就具有这种明显的特征，比如微博、朋友圈、空间等等。以微博为例，我们知道之前鹿晗公布恋情，王宝强以及乔任梁等的突发事件等等，这些事情什么时候发生，对于平台来说事先可能完全不知道，而且极有可能是大 V 的即兴发挥。当然，现在因为商业合作上的原因，某些大 V 的部分营销活动也会与各类社交业务平台提前沟通，确保活动正常执行，但是即使是提前沟通，周期也会非常短。

对于不可预测性的场景，因为不知道什么时候会出现突发热点事件，所以就无法像电商大促一样提前做好准备。社交类业务没法提前准备，就只能随时准备着，我认为这个挑战还是非常大的。

我们要迎接的技术挑战

说完了场景，我们来看看这给技术带来了哪些挑战。

1.运维自动化

这个不难理解，应对极端场景下的系统压力，一定要有资源支持，但是如何才能将这些资源快速扩容上去，以提供业务服务，这一点是需要深入思考的。结合前面我们讲过的内容，标准化覆盖面是否足够广泛，应用体系是否完善，持续交付流水线是否高效，云上资源获得是否足够迅速，这些都是运维自动化的基础。特别是对于不可预测的场景，考验的就是自动化的程度。

2.容量评估和压测

我们要时刻对系统容量水位做到心中有数，特别是核心链路，比如电商的交易支付链路。我们只有对系统容量十分清楚，才能针对特定场景判断出哪些应用和部件需要扩容，扩容多少，扩容顺序如何。同时，系统容量的获取，需要有比较完善的自动化压测系统，针对单接口、单应用、单链路以及全链路进行日常和极端场景下的模拟压测。

3.限流降级

我们前面提到了电商大促的例子，业务在峰值时刻，系统是无论如何也抵御不住全部流量的。这个时候，我们要做的就是保证在承诺容量范围内，系统可用；对于超出容量的请求进行限流，请用户耐心等待一下。如何判断是否需要限流呢？这时我们要看系统的各项指标，常见的指标有 CPU、Load、QPS、连接数等等。

同时，对于非核心的功能，在峰值时刻进行降级，以降低系统压力。这里有两种方式，分别是主动降级和被动降级。主动降级就是在峰值时刻，主动把功能关掉，如商品评论和推荐功能等等；我们前面介绍到的静态化，也是一种降级策略。对于被动降级，也就是我们常听到的熔断。某个应用或部件故障，我们要有手段将故障隔离，同时又能够保证业务可用，所以会涉及故障判断和各类流量调度策略。

4.开关预案

上面介绍到的限流降级，也是一类开关，属于业务功能开关；还有一类是系统功能开关，比如当缓存故障时，我们就需要将请求转发到数据库上，目的也只有一个，让系统可用。但是问题来了，数据库的访问效率没有缓存高，所以缓存可以支撑的流量，数据库肯定是支撑不了的，怎么办呢？这时，就要与限流策略结合起来，先限流，限到数据库能够支撑的容量，再做降级。这样几个策略组合在一起，就是应急预案的执行了。当然，预案里面还会有业务预案。

5.故障模拟

上述预案，需要在日常，甚至是从经历过的故障中提炼出场景，制定好策略，然后不断进行模拟演练。只有这样，等到真正出现问题时，我们的预案才可以高效执行。我们知道 Netflix 的 Chaos Engineering，其中的 Chaos Monkey，就是专门搞线上破坏，模拟各种故障场景，以此来看各种预案执行是否到位，是否还有可以改进的地方。

所以，类似 Chaos Engineering 的故障模拟系统，也需要建设起来。我们需要模拟出一些场景，比如最常见的 CPU 异常，RT 响应异常，QPS 异常等等，看我们的预案是否能够快速执行，能够保持系统或将系统快速恢复到正常状态。

6.监控体系

最后，我再提一下监控。通过我们前面介绍的内容，监控的重要性就不言而喻了，因为所有的指标采集和统计，异常判断，都需要监控体系的支持。监控体系和前面介绍的运维自动化一样，都是最为基础的支撑平台。

极端业务场景下的不确定因素

上面我们讨论了极端业务场景给技术层面带来的挑战。但是对于稳定性保障而言，我认为最困难的部分，不在技术层面，而是在业务层面，也就是用户的业务访问模型。从技术层面来说，我们还有一些确定的套路可以去遵循，但是访问模型就是个极不确定的因素了。

我们这里还是以电商来举例说明，比如大促时用户下单这个逻辑。一个用户在购物车勾选商品去结算这个场景，用户的访问模型或业务场景就可能会有很多变化，比如是下 1 个商品的订单，还是同时 5 个商品的订单？每个商品的购买数量是 1 个、2 个还是 3 个？商品的购买数量有没有限制？这些商品涉及 1 个卖家，还是多个卖家？不同卖家又会有不同的优惠折扣，是买二送一，还是满 100 送 20？满一定额度之后是否包邮？全站促销是否有全站优惠，是否有时间段限制？优惠之间是否有优先级和互斥逻辑？支付方式是优先使用支付宝，还是微信，亦或是银行卡等等。

上面这些还只是简单描述，并且是针对单个用户的。当用户数量达到几十万，上百万之后，用户行为可能还有访问首页、详情页以及搜索的情况等等，场景更复杂，整个业务模型中的变量因素就会非常多，且不确定。

往往某个因素的变化，就可能带来容量模型的改变。假设 1 个商品，1 个卖家，1 个优惠策略，对 DB 产生的 QPS 是 20，TPS 是 10，但是这其中的因素稍微一变化，产生的 QPS 和 TPS 就是翻倍的。如果这一点评估不到位，大促时实际的用户场景跟预估的偏差过大，系统可能就会挂掉。

所以，对于稳定性而言，用户访问模型才是关键，这个摸不准，只有技术是没用的，这就更需要我们能够深入业务，理解业务。

我们经常听到的“脱离业务谈架构，谈技术，都是不负责任的”，原因就在于此。希望今天的内容能够让你在学习到知识和技能的同时，也有所启发，切忌脱离业务，空谈技术。

今天我们分享了极端业务场景下，如何做好稳定性保障。关于稳定性保障，你还有哪些问题？有过怎样的经验？欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

32 | 稳定性实践：容量规划之业务场景分析

上期文章我们从整体上介绍了极端业务场景下，如何做好稳定性保障工作。今天，我们结合电商大促这个场景，来看一下容量规划这项工作。

稳定性保障的一个难点是我们要面对一个非常复杂的因素，那就是业务模型，或者叫用户访问模型。因为它的不确定性，会衍生出很多不同的业务场景，而不同的场景，就会导致我们的应对策略有所不同。

所以，容量规划，就是对复杂业务场景的分析，通过一定的技术手段（如压力测试），来达到对资源合理扩容、有效规划的过程。

容量规划的场景分析

我们一直在讲，不能脱离业务场景空谈技术，所以我们还是先从电商大促这个业务场景入手来分析。

对于电商来说，核心链路就是交易链路。简单来说，就是用户要能登录，然后能通过浏览商品详情页下单订购，或者加购物车，通过购物车进行订购结算，这个过程中还要进行各种优惠的批价处理，库存的判断等等，形成订购之后，最终还要能够支付成功，一个完整的交易支付流程才算走完。

在大促的峰值时刻，场景可能又有不同，因为绝大部分用户选购什么商品，早已加入到了购物车中，且各种优惠券也已经申领成功，就等着最后这个时间点直接下单完成订购。所以，在大促这个场景下，交易下单这个环节是核心中的核心。

因为这个时间点的交易流量实在是太高了，所以近两年电商也改变了一些玩法，其目的就是希望减少峰值流量，让流量在整个大促阶段更加均匀。具体的运营和玩法细节这里就不详细介绍了。

那么，我们要应对的场景就相对清晰了，就是在大促零点峰值时刻，评估好交易流量，再进一步转化一下，就是每秒的交易订单峰值。

下图就是我们进行评估的路径分析示例，用户首先从首页、大促会场或者微信里的分享页面转化过来，然后通过搜索、店铺、详情页以及购物车进行最后的转化，形成订购下单和最终的支付。

具体数值的评估上，我们会跟产品运营团队共同讨论，整体的业务目标由运营团队给出，比如 GMV 目标收入，UV、PV、转化率、客单价以及商品单价，这些都是业务目标。通过这些业务数据，我们根据上图的路径逐步分解，就会逐步得出每一层的流量数据。

假设大促会场会有 500 万 UV，根据 GMV 和客单价，如果要完成目标，推导出到详情页的转化率需要达到 60%（产品运营需要努力达成这个业务目标），那详情页的 UV 就是 300 万；根据用户访问行为分析，对详情页的各个应用产生的 QPS 再做一个评估，这样单个应用的容量值就有了，然后再进一步向下转化，能够形成订购，形成加购物车的又有多少，再进行评估，最后就可以得出一个交易下单的峰值以及支付的峰值。

计算出峰值后，还要与历年评估的峰值数据，以及实际的峰值数据进行对比，根据对比情况进行调整。评估出来的这个峰值，就是系统要承诺支撑的容量，因为只有达到这个容量值，才能支撑业务完成对应的业务目标。

总结来说，这就是一个根据业务 GMV、UV 等目标，对技术上的交易下单峰值这个核心指标进行推导的过程。

那么，接下来就根据评估的各个应用和基础服务需要承担的流量，先扩容一轮，同时开始构造数据模型和压测模型来模拟真实流量，以此验证我们的系统是否能够达标，过程中再进行局部的扩容和优化。

一般来说，先进行单链路压测，比如购物车订购，详情页订购等场景的压测，达标后再进行多链路压测，最后再进行全链路压测，直至达成目标。为了能够保有一定的容量缓冲，最后几轮压测，我们会将压测流量调整到目标值的 120% 或 150%，来保证系统能够应对足够极端的场景，这样才能够游刃有余地实现 100% 的目标。

构造压测的数据模型

如何构造压测的数据模型呢？这是一个比较复杂的问题，因为我们靠拍脑袋或者靠猜，是无法准确评估的。通常情况下，我们从以下两方面入手。

一方面，数据模型要接近真实场景。这就需要我们不断地积累经验，记录早期大促的详细数据和真实场景（比如不同用户购物车里的商品数量、优惠策略、不同渠道比例等，以及各种运营活动的玩法），这样可以最大程度地模拟真实的用户访问模型。这个过程，蘑菇街更多的还是手工推导，像阿里做得比较极致，可以通过 BI 系统，将往年模型和当年模型进行分析比对，直接生成对应的数据模型，甚至是多套模型。

另一方面，数据量要接近真实场景。数据量有很多维度，比如用户数量、商品数量、店铺数量、优惠券数量等等。这里一般会通过数据工厂这样的工具平台，结合运营团队给出的数据量评估，快速制造出对应量级的数据。另一种方式就是从线上将真实数据，进行敏感信息脱敏处理后，导出到另一张影子表中，专门提供给压测使用，这样做的好处是不会污染线上运行数据。

总结

通过上面的分享，我们应该不难发现，容量规划工作，单纯靠技术能力是无法解决的，需要经验和数据的积累，到了阿里这个体量就必须借助人工智能和各类分析算法这样更高级的手段才能解决。

同时，容量问题，也不是简简单单通过资源扩容这种成本投入就可以解决的，扩容是最后的执行手段，但是怎么合理的、科学的扩容，就需要有合理的规划。当业务体量和复杂度到达一定程度时，就要依靠技术人员对业务的深入理解。能够合理规划业务、技术和数据模型，是需要一些经验积累，以及在各类极端场景下的经历。

最后，如此复杂的技术体系，也只有在同样复杂的场景下才会被催生出来，才会有存在意义。所以，我们在学习借鉴时，还是要从各自的实际场景出发，慢慢积累，大可不必强求短期速成。

你自己是否有过容量规划的经历？遇到过哪些问题？欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

33 | 稳定性实践：容量规划之压测系统建设

容量规划离不开对业务场景的分析，分析出场景后，就要对这些场景进行模拟，也就是容量的压力测试，用来真实地验证系统容量和性能是否可以满足极端业务场景下的要求。同时，在这个过程中还要对容量不断进行扩缩容调整，以及系统的性能优化。

今天，我们就来看压力测试的技术实现方式：压力测试系统的建设。我们详细讲讲压力测试的几个维度。

第一个维度，压测粒度

压测粒度上，我们一般会遵照从小到大的规律来做。

1.单机单应用压力测试

优先摸清单个应用的访问模型是怎样的，再根据模型进行单机单应用压力测试。这时我们就可以拿到单个应用和单个应用集群的容量水位，这个值就是后续我们根据业务模型分析之后扩容的基础。

2.单链路压力测试

获取到单个应用集群的容量水位之后，就要开始对某些核心链路进行单独的压力测试，比如商品详情浏览链路、加购物车链路、订购下单链路等等。如下图的交易下单链路压测模型示例，连线上的数字是不同应用或接口调用的流量占比。

3.多链路 / 全链路压力测试

当单链路的压测都达标之后，我们就会组织多链路，或者全链路压测。多链路本质上就是多个单链路的组合，全链路就是多链路的组合。如下图就是多个交易场景的多链路组合。

第二个维度，压测接口及流量构造方式

接口一般分为 HTTP 接口和 RPC 接口，这一点应该不难理解，就不做过多讲解了。

流量构造方式上，根据压测粒度的不同，会采用不同的方式，我们常见的有以下几种方案。

1.线上流量回放

这种方式直接利用了线上流量模型，比较接近真实业务场景，常见的技术手段如 TCPCopy，或者 Tcpdump 抓包保存线上请求流量。但是这种方式也存在一些代价，比如需要镜像请求流量，当线上流量非常大的时候就很难全部镜像下来，而且还需要大量额外的机器来保存流量镜像。到了回放阶段，还需要一些自动化的工具来支持，还要解决各种 session 问题，真正实施的时候，还是会有不少的工作量。

2.线上流量引流

既然线上回放比较麻烦，那为什么不直接使用线上流量进行压测呢？这个思路确实是可行的，我们前面讲过，压测的主要是 HTTP 和 RPC 两种类型的接口，为了保证单个应用的流量压力足够大，这里可以采取两种模式。

一个是将应用集群中的流量逐步引流到一台主机上，直到达到其容量阈值；另一个方案是，可以通过修改负载均衡中某台主机的权重，将更多的流量直接打到某台主机上，直到达到其容量阈值。

这个过程中，我们可以设定单台主机的 CPU、Load 或者 QPS、RT 等阈值指标，当指标超出正常阈值后就自动终止压测，这样就可以获取到初步的容量值。

这种方式的好处是，不需要额外的流量模拟，直接使用最真实的线上流量，操作方便，且更加真实。下图是两种引流的方案示例。

3.流量模拟

上述两种流量模拟方式，更适合日常单机单应用的容量压测和规划，但是对于大促这种极端业务场景，真实流量就很难模拟了，因为这种场景只有特定时刻才会有，我们在日常是无法通过线上流量构造出来的。

所以这里就需要利用数据工厂，最终通过流量平台来形成压测流量。这里的工具用到了 Gatling，是一款开源的压测工具，用 Scala 开发的，后来我们针对自己的需求，比如自动生成压测脚本等，做了一些二次开发。

如果会有多种流量模型的话，就要生成多个流量模型，具体可见下图：

第三个维度，施压方式

上面介绍了容量压测的构造过程，那接下来我们要做的就是对真实的线上系统施加压力流量了。很自然的，这里就需要有施加压力的机器，在上面“全链路压测系统”那张图中，你可以看到，我们的施压方式是通过上百台的机器根据压测脚本和压测数据对系统施压的，我来简单介绍一下大致过程。

通过实现在 Web 控制台配置好的压测场景，自动生成压测脚本。

利用数据工厂构造出压测数据，这个就是业务场景的模拟，像阿里做得比较完善，就可以借助 AI 和 BI 的技术手段生成很多压测模型，且基本都接近于现实情况下的业务场景。

通过 Web 控制台，根据压测脚本和压测数据，生成压测任务，推送到压测集群的 Master 节点，再通过 Master 节点推动到上百台的 Slave 节点，然后就开始向线上系统施加模拟的流量压力了。

关于施压机的分布，大部分仍然是跟线上系统在同机房内，少量会在公有云节点上。但是对于阿里，因为其自身的 CDN 节点遍布全球，所以他就可以将全球（主要是国内）的 CDN 节点作为施压机，更加真实地模拟真实用户从全球节点进入的真实访问流量。这种方式对于蘑菇街就显得成本过高，技术条件和细节也还达不到这个程度。

当前阿里已经将这种压测能力输出到了阿里云之上，可以说是对其云生态能力的有力补充，同时也为中小企业在容量规划和性能压测方面提供了很好的支持。

第四个维度，数据读写

压测过程中，对于读的流量更好构造，因为读请求本身不会对线上数据造成任何变更，但是对于写流量就完全不一样了，如果处理不好，会对线上数据造成污染，对商家和用户造成资损。

所以，对于写流量就要特殊处理，这块也有比较通用的解决方案，就是对压测的写请求做专门的标记。当请求要写数据库时，由分布式数据库的中间件框架中的逻辑来判断这个请求是否是压测请求，如果是压测写请求则路由到对应的影子库中，而不是直接写到线上正式的库中。

在这之前，要提前创建好对应的影子库。假设建立影子库的原则是原 schema + mirro，如果正式库是 order，则影子库为 order_mirror，这时两个库中的数据量必须是一致的。对于非敏感信息，数据内容也可以保持一致，这样可以在最大程度上保证数据模型一致。

这里再呼应一下我们最开始提到的基础服务标准化工作，如果这个工作在前面做得扎实，它的优势在这里就体现出来了。我们刚刚提到的影子库的路由策略是基于中间件框架来实现的，如果使用的框架不一样，不是标准的，这个功能可能就很难应用起来。这一点在后面全链路以及开关等稳定性方案中，还会涉及到。

今天我们介绍了容量压测的技术方案，比较复杂，而且需要对相应场景进行针对性的建设。关于细节部分，你还有什么问题，欢迎留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

34 | 稳定性实践：限流降级

本周我们继续来讨论稳定性实践的内容。在现实情况下，当面对极端的业务场景时，瞬时的业务流量会带来大大超出系统真实容量的压力。

为了应对，前面我们介绍了容量规划方面的实践经验。不过，我们不会无限度地通过扩容资源来提升容量，因为无论从技术角度，还是从成本投入角度，这样做都是不划算的，也是不现实的。

所以，我们通常采取的策略就是限流降级，以保障承诺容量下的系统稳定；同时还有业务层面的开关预案执行，峰值时刻只保障核心业务功能，非核心业务功能就关闭。

今天我们就先来介绍一下限流降级的解决方案。

什么是限流和降级

首先，我们先梳理清楚限流和降级的概念，明白它们会发挥怎样的作用，这样才便于我们理解后续的解决方案。

限流，它的作用是根据某个应用或基础部件的某些核心指标，如 QPS 或并发线程数，来决定是否将后续的请求进行拦截。比如我们设定 1 秒 QPS 阈值为 200，如果某一秒的 QPS 为 210，那超出的 10 个请求就会被拦截掉，直接返回约定的错误码或提示页面。

降级，它的作用是通过判断某个应用或组件的服务状态是否正常，来决定是否继续提供服务。以 RT 举例，我们根据经验，一个应用的 RT 在 50ms 以内，可以正常提供服务，一旦超过 50ms，可能就会导致周边依赖的报错或超时。所以，这时我们就要设定一个策略，如果应用的 RT 在某段时间内超过 50ms 的调用次数多于 N 次，那该应用或该应用的某个实例就必须降级，不再对外提供服务，可以在静默一定时间后（比如 5s 或 10s）重新开启服务。

这里再特别说一下降级，今天我们讲的内容可以理解为服务降级，后面我会介绍业务开关，可以理解为业务降级。这里只是叫法不同，不同的人有不同的理解，所以我们在讨论概念时，还是尽量回到我们要解决的问题和场景上来，上下文保持一致了，在观点和思路上也更容易达成一致。

讲到这里，再提个问题，我们讲的降级，和熔断这个概念是什么关系？你不妨停下来，按照我们刚刚讲过的思路思考一下。

常见的限流解决方案

我们先看几种常见的限流类型。

第一类，接入层限流。

作为业务流量的入口，我们限流的第一道关卡往往会设置在这里，而且接入层限流往往也是最有效的。这里又有两类解决方案，根据接入层所使用的技术方案而定。

1.Nginx 限流

Nginx 或其开源产品是最常用的 Web 服务器，我们使用的是 TEngine。对于一个 Web 类应用，如 Web 页面或 H5 页面，我们通常会将限流策略增加到这一层，会设置 QPS、并发数以及 CPU 的 Idle 作为限流指标。Nginx 有对应的函数接口，可以获取到以上指标信息，然后通过 Lua 脚本实现限流的逻辑，并作为 TEngine 的插件安装即可。

2.API 路由网关模式

对于客户端模式的接入，我们使用了 API 路由网关模式，一方面可以更方面地管理客户端与服务端的链接，另一方面也可以通过配置的方式管理服务接口，这里的服务管理会复用到微服务架构的配置中心，并实现相应的路由策略。对于 QPS 和并发限流，直接在配置中心中进行配置即可。

第二类，应用限流。

这一类的限流策略跟上面 API 路由网关模式的限流相似，同样是依赖配置中心管理，限流逻辑会配套服务化的框架完成。

第三类，基础服务限流。

主要针对数据库、缓存以及消息等基础服务组件的限流而设定。同样，限流逻辑会配套分布式数据库中间件，缓存或消息的框架来实现。

讲到这里，我来解释几个关键的技术点。

资源和策略。资源是我们要进行限流的对象，可能是一个应用，或者一个方法，也可能是一个接口或者 URL，体现了不同的限流粒度和类型。策略就是限流的规则，比如下面我们要提到的 QPS 和并发数限流。

时间精度。主要指对于 QPS、并发数或 CPU 的阈值判断。比如对于 QPS，我们就会设定一个 QPS 时间精度（假设 3s），如果低于阈值则不启用策略，如果超过阈值就启动限流策略。

指标计数。对于并发限制请求，会统计当前的并发数，1 次请求进入到限流模块加 1，等请求结束退出时减 1，当前正在处理的请求数就是并发数。对于 QPS 限流，统计 QPS 不能按照秒统计，因为第 1s，系统可能就被打挂了，所以 QPS 得按照毫秒级别去统计，统计的级别越小，性能损耗越大。所以定在 10ms~100ms 的级别去统计会更平滑一些，比如将 1s 切成 10 份，每一份 100ms，一个请求进来肯定会落在某一份上，这一份的计数值加 1。计算当前的 QPS，只需要将当前时间所在份的计数和前面 9 份的计数相加，内存里面需要维护当前秒和前面 2 秒的数据。

限流方式。对于 Nginx 就针对总的请求进行限流即可，但是粒度会比较粗。对于应用层，因为配置中心的灵活性，其限流就可以做得更细化。比如可以针对不同来源限流，也可以针对去向限流，粒度上可以针对类级别限流，也可以针对不同的方法限流，同时还可以针对总的请求情况限流，这些灵活策略都可以在微服务的配置中心实现。

Spring AOP。对于 Java 应用，绝大多数公司都会用到 Spring 框架，包括我们上面讲到的分布式数据库等组件，也一样会依赖 Spring 框架，比如我们用到的 MyBatis 开源组件。而 Spirng 框架中的关键技术点，就是 IoC 和 AOP，我们在限流方案的实现上，也会利用到相关技术。简单来说就是，我们通过配置需要限流的方法作为 AOP 的切入点，设定 Advice 拦截器，在请求调用某个方法，或请求结束退出某个方法时，进行上述的各种计数处理，同时决定是否要进行限流，如果限流就返回约定好的返回码，如果不限流就正常执行业务逻辑。基于 AOP 这样一个统一的技术原理，我们就可以开发出与业务逻辑无关的限流组件，通常会在对外的服务调用、数据库调用、缓存调用、消息调用这些接口方法上设置默认的切面，并在业务代码运行时注入，这样就可以做到对业务透明，无侵入性。

Web 类型的限流。对于 Web 类型 URL 接口限流，我们就利用 Servlet 的 Filter 机制进行控制即可。

控制台。上面我们讲了各种配置和策略，如果都是通过人工来操作是不现实的，这时就需要开发对应的限流降级的控制台，将上述的各种配置和策略通过界面的方式进行管理，同时在配置完成之后，能够同步到对应的服务实例上。比如对于 Nginx，当一个策略配置完成后，就要同步到指定的服务器上生成新的配置文件并 Reload。对于配置中心模式的策略，也就是 Spring AOP 模式的限流，在控制台上配置完成后，就要将配置值同步更新到配置中心里，同时再通过运行时的依赖注入，在线上运行的业务代码中生效。

整体简化的示意图如下：

限流降级的难点

上面整体介绍了限流降级的解决方案，我们可以看到涉及到很多新概念，各种不同的限流类型，同时还有比较复杂的技术细节，所以要清晰地理解这些概念。

对于降级，主要是针对 RT 来进行判断，它的整个技术方案没有限流这么复杂，且思路上跟限流是相似的，所以我们就不再单独介绍降级的技术方案了。

从整个建设过程来看，我的体会是，限流降级的难点和关键还是在于整体技术栈的统一，以及后期对每个应用限流降级资源策略的准确把握和配置。

我们先来看整体技术栈的统一，这其实也就是我们在专栏最开始就讲到的标准化建设。这里我们会基于一个统一的技术栈进行限流降级方案的设计，要求有统一的 Web 服务器类型。对服务化框架、各类分布式框架以及代码开发框架（如 Spring），这些都要有很明确的要求。如果这里面有某些应用使用的框架不同，那么这套统一的方案就无法推广落地。

我们在实际推广过程中就遇到很多类似的问题，导致大量的时间耗费在技术栈统一上，甚至会要求业务代码做出改变和调整，代码上线运行后再进行统一，这个代价是非常大的。

这也是为什么我们在一开始就非常强调标准化的重要性。这里我们再强调一下标准化，再来复习一下以应用为核心的运维体系的思维导图。

再来看对应用的限流降级资源策略的把握，这个就需要对应用和业务有深入的了解。比如开发人员要非常清楚哪些接口是核心接口，它的来源和去向有哪些；哪些来源是核心的，哪些是非核心的；如果要限流，需要对哪些接口限流，同时要重点保障哪些接口等等。

对于限流和降级的具体策略，就是 QPS 和并发数的配置，也要来源于线上实际运行维护的经验，才能知道配置多少是合适的，配置太大没有限流效果，太小又会频繁触发限流，影响正常业务运行。

所以，限流和降级也是一个动态调测和完善的过程，对于有些动态变化的资源是做不到一劳永逸的。

怎么办呢？一方面我们要依赖人的经验；另一方面，从最终的解决方案看，当调用次数和日志达到一定体量时，我们希望能够借助机器学习算法的手段，来帮助我们分析什么样的设置是最合理的。

今天我们讨论了限流和降级的概念、解决方案以及难点，欢迎留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

35 | 稳定性实践：开关和预案

在稳定性保障中，限流降级的技术方案，是针对服务接口层面的，也就是服务限流和服务降级。这里还有另外一个维度，就是业务维度，所以今天我们就从业务降级的维度来分享，也就是开关和预案。

如何理解开关和预案

开关，这个概念更多是业务和功能层面的，主要是针对单个功能的启用和停止进行控制，或者将功能状态在不同版本之间进行切换。

在业务层面，就像我们前面经常提到的大促场景案例，我们会关闭掉很多非核心功能，只保留交易链路的核心功能。比如我们认为商品评论是非核心功能，这时就会通过开关推送这种方案将这个功能关闭。当用户访问商品详情页时，这个接口就不再被调用，从用户角度来说，就是在大促峰值时刻看不到所浏览商品的评论列表。

在功能层面，我们技术架构中会使用缓存技术，但是要考虑到缓存有可能也会出现故障，比如不可访问，或者数据错乱异常等状况，这时我们就会考虑旁路掉缓存，直接将请求转到数据库这一层。

这里有两种做法：一种做法是通过我们上一篇介绍到的降级手段，也就是我们常说的熔断，自动化地旁路；另一种做法，比如在数据异常情况下，请求是正常的，但是数据是有问题的，这时就无法做到自动化旁路，就要通过主动推送开关的方式来实现。

预案，可以理解为让应用或业务进入到某种特定状态的复杂方案执行，这个方案最终会通过开关、限流和降级策略这些细粒度的技术来实现，是这些具体技术方案的场景化表现。

我们还是接着上面的这个案例来讨论。因为每个业务或应用都会有自己的开关配置，而且数量会有很多，如果在大促前一个个推送，效率就会跟不上，所以我们就会针对某个应用的具体场景，提供批量操作的手段，通过预案场景将同一应用，甚至多个应用的开关串联起来。

比如上面提到的商品详情页，我们不仅可以关闭商品评论，还可以关闭商品收藏提示、买家秀、店铺商品推荐、同类型商品推荐以及搭配推荐等等。有了场景化的预案，管理和维护起来就会更容易。

除了业务层面的预案，我们还可以将预案应用到应急场景下，比如上面提到的缓存故障异常。在真实场景下，要考虑得更全面，比如缓存能够支撑的业务访问量是要远远大于数据库的，这时我们就要做功能降级，这就要考虑数据库是否能够支撑住这么大的请求量（通常情况下肯定是支撑不住的）。所以，遇到这种场景，我们首要考虑的是限流，先将业务流量限掉三分之一甚至是一半，然后再将功能降级到数据库上。

这样就又涉及到多种策略的串行执行。如果没有预案都是单个执行的话，效率肯定会低，而且还可能涉及到多个应用都会执行相同的业务降级策略，这时就必须要有预案来统一管理，提前梳理好哪些应用需要在这种场景下执行对应的开关、限流和降级策略。

技术解决方案

技术方案上并不复杂，开关的字段主要以 Key-Value 方式管理，并从应用维度，通过应用名管理起来，这个对应关系就可以放到统一的控制台中管理。

下图是整个开关和预案管理，以及推送的示意图，我们一起分步骤看一下。

1.开关管理

通过上述我们所说的 Key-Value 方式保存，与代码中的具体 Field 字段对应起来。这里就又会涉及到我们上篇内容中讲到的 Spring 的 AOP 和注解技术。

如下面代码所示，我们通过注解方式定义了一个开关 testKey，它与控制台中配置的 Key 相对应，并获取对应的 Value 取值，在业务运行阶段，我们就可以根据这个值，来决定业务执行逻辑，下面是简化的示例。

@AppSwitcher(key="key1",valueDes = "Boolean 类型 ")

 private Boolean key1;

代码中直接调用 AppName 对应的开关配置，进行不同业务逻辑的实现：

Boolean key1 = MoguStableSwitch.isStableSwitchOn("key1");

if (key1)

{

// 开关打开时业务逻辑实现

}else

{

// 开关关闭时业务逻辑实现

}

2.开关推送

当在控制台上修改开关值后，会推送到微服务的配置中心做持久化，这样当应用下次重启时依然可以获取到变更后的值。还有另外一种方式，就是通过 HTTP 的方式推送，这种情况的应用场景是，当第一种情况失败时，为了让开关快速生效预留的第二个接口。

3.配置变更

应用中引入的开关 SDK 客户端会监听对应配置的变更，如果发生变化，就会马上重新获取，并在业务运行时生效。

4.预案执行

就是多个开关策略的串行执行，会重复上面这几个关键步骤。

关于开关和预案的内容，我们今天就介绍到这里。留一个问题，我们在上篇文章中介绍到限流降级方案的难点，请你思考一下，我们今天讲的开关预案这个内容，可能会遇到哪些难点呢？欢迎留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

36 | 稳定性实践：全链路跟踪系统，技术运营能力的体现

今天我们来分享全链路跟踪系统建设方面的内容。我们知道，随着微服务和分布式架构的引入，各类应用和基础组件形成了网状的分布式调用关系，这种复杂的调用关系就大大增加了问题定位、瓶颈分析、容量评估以及限流降级等稳定性保障工作的难度，如我们常见的调用网状关系。

图片出自：https://www.linkedin.com/pulse/100-million-members-125-hours-watched-per-day-hundreds-probst/

正是这样的背景，催生了分布式链路跟踪，也叫全链路跟踪的解决方案。

关于这一块的技术解决方案，在 Google 的 Dapper 论文发表之后，近些年业界已经有非常多且非常成熟的实践经验和开源产品。

比如阿里的鹰眼系统，就是全链路跟踪系统在国内的最佳实践；再比如美团点评的 CAT 分布式监控系统，也是从产品实践中逐步开源出来，在业界已经得到了非常广泛的应用；还有一些独立的开源产品，比如国内分布式监控技术专家吴晟创建的 Skywalking 项目，也是非常优秀的产品，而且也有比较广泛的应用。

除此之外，还有大量优秀的商业产品，这类产品通常叫 APM，应用性能管理系统，比如国内的听云、博瑞、OneAPM 等等，他们在产品化方面做的会更完善，在很多场景下可以非常方便地落地应用。

介绍上述这些产品，主要还是想说明，当前在分布式或全链路跟踪监控这个领域，无论是在技术还是产品层面都已经相对成熟，我们完全可以通过对这些产品的调研来选择适合自己的解决方案。

蘑菇街在这块也是自研了一套体系，但是技术方案和思路上跟上述这些开源或商业产品都很相似，所以技术层面我就不再做详细赘述。

如果想深入了解相关内容，一方面可以在网上找到非常多的资料，甚至是去阅读源码；另一方面还是推荐极客时间上陈皓老师的《左耳听风》专栏和杨波老师的《微服务架构核心 20 讲》，两位都是骨灰级的微服务和分布式架构专家，他们在技术层面的分享会更有深度和针对性。

全链路跟踪系统在技术运营层面的应用

接下来，主要分享我们利用全链路跟踪系统在技术运营层面做的一些事情，这里提到的运营，就是应用在线上运行时，我们根据应用运行数据所做的运行维护工作，这里我们会更加强调数据的作用。

同时，这里的一个核心技术点就是 TraceID，当请求从接入层进来时，这个 TraceID 就要被创建出来；或者是通过 Nginx 插件方式创建放到 http 的 header 里面；或者是通过 RPC 服务化框架生成。然后在后续的请求中，这个字段会通过框架自动传递到下一个调用方，而不需要业务考虑如何处理这个核心字段。

有了这个 TraceID，我们就可以将一个完整的请求链路给串联起来了，这也是后面场景化应用的基础。下面我们就一起来看会有哪些具体的技术运营场景。

第一个场景，问题定位和排查

我们做全链路跟踪系统，要解决的首要问题就是在纷繁复杂的服务调用关系中快速准确地定位问题，所以这个场景是绕不开的。

我们常见的问题场景，主要有两类：瓶颈分析和异常错误定位。

首先看瓶颈分析。常见的问题就是某某页面变慢了，或者某个服务突然出现大量超时告警，因为无论是页面也好，还是服务也好，在分布式环境中都会依赖后端大量的其它服务或基础部件，所以定位类似的问题，我们期望能有一个详细的调用关系呈现出来，这样我们就可以非常方便快速地判断瓶颈出现在什么地方。

比如下图的情况，就是某个页面变慢。我们根据 URL 查看某次调用的情况，就发现瓶颈是在 RateReadService 的 query 接口出现了严重阻塞。接下来，我们就可以根据详细的 IP 地址信息，到这台机器上或者监控系统上，进一步判断这个应用或者这台主机的异常状况是什么，可能是机器故障，也可能是应用运行故障等等。

￼

再来看一个案例。下图中我们可以看到，一次完整的请求耗时比较长，但是通过调用链分析会发现，其中任何一个单次请求的时延又非常低，并没有像上个案例那样有明显的请求瓶颈。我们再进一步分析，就会发现整个请求的列表非常长，且请求列表里面都是在访问缓存内容。很显然，这样的调用方式不合理，需要我们优化调用逻辑，要么通过批量接口方式，要么通过异步的方式，再或者要去分析业务场景是否合理。

通过上面的案例，我们可以看到，在应用了全链路跟踪的解决方案后，复杂调用关系下的问题定位就相对简单多了。

对于出现异常报错，也是一样的判断逻辑，限于篇幅我就不再赘述了。

第二个场景，服务运行状态分析

上面的问题定位，主要还是针对单次请求或相对独立的场景进行的。更进一步，我们在采集了海量请求和调用关系数据后，还可以分析出更有价值的服务运行信息。比如以下几类信息。

1. 服务运行质量

一个应用对外可能提供 HTTP 服务，也可能提供 RPC 接口。针对这两类不同的接口，我们可以通过一段时间的数据收集形成服务接口运行状态的分析，也就是应用层的运行监控，常见的监控指标有 QPS、RT 和错误码，同时还可以跟之前的趋势进行对比。这样就可以对一个应用，以及对提供的服务运行情况有一个完整的视图。

2. 应用和服务依赖

除了上述单个应用的运行状态，我们还可以根据调用链的分析，统计出应用与应用之间，服务与服务之间的依赖关系及依赖比例，如下图所示。

这个依赖管理的作用，就是给我们前面介绍的容量压测和限流降级这两个工作做好准备。我们可以根据来源依赖和比例评估单链路的扩容准备；同时根据去向依赖进行流量拆分，为下游应用的扩容提供依据，因为这个依赖比例完全来源于线上真实调用，所以能够反映出真实的业务访问模型。

同时，根据这个依赖关系，特别是服务依赖关系，我们还可以进一步分析依赖间的强弱关系，也就是强弱依赖。这一点又对我们做限流降级提供了对应的依据，也就是我们前面所说的，我们限流也好，降级也好，都是优先对非核心业务的限流和降级，这样的业务形成的依赖，我们就认为是弱依赖，是不关键的；但是对于核心业务我们就要优先保障，它们形成的依赖关系，是强依赖。无论是扩容也好，还是优化性能也罢，都要最大限度地确保强依赖关系的调用成功。

所以，强弱依赖的分析，还是要从业务场景入手。比如对于电商来说，核心就是交易链路，我们就要判断如果一条链路上的某个应用或服务失败了，是不是会影响订购下单，或者影响支付收钱，如果影响，就要标注为强依赖，这个应用就要标注为核心应用；如果这个应用失败了，可以通过限流或降级的方式绕过，只是影响用户体验，但是不影响用户订购支付，那这个依赖关系就可以标注为弱依赖，该应用就可以标注为非核心应用。

同时，因为我们的业务场景和需求在不断变化，应用和服务间的调用关系和依赖关系也是在不断变化中的，这就需要我们不断地分析和调整强弱依赖关系，同时也要关注各种调用间的合理性，这个过程中就会有大量的可优化的工作。

通常情况下，这些事情对于业务架构师和运维人员来说，都会比较关注。因为业务架构师要对业务访问模型十分了解，他要经常关注这些信息；而运维会关注线上稳定性，需要在关键时刻执行限流降级或开关预案策略，所以也必须对这些信息非常熟悉。

3. 依赖关系的服务质量

上面介绍了应用和服务间的依赖管理，同样的我们也会关注被依赖的应用或服务的实时运行状态和质量，这样就可以看到应用间实时的调用状态。是不是有的应用调用 QPS 突然增加了，或者 RT 突然暴涨，通过这个依赖关系就可以快速确认。

￼

第三类场景，业务全息

顾名思义，业务全息就是全链路跟踪系统与业务信息的关联。从上述的介绍中，我们可以看到，全链路跟踪系统的应用更多的还是在技术层面，比如定位“应用或服务”的问题，应用或服务间的依赖关系等等。

但是现实中，我们也会遇到大量的业务链路分析的场景，比如可能会有针对某个订单在不同阶段的状态等。假设一个情况是用户投诉，他的订单没有享受到满 100 元包邮的优惠，这时我们就要去查找用户从商品浏览、加购物车到下单整个环节的信息，来判断问题出在哪儿。其实，这个场景和一个请求的全链路跟踪非常相似。

所以，为了能够在业务上也采用类似的思路，我们就将前面介绍到的请求链路上的唯一 TraceID 与业务上的订单 ID、用户 ID、商品 ID 等信息进行关联，当出现业务问题需要排查时，就会根据对应的 ID 将一串业务链整个提取出来，然后进行问题确认。这就会极大地提升解决业务问题的效率。

总结

今天我们从技术运营层面的应用这个角度重新认识了全链路跟踪系统。同时，从这个案例中，我们也应该看到，技术、产品和运营相辅相成，共同促进彼此的完善和成熟。

全链路跟踪系统在技术方案的广泛应用，给我们提供了大量可分析处理的线上运行数据，从这些数据中，我们又能提炼出对线上稳定运行更有价值的信息。所以，技术之外，我们也应该更多地考虑技术在价值方面的呈现。

今天的内容就介绍到这里，你在这方面遇到过哪些问题，有怎样的经验，欢迎留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

37 | 故障管理：谈谈我对故障的理解

对于任何一个技术团队来说，最令人痛苦、最不愿面对的事情是什么？我想答案只有一个，那就是：故障。

无论是故障发生时的极度焦虑无助，还是故障处理过程中的煎熬痛苦，以及故障复盘之后的失落消沉，都是我们不愿提及的痛苦感受。在海外，故障复盘的英文单词是 Postmortem，它有另外一个意思就是验尸，想想就觉得痛苦不堪，同时还带有一丝恐怖的意味。

写故障相关的文章，也着实比较痛苦。一方面回顾各种故障场景，确实不是一件令人愉悦的体验；另一方面，故障管理这个事情，跟技术、管理、团队、人员息息相关，也是一套复杂的体系。

我们看 Google SRE 这本书（《SRE：Google 运维解密》），绝大部分章节就是在介绍故障相关的内容。其实看看这本书就能明白稳定性和故障管理这项系统工程的复杂度了，而且从本质上讲，SRE 的岗位职责在很大程度上就是应对故障。

所以，接下来的几期文章，我会谈谈我对故障管理的理解，以及一些实际经历的感受，也希望我们每一个人和团队都能够在故障管理中得到涅槃重生。

今天，先谈谈我们应该如何来看待故障这个事情。

系统正常，只是该系统无数异常情况下的一种特例

上面这句话，来自 Google SRE 这本书，我认为这是一个观点，但是更重要的，它更是一个事实。所以，正确理解故障，首先要接受这个现实。

故障，是一种常态，任何一个软件系统都避免不了，国内最牛的 BAT 避免不了，国外最牛的 Google、Amazon、Facebook、Twitter 等也避免不了。业务体量越大，系统越复杂，问题和故障就越多，出现故障是必然的。

可能你会有疑问，既然他们也存在各种故障，但是在我们的印象中，好像也没经常遇到这些大型网站整天出问题或不可访问的情况，这恰恰说明了这些公司的稳定性保障做得非常到位。

这里有一个非常重要的体现，就是Design for Failure的理念。我们的目标和注意力不应该放在消除故障，或者不允许故障发生上，因为我们无法杜绝故障。所以，我们更应该考虑的是，怎么让系统更健壮，在一般的问题面前，仍然可以岿然不动，甚至是出现了故障，也能够让业务更快恢复起来。

其实对这个理念的实践，我们在前面都已经介绍过了，比如限流降级、容量评估以及开关预案等技术方案的稳定性保障体系，这些技术方案本质上并不是为了杜绝故障发生，而是为了能够更好地应对故障。

同样的，我们刚提到的那些国内外超大型网站，之所以能够保持很高的稳定性和业务连续性，恰恰是说明他们在故障隔离、快速恢复、容灾切换这些方面做得非常优秀，一般的问题或故障，根本不会影响到业务访问。

所以，转变一下思路，重新理解系统运行的这种特点，会给我们后续在如何面对故障、管理故障的工作中带来不一样的思考方式。

故障永远只是表面现象，其背后技术和管理上的问题才是根因

简单表述一下，就是永远不要将注意力放在故障本身上，一定要将注意力放到故障背后的技术和管理问题上去。

这里的逻辑是这样的，技术和管理上的问题，积累到一定量通过故障的形式爆发出来，所以故障是现象，是在给我们严重提醒。

有时我们过分关注故障本身，就容易揪着跟故障相关的责任人不放，这样会给责任人造成很大的负面压力，进而导致一些负面效应的产生，这一块在后面我还会专门分享。

与之对应的改进措施，往往就容易变成如何杜绝故障。前面我们讲到，从现实情况看这是完全不可能的，所以就容易输出一些无法落地、无法量化的改进措施。

你可以思考一下，面对故障的时候，是不是经常出现上述这两种情况。

所以，想要更好地应对和管理故障，当故障发生后，我们需要考虑的问题应该是其背后存在的技术和管理问题。这里和你分享我自己在故障后的复盘中，经常会反思和提出的几个问题。

为什么会频繁出故障？是不是人员技术不过硬？人为操作太多，自动化平台不完善，操作没有闭环？代码发布后的快速回滚措施不到位？

为什么一个小问题或者某个部件失效，会导致全站宕机？进一步考虑，是不是业务高速发展，技术架构上耦合太紧，任何一个小动作都可能是最后一根稻草？是不是容量评估靠拍脑袋，系统扛不住才知道容量出问题了？是不是限流降级等保障手段缺失，或者有技术方案，但是落地效果不好？

为什么发生了故障没法快速知道并且快速恢复？进一步考虑，是不是监控不完善？告警太多人员麻木？定位问题效率低，迟迟找不到原因？故障隔离还不够完善？故障预案纸上谈兵？

管理上，团队成员线上敬畏意识不够？还是我们宣传强调不到位？Oncall 机制是否还需要完善？故障应对时的组织协作是不是还有待提升？

总结下来，任何一个故障的原因都可以归结到具体的技术和管理问题上，在故障复盘过程中，通常会聚焦在某个故障个例上，归纳出来的是一个个非常具体的改进措施。

用一句话总结：“理解一个系统应该如何工作并不能使人成为专家，只能靠调查系统为何不能正常工作才行。”（From SRE ，by Brian Redman）

最后，作为管理者，我会问自己一个终极问题：下次出现类似问题，怎么才能更快地发现问题，更快地恢复业务？即使这一次的故障应对已经做得非常好了，下次是否可以有更进一步的改进？

这个问题，会促使我个人更加全面地思考，且能够关注到更全局的关键点上。比如，是不是应该考虑有更加完善的发布系统，减少人为操作；是不是应该有整体的稳定性平台建设，包括限流降级、开关预案、强弱依赖、容量评估、全链路跟踪等子系统，以及建设完成后，应该如何一步步的落地；还有，故障预案和演练应该如何有效的组织起来，毕竟这些是从全局考虑，自上而下的一个过程。

最后

再表达两个观点。

第一，出问题，管理者要先自我反省。不能一味地揪着员工的错误不放，员工更多的是整个体系中的执行者，做得不到位，一定是体系上还存在不完善的地方或漏洞。在这一点上，管理者应该重点反思才对。

第二，强调技术解决问题，而不是单纯地靠增加管理流程和检查环节来解决问题，技术手段暂时无法满足的，可以靠管理手段来辅助。比如我上面提到的就基本都是技术手段，但是要建设一个完善的体系肯定要有一个过程，特别是对于创业公司。这时可以辅以一些管理措施，比如靠宣传学习，提升人员的线上安全稳定意识，必要的 Double Check，复杂操作的 Checklist 等，但是这些只能作为辅助手段，一定不能是常态，必须尽快将这些人为动作转化到技术平台中去。

这样做的原因也很明显，单纯的管理手段还是靠人，跟之前没有本质区别，只不过是更加谨小慎微了一些而已。同时，随着系统复杂度越来越高，迟早有一天会超出单纯人力的认知范围和掌控能力，各种人力的管理成本也会随之上升。

今天和你分享了我对故障这件事情的理解，期望这样一个不同角度的理解能够带给你一些启发，欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

38 | 故障管理：故障定级和定责

故障管理的第一步是对故障的理解，只有正确地面对故障，我们才能够找到更合理的处理方式。今天就来和你分享关于故障定级和定责方面的经验。

故障的定级标准

上期文章中介绍到，如果我们的注意力仅仅盯着故障本身，就非常容易揪着责任人不放，进而形成一些负面效应，所以我们要将更多的注意力放到故障背后的技术和管理问题上。

但是，这并不是说对故障本身就可以不重视，相反，故障发生后，一定要严肃对待。这里就需要制定相应的标准和规范来指导我们的处理过程。这个过程并不是一定找出谁来承担责任，或者一定要进行处罚，而是期望通过这样的过程，让我们能够从故障中深刻地认识到我们存在的不足，并制定出后续的改进措施。

这里有一个关键角色，我们称之为技术支持，也有的团队叫 NOC（Network Operation Center）。这个角色主要有两个职责：一是跟踪线上故障处理和组织故障复盘，二是制定故障定级定责标准，同时有权对故障做出定级和定责，有点像法院法官的角色，而上面的两个标准就像是法律条款，法官依法办事，做到公平公正。

所以，这里的一个关键就是我们要有明确的故障定级标准。这个标准主要为了判定故障影响程度，且各相关利益方能够基于统一的标准判断和评估。

现实情况中，因为各方受到故障的影响不同，对故障影响的理解也不同，所以复盘过程中，经常会出现下面这两种争执场景。

技术支持判定故障很严重，但是责任方认为没什么大不了的，不应该把故障等级判定到如此之高；

技术支持认为故障影响较小，但是受影响方却认为十分严重，不应该将故障等级判定得这么低。

遇到这种情况，技术支持作为故障判定的法官，就必须拿出严格的判定标准，并说明为什么这么判定。

我们将故障等级设置为 P0~P4 这么 5 个级别，P0 为最高，P4 为最低。对于电商，主要以交易下跌、支付下跌、广告收入资损这些跟钱相关的指标为衡量标准。对于其它业务如用户 IM 等，主要区分业务类型，制定符合业务特点的定级标准。两个示例如下。

交易链路故障定级标准示例：

用户 IM 故障定级标准示例：

故障定级的标准，会由技术支持与各个业务研发团队进行点对点的细节沟通讨论，从业务影响角度把影响面、影响时长这些因素串联起来。这样即使在后续出现争执，也会有对应的标准参考。这个标准可能覆盖不到有些故障影响或特例，但是技术支持可以根据自己的经验进行“自由裁量”。同时，每个季度或半年对标准进行一次修订和完善。这样，我们前面提到的争执就会越来越少，再加上我们内部树立了“技术支持角色拥有绝对话语权和决策权”的制度，执行过程中就会顺畅很多。

对于 P0 故障，通常是由两个级以上的 P1 故障叠加造成的，这说明已经发生了非常严重的全站故障。

不同的故障定级，在故障应对时采取的策略也就不同。一般来说，P2 及以上故障就需要所有相关责任人马上上线处理，并及时恢复业务。对于 P3 或 P4 的问题，要求会适当放宽。整个过程，技术支持会给出一个基本判断，然后会组织召集临时故障应急小组处理。

关于全年全站，或者分业务的可用性和可靠性，这个可以借鉴业界通用的 MTBF（Mean Time Between Failures，平均故障间隔时间）、MTTR（Mean Time To Recovery，平均修复时间）、MTTF（Mean Time To Failure，平均失效前时间）这几个指标来衡量，这里我们就不详细介绍了。

故障的定责标准

上述的故障定级标准，主要是用来判定故障等级，使得故障相关方不至于过分纠结在等级标准上。而故障定责的主要目的是判定责任方。这就需要有明确的故障定责标准，我认为有两个主要目的。

避免扯皮推诿。比如我认为是你的责任，你认为是我的责任，大家争执不清，甚至出现诋毁攻击的情况。

正视问题，严肃对待。不是为了处罚，但是作为责任方或责任团队一定要正视问题，找出自身不足，作为改进的主要责任者，来落地或推进改进措施。

关于第一点，避免扯皮推诿，大概是很多团队都会遇到的非常头疼的问题，也是最令人生厌的问题，所以避免这样的问题，就必须得有相对清晰的定责标准。

比如我们经常会提到的运维背锅的说法，这种情况出现的场景经常是，某个核心功能出现了故障，有大量超时或失败，对应的开发定位一下，说我的代码没有问题，场景也没复现，这个应该是运维负责的主机、网络或者其他基础服务有问题吧，这个责任很轻易地就甩给了运维。类似的上游把责任推脱到下游的情况是经常出现的。

我们自己的实践，是严禁这种情况出现的。也就是作为受影响方，开发负责人有责任端到端地把问题定位清楚，只有当定位出来的问题确实是发生在运维的某个部件时，才允许将责任传递 ，否则不允许出现将自己的问题简单排除，就推断或者感觉应该是其他责任方的问题，然后终止后续排查或者指定下游责任方的情况出现。

当然，在这个过程中，如果需要配合，是可以要求各方投入支持的，因为共同的目标还是要清晰定位问题，找到解决方案。

这时候，就更加需要开放和宽松的氛围，如果大家始终朝着如何摆脱责任或甩锅的目标行事，就会出现非常负面的效应，这一点后面我们会详细分享。

关于定责，我们划分了几个维度，我简单示例如下。

1.变更执行

比如变更方没有及时通知到受影响方，或者事先没有进行充分的评估，出现问题，责任在变更方；如果通知到位，受影响方没有做好准备措施导致出现问题，责任在受影响方；变更操作的实际影响程度大大超出预期，导致受影响方准备不足出现故障，责任在变更方。

2.服务依赖

比如私自调用接口，或者调用方式不符合约定规则，责任在调用方；如果是服务方没有明确示例或说明，导致调用方出现问题，责任在服务方等等。

3.第三方责任

比如机房 IDC 电力故障、服务器故障、运营商网络故障等等，如果确实是不可抗力导致，责任在第三方；但是因自身的冗余或故障预案问题导致故障，责任在应用 Owner。

有了这样的原则，在故障复盘时，就可以有效减少不和谐氛围的出现。因为每个公司的业务形态和特点不一样，里面的具体内容可能也不一样，上述的定责标准可能不完全适用，所以仅供示例参考。如果你在日常深受故障定责的困扰，建议尽快把规则明确起来，并能够与各方达成一致，这样就会最大程度地减少扯皮推诿的情况出现。

总结

今天我们讨论了故障管理中的定级和定责标准。蘑菇街在这方面的具体管理执行中，还是取得了不错的效果，所以分享出来，欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

39 | 故障管理：鼓励做事，而不是处罚错误

故障发生后，我们一定要严肃对待，要对关键责任人或责任方定责，但是定责的目的不是处罚，因为故障复盘一旦以处罚为导向，就会导致非常严重的负面效应。

我们应该如何对待定责和处罚呢？今天就来分享一下我的理解，以及我个人的一些处理方式。

关于定责和处罚

定责的过程，是找出根因，针对不足找出改进措施，落实责任人。定责的目的，是责任到人，并且责任人能够真真切切地认识到自己的不足之处，能够主导改进措施的落地。同时，也让整个团队认识到，我们对于故障的态度一定是严肃严格的。

但是，在具体的执行过程中，我们一定要区分定责和处罚。定责是对事不对人的，但是处罚就变成对人不对事了，因为处罚一定会跟薪资、奖金、绩效、晋升等这些跟个人利益相关的事情直接挂钩。

我的观点是，处罚不能一刀切，更不能上纲上线，一定要慎重。

关于是否处罚，我个人认为可以遵循这样的原则：对于有明确底线，坚决不允许触碰的规则，如果因不遵守规则，故意触犯，导致了严重故障的出现，这种情况是要处罚的。

这样的规则建议通过设定高压线的方式让团队成员牢记心中，就像“酒后不开车”一样，简单明确。我大致列举几条我们的“高压线规则”。

未经发布系统，私自变更线上代码和配置；

未经授权，私自在业务高峰期进行硬件和网络设备变更；

未经严格的方案准备和评审，直接进行线上高危设备操作，如交换机、路由器防火墙等；

未经授权，私自在生产环境进行调测性质的操作；

未经授权，私自变更生产环境数据信息。

通过高压线去加强安全稳定意识，目的是要让每一个人对线上都心存敬畏。从我们的经验来看，绝大多数的严重故障都是因为无意识或意识薄弱导致的，并不是因为单纯的技术能力不足等技术因素。特别是那种自我感觉没问题，就把命令噼里啪啦敲到线上的操作，是最致命的。

2016 年是公司业务高速发展的阶段，设备扩容比较频繁，网络割接操作也很多。因为没有明确严格的规则，导致团队成员为了赶工期，在白天进行网络设备变更，结果就是严重的 P0 和 P1 故障频发。复盘过程中，很多人的反馈就是：我以为是没问题的，我以为是没影响的。其实恰恰就是因为这种“想当然”，导致了严重故障。

后来我们总结，在这些关键的操作上，如果大家意识到位，能够谨小慎微，绝大多数低级失误都是可以避免的，所以针对这些场景，我们就专门制定了高压线。

制定高压线的效果也是很明显的。在近两年的时间里，我们没有出现过任何一例因为意识缺失或低级失误导致的 P0 和 P1 故障。反倒是跟我们有产品技术合作的第三方厂商，有时会出问题，我们了解下来，基本都是白天变更导致的，要么是没有放到凌晨实施，要么就是白天临时变更，没有准备充分。

所以，制定明确的高压线规则，提升意识，碰一次就要疼一次。这个时候的惩罚是为了提升责任人的敬畏意识和主观意识，人为失误才会减少，处罚也才会有效。

当然，更好的结果是，类似的故障越来少，处罚的执行也基本没有了。

鼓励做事，而不是处罚错误

前面我们分享过这句话：

理解一个系统应该如何工作并不能使人成为专家，只能靠调查系统为何不能正常工作才行。（From SRE ，by Brian Redman）

我想很多朋友跟我一样，都会产生共鸣。仔细考虑一下，我们每个人的技术能力提升，甚至是质的提升，基本都是伴随着大大小小故障的发生、处理、复盘和改进，这样一个过程提升起来的。

虽然我们不希望有故障发生，但是真的没有了故障，我们也就没有了真刀真枪实战成长的机会。我们对待故障一定要客观和辩证地理解，特别是对于管理者来说，对于故障，一定要有容忍度，一定要有耐心。

发生故障一方面暴露出我们整体技术架构的不足之处，另一方面，也给我们提供了未来改进的方向。同时，也是最重要的，我们的团队和人员，在这样一次次痛苦的经历后，各方面的能力都得到了锻炼，团队和个人素养也一定会有大幅度提升。所以，对故障有容忍度，有耐心，我们的团队就会变得越来越强，对于故障的应对也会变得更加游刃有余。

反观另一种管理方式，一出故障就劈头盖脸地把团队和责任人骂一通，并且还要严厉处罚的方式，最后的效果就是严重打击士气，适得其反。

所以，作为管理者，当一个故障发生之后，除故障本身外，还要关注更全面的内容，比如关注人、事情背景和前因后果。

列举一下我之前经常遇到的两种情况。

1. 员工积极主动地承担了一些极具挑战性的工作，需要尝试某个新技术或解决方案，而团队、业界和社区可能都没有可供直接借鉴的经验，结果在落地的过程中踩到了一些坑，导致出现了问题。

这种情况在成熟的技术和产品中也极容易出现，比如开源产品，有时候不翻源码都不知道某个地方埋着深坑。即使是商业产品，像 Oracle 在他的官方 bug 库里列着一堆已知 bug，就是明确告知用户使用时要非常小心，真的碰到 bug 了，官方一般也是建议升级版本。根据我的经验，对于这样一个庞大的 bug 库，不出问题一般没人会去把整个 bug list 都看一遍的。

2. 业务高速发展时期，业务量成指数级增长时，团队人员技能和经验水平整体上还没法很好地应对，这个时候可能任何一个小变动都是最后一根稻草。这种时候就需要群策群力，而不是简单处罚了事。

这两种情况都需要全面了解信息之后，再做判断。甚至要优先传递信任，而不是不管三七二十一就直接批评和处罚。何况，如果不出问题，可能很多主管压根都没有关注过员工在做的事情，过程中是否有困难，是否需要支持等等，这本身就是管理者的失责。

在当前这种新业务和新形态不断涌现，又要求快速迭代的背景下，软件开发这种技术工作很大程度上还是要依赖员工的创新和创造。所以在很多情况下，管理者一定要对故障有一定的容忍度，因为员工努力做事的积极性一旦被打击，变得畏首畏尾起来，也就谈不上什么技术进步和突破了，而且想要再恢复起来也会非常困难，最终很大概率上会导致优秀人才流失，为别人做了嫁衣。

所以，团队内部一定要营造出鼓励做事向前冲的氛围，而不是制造担心犯错误被处罚的恐慌氛围。

处罚的“负”作用远超我们的想象

前面讲到，定责不是处罚，是就事论事。员工哪些地方做得不到位，是能力不足还是经验欠缺，这些东西主管可以基于事实，很正式、严肃地表达出来。通常情况下，员工也大多是可以接受的。同时帮助员工进一步分析应该怎么提升，或者聆听员工有什么求助或困难。这种情况下，员工的感受是，主管尊重我，在帮助我。

但是，话题和目的一旦转到处罚相关的事情，员工一般会有两种类型的反应：一种是消沉低落（反正都是我的错，你说咋样就咋样）；另外一种是极力地反抗和质疑（凭什么罚我不罚别人，又不是我一个人的问题等等）。

这时，员工的注意力也会从怎么改进，转变到为什么要处罚我的角度上来。在这种消极和抵抗情绪中再去沟通什么改进措施，就没有任何效果了。作为管理者，也就非常容易陷入到与被沟通者的反复解释中，他质疑一句，你就解释一句，但是他压根就没听进去。

从我们的经验来看，如果定责跟绩效强挂钩，团队就陷入这种恐慌、质疑、挑战以致最终相互不信任的局面。员工害怕、甚至拒绝承担责任，宁可少做不做，也不愿多做多错，团队沟通成本上升，运作效率自然下降。特别是一个故障如果是涉及多方的，扯皮推诿就开始了，都想着把责任撇干净，甚至当众相互指责，这个负面效应杀伤力极大。

后来我们就取消挂钩，对于出现的故障有专门的系统记录，然后把这件事情放到员工一个季度，半年，甚至一年表现中进行整体判断。如果员工整体的表现都是不错的，甚至是突出的，说明员工已经改正或者那件事情确实是偶尔的失误导致，这种情况下员工仍然会有好的绩效。但如果是频繁出问题，这种情况就基于事实反馈，也会更加容易沟通。

我的团队中，就出现过类似的情况。有员工导致了线上严重故障，当个季度绩效较差，但是因为全年表现突出，年终仍然是优秀；也有员工，因为连着两个季度触碰高压线，全年又无明显突出的表现，年终绩效也就不理想。

总结

我们做个小总结，对于故障的态度，我们还是得要辩证地看。对于是否处罚，也要具体问题具体分析。完全不处罚，或者一刀切，一律处罚都是不可取的。作为管理者，还是要将规则和标准定义清楚，在执行时才能够做到公平公正。

另外，管理者除了关注故障本身之外，还要考虑得更加全面一些，要关注到人的感受，关注事情的前因后果，只有这样，在管理执行过程中才会让员工感受到尊重和信任。

最后，你在故障定责和处罚方面有什么经历和想法，欢迎留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

40 | 故障管理：故障应急和故障复盘

上周我们分享了故障管理中，应该如何对待故障，怎样做好故障定级和定责方面的管理工作。今天我就和你分享当故障真正发生后，我们在故障通报和故障复盘方面的实践经验。

故障应急

当故障真实发生后，带来的影响不仅仅是技术层面的，更多的是业务层面的，比如用户和商家的批量投诉，交易量下跌，广告资损等等。而这些影响又会产生巨大的外部压力，并传递到技术团队，这时如果没有很好的故障应对机制，技术团队就很容易陷入慌乱，不知所措。

我们能否有效应对这种突发且高压的状况，我觉得有两个方面十分关键。

第一方面，业务恢复预案。

这也是我们在故障应急状态下一定要坚守的第一原则：优先恢复业务，而不是定位问题。这就需要我们事先有充足的预案准备以及故障模拟演练，这就跟我们前面介绍的各种稳定性保障措施相关，通过稳定性平台的建设，与我们能够预见到的，以及我们经历过的故障场景相结合，当发生故障时能够第一时间执行对应的恢复预案。

同时，预案的执行不能仅仅在故障发生时才执行，而是应该把故障模拟和恢复演练放在平时。我在团队中经常传递的一个理念就是：凡是没有演练过的预案，都是耍流氓。也就是如果我们在日常系统稳定的状态下都不敢执行预案，或者执行了没效果，那真到了故障发生后，在更为复杂的状况下，预案 100% 也是不敢做的，因为这种异常状态下，我们还要考虑执行了预案是否会导致次生故障。

关于故障模拟，可以分为不同层面来梳理，比如：

IDC 层面，如电力切换、UPS 切换、核心网络设备切换，单设备故障等，这些故障是可以通过人为破坏进行模拟的，模拟手段相对简单，但是破坏力和影响面会很大，所以做之前一定要准备充分。我们会定期 1~2 个月做一次类似的模拟演练，涉及机房配合的，也会提前跟运营商约定好时间；

系统层面，如 CPU、磁盘 IO、网络 IO、网络时延、丢包等异常场景，这些都有开源或 Linux 系统自带的工具支持，比如 Stress 工具模拟 CPU 升高，dd 模拟磁盘 IO，tc 模拟网络问题；

应用层面，最典型的就是 RT 升高，抛出异常，返回错误码等等，这里还是会用 Spring 的注解功能，在运行时模拟异常状况，然后有针对性地看各种限流降级和开关预案策略能否生效。

关于故障模拟，我再次向你推荐 Netflix 的 Chaos Engineering，介绍得非常全面。

第二方面，有效的组织协调。

故障发生后的排障和恢复操作，往往需要多个技术团队协作完成，这时就需要有一定的应急机制，来确保相关人员能够快速响应和高效协作。同时，因为对业务造成的影响导致业务团队会承受很多外部压力，这时也需要有统一的口径对外反馈，比如大致原因（对外不用详细），影响面以及预估恢复时长等等，从而确保信息的透明，避免各种不着边际的猜测对公司信誉造成的影响。

这时，我们前面介绍到的技术支持这个角色就起到了非常关键的作用。对内，要有效组织技术团队的集中和协作；对外，负责对接业务部门同步信息，同时屏蔽各方对技术团队和故障处理人员的干扰。

出现一个严重故障后，技术支持通常要做如下几个关键事项。

确定故障影响面及等级。故障会通过监控、告警、业务反馈或用户商家投诉几个渠道反馈过来，这时技术支持会根据故障定级标准，快速做出初步判断，确认影响面，以及故障等级。

组织应急小组。对于无法马上恢复或仍需要定位排查的故障，会直接将相关技术团队的主管和骨干开发人员召集到一起，通常是专用的会议室，并确认故障处理主要指挥者，通常是受影响业务的技术负责人，比如商品出现故障就由商品的技术团队主管指挥排障，交易出现故障就由交易技术团队主管指挥，如果是全站性的故障通常会由技术总监直接介入负责指挥。

信息通报。完成上述第一步后，通常会给相关技术和业务团队通报故障初步信息，包括登记、影响面、故障简述以及主要处理团队和责任人。完成第二步，组织起应急小组之后，每隔一定时间，如 15~30 分钟要对进展做一次信息同步。同时，如果等级和故障信息有变，也要同步出来，直至故障排除，业务恢复。为了保证沟通的顺畅，技术支持并不与处理故障的人员直接沟通，而是通过指挥者沟通，这样确保高效沟通，同时也确保处理故障的人员能够相对地专注在故障处理上，而不是响应来自各方的询问，甚至是质问。

所以，整体总结下来，故障应急过程就是：功夫要下在平时，注意建设各种工具和平台，同时要尽可能地考虑和模拟各种故障场景。这就像一支军队在平时一定要做各种军事演习一样，然后就是临场发挥。当故障真正出现时，要有完善的应急机制，马上能够有效运转起来，而不是慌乱无措。

故障复盘

上面介绍了故障应急，那接下来我们再看故障管理的下一个阶段，也就是故障发生之后的复盘。

首先，我们一定要先搞清楚复盘的目的。复盘的目的是为了从故障中学习，找到我们技术和管理上的不足，然后不断改进。虽然我们不愿意故障发生，但是从故障中学习，反而是提升团队和员工能力的最佳手段，所以我们一定要辩证地看待故障这件事情。

同时，切忌将复盘过程和目的搞成追究责任或实施惩罚，这对于团队氛围和员工积极性的打击是非常大的。这一点在前面的内容中已经详细介绍过，这里就不再重复了。

在复盘过程中，技术支持仍然要起到关键作用。

召集复盘会议。会提前将故障信息发给故障处理的参与方，准备复盘过程中需要讨论的问题，视情况决定是否邀请业务方人员参会；

组织会议流程。协调和控制会议中的讨论，也就是俗称的控场；

对故障定级定责。起到类似“法官”的判决作用，根据前面讲到的标准执行；

明确后续改进行动及责任人，录入系统并定期跟踪。

复盘会议中，通常会有哪些关键环节呢？

第一，故障简单回顾。主要针对故障发生时间点，故障影响面，恢复时长，主要处理人或团队做简要说明。

第二，故障处理时间线回顾。技术支持在故障处理过程中会简要记录处理过程，比如每个操作的时间点，责任人，操作结果，甚至是中间的沟通和协作过程，比如几点几分给谁打了电话，多长时间上线的等等，这个过程要求客观真实即可。业务恢复后，会发给处理人进行核对和补充。这个时间线的作用非常关键，它可以相对真实地再现整个故障处理过程。

第三，针对时间线进行讨论。回顾完上述时间线之后，我们会提出过程中存在的疑问，这一点会对主要处理人产生一定的压力，所以一定要保持对事不对人。通常我们会针对处理时长过长、不合理的环节提出质疑，比如为什么告警没有发现问题，而是用户投诉反馈的？为什么从发生故障，到有人上线响应拖了很长时间？为什么对应的场景没有限流、降级和开关等预案？为什么预案执行了没有生效？为什么没有做灰度发布和验证等等？通过这些问题和细节的讨论，我们会找出明显的不足，记录下过程中的改进点。

第四，确定故障根因。通过讨论细节，我们对故障根因进行判断，并再次对故障根因的改进措施进行讨论。在这个环节和上个环节中，通常会有很多讨论甚至是争论，技术支持要发挥的作用就是控制好场面，就事论事，一定不要让讨论失控，演变成相互指责和批斗会，一旦有这种苗头，技术支持一定要及时干预并给出警告。

第五，故障定级定责。根因确定后，结合前面已经确认的故障影响面，就可以对故障定级定责了，这里还要依赖前面我们介绍到的故障标准。不过，定责时，我们会让责任方团队和相关处理人员在场，小范围告知，这样做主要是考虑责任人的个人感受。如果无异议，就形成故障完结报告；如果有异议，则可以向上级主管反馈，直至技术团队负责人（CTO 或技术 VP）为止。

第六，发出故障完结报告。故障完结报告的主要内容包括故障详细信息，如时间点、影响面、时间线、根因、责任团队（这里不暴露责任人）、后续改进措施，以及通过本次故障总结出来的共性问题和建议。这样做的主要目的是保证信息透明，同时引以为戒，期望其它团队也能够查漏补缺，不要犯同样的错误。

定期总结故障案例

除了例行的故障应急和故障复盘，我们还会定期对一个时期内的故障案例进行总结。比如按照一个季度、半年和全年的周期，这样可以更容易地发现一些共性问题，以便于研发团队在稳定性建设方面的规划。

举个例子，2017 年年底，我们整体总结了全年的故障案例，对 P0~P2 严重级别的故障进行分类汇总，就发现全年第三方原因的故障，以及数据类的故障占了很大比例。

我们再往细节分析，发现第三方原因的故障，多数是机房 IDC 的电力、网络切换，单台服务器硬件故障导致的。这些在单次故障复盘时，很容易归因于第三方，但是从全年来看，我们认为根因上，还是我们的系统健壮性不够，在限流降级以及日常的故障模拟演练上，还有很大的提升空间。所以，我们就拉上研发团队的主管和骨干员工，重新看这些故障，重新制定出稳定性提升的改进措施。

同时，在故障定级定责方面，由第三方原因导致的故障，后续不再作为故障根因，而只作为触发因素。所以，在故障复盘时一定要制定出我们自身需要改进的措施。

针对数据类故障，我们总结后发现大多集中在“有状态业务”发布过程中。代码和配置发布可以走发布系统，有完善的流程支持，但数据的变更却更多地依赖人工操作，且流程和周边部件的配合上也不成熟。所以，我们就明确下来，要加大对有状态业务的发布和数据变更工具的支持，将经验固化下来，而不是靠人。

总结

上述这些经验，同时又可以推广到整个研发团队，在不断总结的过程中，整个系统的稳定性不断提升，技术架构也不断完善。

到这里，我们整个故障管理的内容就介绍完了。

总结一下，我们首先要对故障有一个正确和理性的认识，既不能放任不管，也不要谈之色变；同时我们也需要科学的管理方式，跟业务结合，制定出对应的故障等级和定级定责制度。

其次，结合我们前面介绍的稳定性保障体系，在日常要做好各类预案和模拟演练，当故障真实发生时，能够做到冷静处理和高效地组织协调。

最后，在故障复盘中总结出我们的不足，然后不断地改进。

关于故障管理的内容，你还有哪些问题想和我交流，欢迎你留言讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

41 | 唇亡齿寒，运维与安全

故障管理模块告一段落了，今天我们来分享运维安全的内容。在日常工作中，我们运维团队和安全团队的配合确实是非常紧密的，有非常多的交集，我觉得可以做个整体的分享，算是抛砖引玉，以激发更多的讨论和思考。

运维和安全的关系

运维和安全，双方有一个共同的特点，就是时常要面对非常棘手，甚至是影响公司口碑声誉的问题。对于安全来说，这一点尤甚，想一想用户信息泄露会造成什么样的后果就不难理解了。

所以，运维和安全的合作，最初都是在这种场景下触发的，也就让两个团队显得更像是难兄难弟。

另外一层关系，就像我们今天分享的题目，运维和安全的关系，就是唇亡齿寒的关系。因为安全是整个业务和技术体系的一道防线，当这道防线被突破，最直接的影响和损失就体现在主机、系统和数据上，而这些又正好是运维的范畴。说得直白一点，就是一旦发生了安全事故，造成的影响，以及后续的修复，这些工作都将由运维来承担。

所以，在双方工作的协作上，我一直认为运维不能只是被动响应，而应该主动与安全合作，共建安全体系，与运维体系融合，把防线建设好，从源头控制。

同时，安全问题和需求一般都会放置在较高优先级上来响应，并通过固定的问题响应机制实行联动，从而实现最高效的配合响应。

蘑菇街安全体系简介

这里首先介绍一下我们的安全体系，限于篇幅，我只对部分关键系统和平台做一个简要概述，同时会介绍一下每个系统与运维系统之间的关系。

1. 入网管控

这是 VPN 接入的管控，并与员工的统一登录鉴权结合，做到一键登录。因为 VPN 接入后，就等于进入了线上的网络环境中，可以访问到很多敏感系统和数据，这里的入网管控就相当于整个环境的第一道防线。

2. 堡垒机

当接入 VPN 之后，对于技术同学就会有进一步的需求，比如访问线下和线上环境，登录主机和网络设备做维护工作，这时我们就需要有另外一道关卡，就是硬件或虚拟设备的登录管控，这个就由堡垒机来实现。这里堡垒机维护的主机列表、主机用户名、权限配置等信息，就需要与运维系统中的 CMDB 以及运维标准化的内容保持统一。

因为堡垒机基本属于每个公司安全建设的第一个产品，所以属于强需求，业界也随之出现了很多优秀的开源及商业产品，你可以自行了解一下。同时，关于这块内容，我们的安全工程师齐剑涛在 17 年 CUNTCon 全球运维技术大会上做过分享，如果有兴趣可以进一步了解。

固守服务器的第一道防线——美联集团堡垒机的前世今生

3. 主机安全管控

在每台主机上运行一个安全 Agent，实时地对可疑进程、可疑端口、可疑账号、可疑日志以及各类操作进行监控，一旦发现异常就会及时告警，确保能够第一时间发现异常，这种就可以一定程度上对黑客入侵导致的破坏进行控制。

4. 黑盒扫描

这个系统主要针对主机上对外开放的端口和使用的服务进行扫描。比如我们之前遇到的 Redis 高危端口漏洞，OpenSSL 心脏滴血漏洞等，同时从接入层会过滤出高频的 url，通过注入或修改消息来模拟恶意攻击，量虽不会大，但是如果存在异常或高危漏洞就可以及时发现，同时这个扫描是不间断的。

5. 白盒扫描（代码审计）

这个系统我们在前面的持续交付流水线中介绍过，会针对代码中明显的漏洞进行审计，比如 XSS 漏洞，SQL 注入等问题，如果在代码中存在类似问题是不允许发布上线的。

这个项目已经开源，地址：https://github.com/WhaleShark-Team/cobra

这样，黑盒和白盒扫描搭配起来，就可以对内外部的服务和系统进程进行全方位的保障了。

6.WAF，Web Application Firewall

WAF 用来对外部的 Web 服务进行保护。我们知道，对于业务系统来说，通常会有很多不正规的渠道来网站爬取各种信息，更有甚者会通过模拟用户行为来注册大量虚假账号，以此来领取各种优惠，或者提交大量虚假订单、评论等等，同时还会对服务器负载造成很大压力。对于这种恶意行为，就需要由 WAF 来保护，通过一定的业务规则配置和识别来阻止恶意访问。

7. 应急响应中心 SRC

在安全界，有这样一个不成文的说法，叫作三分靠技术，七分靠人脉，也就是安全的信息情报有时比单纯的技术攻防要重要得多。对于企业来说，除了要能够招聘到一些安全圈内的专业人士，另一方面，也要有对外公开的应急响应中心 SRC，以此来聚集一些比较友好和善意的白帽子，通过他们主动发现一些网站和系统的漏洞，并能够通过 SRC 提交给公司安全部门。同时，作为企业也会有一些不同形式的奖励，比如奖金和纪念品这样的物质奖励，或者漏洞提交排名这样名誉上的认可，以此来形成更长久和深入的合作。

同时，SRC 也能弥补一些我们主动做的，但是防护措施不到位的情况，最大程度地借助社区和圈子的力量，共同保障企业网站、信息和数据的安全。

上述我们提到的很多检测和限制规则，都会通过规则平台沉淀下来，这个就类似于我们的之前讲到的配置管理。

最后，以一张图作为总结，来整体呈现我们的安全体系。也欢迎你给我留言继续讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

￼

25 | 为什么蘑菇街会选择上云？是被动选择还是主动出击？

2018 年 1 月 22 日凌晨，我们美丽联合集团旗下的蘑菇街和美丽说的业务，整体搬迁到腾讯云，完成了从托管 IDC 模式，到腾讯云上混合云模式的转变。

云计算发展到今天，无论是在技术、服务层面，还是在商业层面都已经相对比较成熟。当前绝大多数初创公司在基础设施上的策略一定是公有云，已经极少再有自建或托管 IDC 的情况，所以不会存在是否上云这样的纠结。

但是对于蘑菇街这样体量的公司，搬迁上云，就必须要考虑得更全面：考虑基础设施的变化，业务的平稳过度，运维模式的转变，成本管控的调整，以及众多的细节问题。

最近，有很多同行对我们为什么做这个选择比较感兴趣。因为尽管混合云模式是当下的大趋势，但真正面临抉择时，又总会被各种具体的细节问题所困扰，犹豫不决。

今天，我从蘑菇街的视角，结合真实情况，聊一聊我们为什么会做出上云这个选择。

我们所面临的问题

1. 成本闲置问题

对于电商，大促已经常态化，除了“双 11”“双 12”以及“6·18”这样的例行大促，每个电商还会有自己的营销活动，比如我们就会有“3·21”春季促销，以及每个月不同的主题促销。这一点对于其它电商也是如此。

大促，从技术层面就意味着要在短时间内应对远远超过日常的峰值流量，可能是平时的十几倍，甚至是上百倍。为了支撑这么大的流量，就需要业务系统有足够的容量支持。

虽然我们会从技术和架构层面来提升容量，但是，无论如何优化，充足的硬件资源扩容是前提条件。

之前，我们在应对“双 11”这样的大促时，只能采购更多的设备。与此同时，我们还要在机柜成本以及资源上下架等纯人工方面进行投入，这往往要花费几千万元的成本。

但是，每次大促峰值一过，这些设备基本就处于极低的负载状态。这批资源要经过将近一年时间，随着业务量快速增长才能逐步消化掉，然后再进入到下一轮大促的采购周期中。

所以，这部分成本投入的收益是非常低的，基本处于闲置状态。

2. 基础设施维护问题

选择租用或托管 IDC 模式，随着业务量增长也会遇到一系列的问题。在我以往的实践操作中，我也遇到了以下几个问题，相信你也有过相似的困扰。

IDC 机房的选址。在中国互联网八大节点所在城市的 IDC 资源无疑是最优的，但是这些地方的优质资源却也是最紧张的。通常会被国内各大互联网公司或云计算公司提前占据，所以很难找到相对独立且成规模的机柜区域，而零散的机柜分布对管理和维护工作来说十分不便。

退而求其次，就只能选择二级或三级节点，但是这样一来在网络质量上就降了一个或多个等级。同时，因为没有 BGP 线路，或者线路质量不高，就需要多线接入，这对业务体验以及管理维护都会带来很大影响。

IDC 机房的扩展问题。一个机房内的机柜消耗完，想扩展就只能另找机房，但是属于同一运营商，或同一 ISP 服务商的同城机房资源是否充足，又是一个未知数。

不同机房间是否互联互通，以及是否增加跨地域的时延，对业务访问体验的影响很大。所以扩展性不足，会大大影响业务体验，甚至影响业务发展。

如果是通过第三方 ISP 接入的，特别是存在多个 ISP 服务商的时候，在互联互通时，服务商之间的沟通协调非常耗费精力，且不同机房以及多 ISP 之间的专线成本也会增加。当基础设施达到一定体量，这个问题会非常突出。

如果你也有过这方面的经历，相信你一定深有体会。

资源利用率问题。即使我们做了虚拟化，按照业界实际情况，CPU 资源使用率一般也就在 10%-15% 左右。所以要想大幅提升使用率，就是要在离线的混部，也就是类似大数据消耗资源特别高的计算类业务上进行资源调配：比如，在凌晨调度到相对空闲的应用服务器上；而在白天，则将资源释放出来给业务应用。

但是，想要在离线混部技术上做文章，说起来容易做起来难，因为这在实际工作中是需要非常深厚的技术积累和非常高的技术门槛的。

业务层面的调度是一方面，另一方面，底层硬件、网络以及操作系统这些也需要相应的技术支持。这其中具体的复杂情况，你可以通过阿里最近在这方面的一些分享体会一下。

单考虑操作系统之上的应用和业务技术是无法满足要求的，所以，这就需要我们在进行技术规划时，在开始底层建设之前就要考虑全面。

我们知道，国内外超大型的互联网公司，以及各大云计算公司，在硬件选型上都有自己的定制化要求。其中一个重要原因，就是为了尽量保持几万甚至十几万硬件设备的系统架构一致，从底层硬件开始就为后续的超大规模运维做技术准备。

当然，这样的定制化需求，只有在需求量足够大的情况下才会被硬件厂商接受，一般如果只有百台或千台的规模，硬件厂商基本是不会考虑的。

所以这就会牵扯出下面这个问题。

3. 底层技术投入和人才的问题

通常在互联网领域，越是底层的技术，技术门槛就越高、越复杂，也越离不开高端人才的投入。比如硬件资源虚拟化，就需要有懂内核、懂网络、懂 OpenStack、懂分布式存储如 Ceph 等等的专业人才。

但是真正精通的人却不多，加上要搞定整套解决方案，还需要一个完整的团队，这就难上加难，在团队组建上面临更大的困难。

人才紧缺，就意味着人力成本会很高，这个就是技术投入的隐性成本。而且因为技术门槛高，一旦发生人员流动，那么，对于原有技术平台来说，无人能把控的风险就会更高。这一点往往会是最大的隐性管理成本所在。

当然，在人才招揽上，我们可以加大人力成本投入，招聘最优秀的人才。但是作为像蘑菇街和美丽说这样以更加聚焦于业务，以业务发展为生命线的公司，我们更期望能够在业务上取得创新和发展，而不是在技术上取得多么非凡的成就（这一点与公司的发展诉求是不一致的）。所以这就从根本上决定了，我们不会无限度地投入，或投入非常大的成本在这些基础技术的研究上。

对于以技术创业为主的公司，其考量的出发点就完全不同了，这里我们不展开讨论。

进一步讲，论体量和规模，我们自有的底层技术无论如何是无法与专业的云计算公司相比的，这就带来另一个问题：如何为这些优秀人才提供成长和发展？因为既然在体量和规模上比不过，那我们能够提供的个人成长空间和机会，一定也比不过专业云计算公司。这种情况下，大部分人才的去向选择就显而易见了。

对于大数据，分布式中间件等岗位，也会存在类似的情况，因为它们大多需要体量和规模才能体现技术挑战性和成长空间。

4. 小结

到这里我们做个小结，随着基础设施体量越来越大，我们在基础设施和平台服务层面，将会投入越来越大的财力、人力和最宝贵的精力。

但是这项投入的收益和成效却不明显，且在这个层面的专业性上，我们与云计算平台之间的差距越来越大，脱节也越来越严重。

我们的决策过程就是，以未来 3-5 年，甚至更长远的视角考量，我们认为上述这些问题一定会成为我们将来业务发展的障碍，因此上云就成了我们的不二选择，并成为公司的战略决策之一。

纵观技术发展趋势

1. 从软件架构发展的趋势上看，从最早期的物理机，到目前主流的虚拟机，再到当前非常火热的 Docker，以及可能在未来会成为又一主流的 Serverless，我们对于资源层面的依赖越来越少，而这个趋势恰恰是云计算不断发展带来的改变。

同时，像 Serverless 这样的技术理念，就是在公有云平台上，为了提升资源利用率，而衍生出来的。而且从目前看，Serverless 也只有在公有云平台上才有意义。在私有云，或者是自建或托管 IDC 中，因为资源规模问题，没有看到太多的实践价值。

2017 年 AWS re:Invent 2017 峰会上，AWS 共发布了在数据库、容器、人工智能、物联网以及网络等等方面的几十项新的产品技术服务。可以说，如果想要技术为业务带来更多的可能性，拥抱云计算是最好的选择。

2. 人工智能对云计算能力的释放。我们当前的人工智能主要是对机器学习算法的广泛应用，这里的两个前提条件，一个是要有足够大的数据量，另一个就是要有足够充足的计算资源。

我们先看一个 2017 年的新闻：

2017 年 5 月份，谷歌宣布麻省理工学院的数学教授安德鲁·V·萨瑟兰使用抢占式虚拟机实例，在 220000 个 GCE 核心上运行了庞大的数学工作负载。据称这是迄今为止在公共云上运行的最庞大的高性能计算集群。

计算任务阶段性的运行对资源需求是非常庞大的，一般企业很难提前预留足够的资源来做这个事情，这时云的资源优势和弹性能力就凸显出来了。

可以说，未来人工智能的发展和应用，必然会依托于云计算。

没有银弹

软件工程中，我们一直在讲，没有银弹。前面我们介绍了我们遇到的一些具体问题，以及云计算的优势所在，但是没有银弹这条规律，仍然也适用于云计算行业。

那么，是不是有了云计算，有了公有云，上述我们所说的问题就都不存在了呢？

以公有云为例，它也一样会遇到 IDC 建设、扩展性以及基础技术投入等等问题，可能也会给我们带来一定的影响。但是对于公有云来说，因为自身财力和人力的优势，面对这样的问题会更容易解决一些，但对于我们可能就是难以逾越的难题了。

同时，公有云虽然解决了很多问题，但是，就目前这个阶段来讲，如果想要获得较高的客户满意度，仍然有很长的路要走，比如不同形态业务的差异化支持和服务问题。

我想，这一点并不是云计算厂商不想做好，因为无论在技术、产品以及服务上，它们并不是一蹴而就的，而是各方面都需要一个逐步积累、磨合和摸索的过程，这就需要云计算厂商与业务客户共同努力，朝着同一个目标前进，需要彼此多一些耐心。

我们也期望在国内见到 AWS 和 Netflix 这样的最佳组合，相互成就，共同成功。

欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

26 | 为什么混合云是未来云计算的主流形态？

爆竹声声辞旧岁，今天是大年初一，在此，祝你新春吉祥，阖家幸福！

上期文章我介绍了我们蘑菇街之所以选择上云，是基于怎样的全面考量。今天我们来聊一聊，对于蘑菇街这样有着一定规模体量的产品，我们在不同时期和不同阶段，对云的使用方式是怎样的。

关于混合云

对于“混合云”这三个字，你应该不会陌生。但是，“混合云”又是比较宽泛一个概念，随着技术趋势的发展，这个概念的内涵和外延也在不断发生着变化。

从字面上理解，“混合云”即私有云和公有云的混合搭配，这也是最开始对混合云最简单直接的解释。

但是随着公有云服务越来越丰富，我们对公有云的应用也不再仅仅限于资源层面，而更多地体现在云服务层面。所以，不同时期、不同角色、不同团队、不同行业对于混合云的使用和理解可能都会不同。

为了方便理解，我们以 CDN 为例。

我们使用的 CDN 服务，其实是云服务最早被应用的典型形态。但是，在早期，更多的是专业 CDN 厂商提供这类服务，而不是腾讯云和阿里云这样的公有云巨头来提供，同时它跟我们实际接触到的机器资源又有很大的不同。

所以在很长一段时间内，我们并没有意识到这就是云服务。但是，这种使用模式，从云的特性来讲，就是混合云模式，但是不同时期，不同背景的人对它的理解可能就完全不一样。

关于 CDN 这一块，在后续专栏中，我将会单独撰写文章进行详细介绍。

我们对混合云概念的熟知，更多的还是在公有云服务兴起之后。因为其提供了更加灵活、便捷的资源弹性能力，满足了行业内普遍的弹性需求，被应用到大量的弹性应用场景中，与业务自身所在的 IDC 机房形成一个整体，就有了混合云模式。

对于当前新兴的创业公司，除部分因政策监管因素无法上云的业务外，基本都会将业务完整地放到公有云上运行。

但是对于类似蘑菇街这样的产品，因为在公有云蓬勃发展之前就已经建设了自有的技术体系和架构，所以在选择上云的过程中，就需要有个过渡过程，这个过程就是混合云需求存在的应用场景。

下面我就分享一下，蘑菇街上云过程中的几项基础设施，在过渡阶段以及后续建设上的思路。

我们所经历的几个基础设施建设阶段

第一个阶段，完全托管 IDC 模式。我们选择与电信运营商或者第三方 ISP 合作，租赁其 IDC 机房中的机柜。而其他主机硬件和网络设备都是我们自行采购，然后放入机房中进行托管。

这种模式我在上篇文章中也介绍过，会随着业务规模体量不断增加而出现一系列问题。

第二个阶段，资源短期租赁模式。上期文章中我曾介绍过，因为电商大促的例行化，以及峰值流量的激增，导致我们短时资源需求量庞大。如果再靠一次性采购模式，付出的成本巨大，且后期成本闲置，造成严重的浪费。

我们曾跟运营商或第三方 ISP 谈过一些短期租赁合作，因为运营商或 ISP 服务商在机柜资源上相对充裕，通常在它们完全租赁出去之前，也会存在闲置情况。所以如果我们能够向它们短期租赁机柜，这对我们双方都是有益的。

但是，只有机柜没有资源也是没有意义的。所以在资源上，运营商和 ISP 会利用其广泛的合作渠道优势，帮助我们与其自身，或与第三方达成资源上的短期租赁合作。

这种合作模式，在前两年确实帮我们在资源紧张和成本优化方面，解决了很大的难题。

虽然机柜和硬件资源在形态上还不能称之为云，方式上也不够灵活，但是这种模式起到的作用，很大程度上满足了我们对弹性的需求，所以我们内部戏称这种模式为“人肉云”，或者叫“人工云”。

这种模式令我深有感触，顿时豁然开朗：

解决问题，有时跳出纯技术思维模式，尝试通过外部合作和沟通的模式，一样可以有很好的解决方案，甚至可以解决在技术层面解决不了的问题。

第三个阶段，同城混合云模式。近些年运营商和 ISP 服务商也在做自己的公有云体系，所以随着他们服务的不断完善，后来为了能够提升交付效率，我们也会尝试使用他们的公有云业务。

这里我这所以提到同城混合云模式，主要原因是，作为运营商和 ISP 服务商，他们的云资源可以与我们在同一机房或同城机房。这种模式最大的优势就是可以与我们的 IDC 网络专线拉通，大大降低网络时延，网络质量相对稳定，同时成本也相对较低。

如果是跨城甚至是跨省，就会频繁发生网络抖动、丢包这些问题。对于时延敏感的服务，是完全满足不了要求的，且微服务间频繁调用产生的大流量带宽需求，成本也是非常巨大的。

所以，这种情况下，虽然公有云的各项产品和服务相对完善，但是如果在对应的城市没有公有云节点，或者距离较远，又或者专线质量不高，就基本没法满足我们规模化使用的场景。

但也不是全部无法满足。后面一篇文章我会介绍通过公有云建设 CDN 和二级 CDN 体系的内容，虽然没有专线，但仍然可以满足部分业务场景。

通过上面的内容，你可以看到，同城运营商和 ISP 服务商在公有云服务方面优势巨大，且这种优势主要体现在地域和网络资源质量上。

我想，运营商的公有云业务在近期有不错的发展，这也是很重要的原因之一。

第四个阶段，公有云体系内混合云模式。上篇文章我介绍到，从长远的角度考虑，为了能够更加全面和深入地利用好云计算的产品技术，我们整体搬迁到了腾讯云。

这个阶段初期，我们使用的还是完全独立的物理机资源。这种资源使用模式与之前托管 IDC 模式相比，除硬件和网络外，操作系统和各项技术栈还完全是由我们自己运维。

之所以这样做，还是为了保证迁移过程的平稳。因为我们自身的技术体系和架构已经非常庞大，也有较高的复杂度。

要想在另外一套基础设施上将这套精密的体系部署、调测、运行起来，同时还要保证各项性能指标以及系统容量不出问题，项目难度就已经非常高了。而这样做可以很好地防止软件架构发生变化，避免各种复杂因素交织在一起所导致的业务稳定性的不可控。

之前我看到有很多人批评，甚至是贬低这种公有云提供独立物理机资源的模式，认为这是换汤不换药，或者认为这是技术含量太低、技术水平不足的表现。但是我认为这种理解还是太片面。

单纯从技术角度来讲，这种模式或许没有体现出公有云的特性，但是从实际业务场景和实际客户需求来讲却是必要的。而且对于类似蘑菇街这样有着大规模业务体量和复杂技术架构的产品来说，它还满足了用户的过度需求。

所以，我认为腾讯云在这一方面还是体现出了“客户第一”的意识的。

当然，搬迁到腾讯云之后，下一个阶段，我们必然会利用更多的云资源和云服务。比如无状态的 Web 服务或者微服务应用，在大促时完全可以利用云的弹性优势进行快速的资源扩缩容。

但是对于数据库或大数据这样的存储类业务，因为它们本身又是支持业务运行的核心基础设施，所以短期内我们仍然还是采用独占物理机的模式。我们主要基于下面两方面进行考量。

1. 技术架构匹配问题。以数据库为例，我们自研了分布式数据库中间件和大量的工具，比如对分库分表的支持和数据迁移转换等等。还针对具体的业务场景和特性在数据库和操作系统层面做了大量的优化工作，包括但不限于各类参数的调优，以及部分特性的定制。

再者，云上资源也无法规模化地满足我们对硬件的特定需求，所以我们在这种模式下，就很难一下子将云服务利用起来，而其它的分布式组件也会存在类似问题。

归根结底，这还是云上的技术体系和原有的业务技术体系不匹配的矛盾所导致的，需要二者花更多的时间来磨合。同时，这也决定了在未来很长一段时间内，混合云模式才是最佳实践模式。

2. 数据安全问题。我认为一些有政策要求或政策限制的业务，需要慎重考虑这个问题。

比如金融行业，或者某些 ToB 的业务，由于各种竞争或敏感问题，客户本身就不允许你的服务在云上，那么在数据安全问题上需要更全面地考虑，这种情况下如果采用混合云模式就会受到很大限制。

但是，如果没有上面这些问题的困扰，我认为上云是最好的选择。上云前后需要建立起彼此相互之间的信任，同时也可以共同签署信息安全约定，在法律层面进行约束。

退一万步讲，即使不上云，我们的数据在自己的机房里就一定 100% 安全吗？我想这才是需要我们真正考虑的问题。

总结

上面我以蘑菇街为例，分析了我们为什么会认为混合云会是未来一段时间内的主流形态，并推测了可能还会出现的其他混合模式，比如多云平台的混合、多云平台服务的混合等等。

不管如何选择和使用，我们一定还是要以满足业务场景为出发点，脱离了这一点，单纯追求技术深度和复杂度是没有意义的。

在公有云或混合云应用过程中，你曾遇到过什么问题，或者有什么好的建议，欢迎你留言与我讨论。

感谢我们彼此的坚持与陪伴，新年新征程，在新的一年里，期待与你共同进步，我们下期见！

27 | Spring Cloud：面向应用层的云架构解决方案

上期文章我们介绍了混合云，以及在实际操作中我们常见的几种混合云模式。今天我们来聊一聊 Spring Cloud 如何解决应用层的云架构问题。

对于 Spring Cloud，你大概不会陌生，它跟 Spring 生态中的另一个开源项目 Spring Boot，基本上已经成为国内绝大多数公司向微服务架构转型时的首选开发框架。

Spring Boot 可以支持快速开发单个微服务应用，Spring Cloud 则提供一系列的服务治理框架，比如服务注册、服务发现、动态路由、负载均衡以及熔断等等能力，可以将一个个独立的微服务作为一个整体，进行很好的管理和维护。

从业界实际使用情况和反馈来看，由于两者完美的搭配，Spring Cloud 和 Spring Boot 确实是可以通过相对较低的技术成本，让开发人员方便快速地搭建起一套分布式应用系统，从而进行高效的业务开发。

同时，优秀的服务治理能力，也为其后续在稳定性保障工作方面打下了不错的基础。

（注：因为 Spring Cloud 必须基于 Spring Boot 框架才能发挥它的治理能力，所以下面我们提到的 Spring Cloud 是默认包含了 Spring Boot 框架的。）

所以，通常我们更多地是把 Spring Cloud 作为微服务应用层面的开发框架，帮助我们提升开发效率。看起来，它貌似跟“云”这个概念没有什么直接关系。

而实际上，在将应用与云平台连接方面，Spring Cloud 也发挥着非常核心的作用。这也是为什么本期文章的标题没有直接定义为微服务治理架构，而是面向应用层的云架构。

下面我们具体来看看。

Spring Cloud 框架中云的影子

目前整个 Spring 生态是由 Pivotal 这家商业公司在主导，但是 Pivotal 更大的目标是要为客户提供云上的端到端的解决方案。

所以 Pivotal 最早提出了 Cloud-Native（云原生）的概念，或者说是一种理念，目的是帮企业提供云上业务端到端的技术解决方案，全面提升软件交付效率，降低运维成本。简单来说，就是除了业务解决方案和代码，其它事情都可以交给平台处理。

基于这样的理念，Pivotal 打造了自己的云原生解决方案 PCF（Pivotal Cloud Foundry），包括多云和跨云平台的管理、监控、发布，以及基础的 DB、缓存和消息队列等等，一应俱全。

我们可以看到，在 PCF 整体解决方案中，Spring 生态是向用户的业务应用层架构拓展的非常重要的一环，帮助其进行高效的业务开发，并提供后续的稳定性保障。 ￼

所以，这个时候，Spring Cloud 除了提供微服务治理能力之外，还成为了微服务应用与云平台上各项基础设施和基础服务之间的纽带，并在其中起到了承上启下的关键作用。

至此，我们可以得出这样一个判断，也是本篇文章想传递的一个信息：Spring Cloud 不仅仅是微服务治理解决方案，它同时还是面向应用层的云架构解决方案。

虽然 Pivotal 最早提出了云原生的理念，也提供了 PCF 这样的云原生整体商业解决方案，但是从目前业界的实际应用情况来看，Spring Cloud 这个局部解决方案的应用更为广泛。

而且从图中我们看到，其与 AWS 的深度整合，也正反映出当前 Spring Cloud 在整个业界的影响力和被应用的广泛程度。

插句题外话。早期阿里开源的 Dubbo，其实是跟 Spring Cloud 类似的微服务框架，并且经过阿里大规模的应用实践，可以说是非常优秀的开源项目。早些年国内在选择微服务框架时，Dubbo 基本是首选，但是近年来因为开源维护不力，很早停止了版本更新，导致大量的用户流失，促使用户纷纷涌入 Spring Cloud 阵营。

而 Spring Cloud 经过近几年的发展，深入了解用户需求和痛点，不断完善改进，早已蜕变成我们所说的应用层的云架构，紧跟整个云计算发展趋势的大潮。

最近 Dubbo 重启开源维护，与阿里云 EDAS 产品体系整合，很大原因就是因为在用户技术架构体系里，缺少了 Spring Cloud 这样的产品，再加上 Dubbo 原有的一些用户基础，重启维护无论从哪方面看都是值得的。但是需要多久才能重拾用户的信心，就要看 Dubbo 的后续表现了。

以 Spring Cloud 为代表的云原生模式也是当前业界的主流模式。虽然它可能以解决应用层面的问题为主，尚未与云平台全面对接整合，不过它所带动起来的云原生的理念却被业界越来越广泛地接受。

同时，随着容器及编排技术的发展和成熟，就出现了另外一个云原生的体系，且活跃程度非常高：它就是以 Google 为首的 CNCF（Cloud Native Computing Foundation）。下面我们一起看一下。

CNCF

CNCF 设想中的云原生分层架构示意图： ￼

CNCF 组织成立后，圈中大佬们纷纷加入，比如 AWS、微软、思科、Pivotal 等等，国内的腾讯云、阿里云和华为也参与其中，可见其影响力有多大。

CNCF 的核心项目除了 K8S 外，还有 Goggle 的 gRPC，Docker 的 ContainerD，CoreOS 的 Rkt 等重量级开源项目。同时也有与 Spring Cloud 类似，但更加通用的微服务治理框架，如 Linkerd 和 Envoy，它们被称为 Service Mesh（服务网格）。

这些项目的优势在于，它们是与 K8S 集成和配套的，可以很便捷地应用于 K8S 生态中。虽然 K8S 自身也是支持服务发现、负载均衡这些基本的微服务治理的，但是在 CNCF 中，它显得更加包容与开放，不断吸引业界最佳实践的开源产品加入，共同打造更加开放的生态。下图为 CNCF 当前的项目。 ￼

同时，因为目前 K8S 已实际上成为业界容器编排方面的标准，且被广泛应用，所以各大云厂商，无论公有云和私有云，都会主动支持 K8S 在云计算体系中的落地。

因此，我们根本不用担心 K8S 与云平台上 的资源和各种服务的对接问题，而且它最终也会将应用与云平台很好地连接起来，让开发者能够更加专注于业务开发。至于剩下的工作，则都交由平台去做。

当前，CNCF 的各个项目社区非常活跃，以至于我们一提到云原生，就会联想到基于 CNCF 和 K8S 的生态体系。虽然 Google 和 CNCF 都不是云原生的提出者，但目前看来，它们都是云原生的最佳实践者。

可以预见的技术发展趋势

我们可以看到，无论是 Spring Cloud、CNCF、云原生、还是 K8S 等等新技术或理念，究其根本，都是为了能够更快更好地支持业务需求的快速实现。

从云原生的理念中，我们可以看到，跟业务无直接关系且相对通用的技术在不断地被标准化，而且标准化层面越来越高。

从最底层的硬件和网络设备，到上层数据库、缓存、文件存储以及消息队列等等基础组件服务，再到 Spring Cloud 和 Service Mesh 这样的应用层面的服务管理和治理能力，都正变得越来越标准和通用。

技术每被标准化一层，原来繁琐低效的工作就少一些，技术标准化的层面越高，技术门槛就会变得越低。我们可以作个大胆的预想：或许未来真的只会有业务解决方案和业务代码。

对于我们技术人来说，未来更多更迫切的能力需求将会是：如何利用好业界已有的丰富的技术产品和平台，在面对更加丰富多样且复杂的业务领域需求时，能够更加专注于寻求业界解决方案，以更好地将业务和技术连接起来。找到适合业务解决方案的技术并落地实现，而不再只是专注于技术层面的造轮子。

对于运维来说，我们同样要了解技术发展趋势。虽然我们不会直接参与具体的业务解决方案和代码的开发，但是，如果架构师是业务架构的设计者，那么我们应该成为技术架构的管理者，从效率、成本、稳定性这几个方面来检验架构是否合理，并为架构朝着更加健康的方向发展保驾护航。这也是运维职能转型和思路转变的一个重要方向。

欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

28 | 以绝对优势立足：从CDN和云存储来聊聊云生态的崛起

前面几期文章我们介绍了混合云模式，以及面向应用层的云架构解决方案的 Spring Cloud。接下来，我们就以蘑菇街的两个具体案例，来分享一下基于混合云模式的具体实践。

今天，我们先一起看一下我们最为熟悉的 CDN 和云存储建设。

CDN 和云存储

我们之前提到，CDN 应该算是最早期、最典型的公有云服务，如果我们在业务上用到了 CDN 服务，其实就已经算是在实践混合云模式了。

蘑菇街作为 ToC 的电商业务，自然会有大量的图片访问需求，其中尤以商品图片为最。为了保证用户体验，我们的产品在 2011 年上线之初，就应用了 CDN 技术，当时我们合作的都是专业的 CDN 厂商。

当然，大量的图片访问需求会带来大量的图片存储需求，且随着业务高速发展，这个需求量必然会极速增长。

图片的访问需求量往往会以几百万、几千万、几亿到几十亿、上百亿的增长态势呈现。而它所占用的存储空间也会从 G 扩展到 T，到几十 T、几百 T，再到后来的 P 级别。

所以，起初我们在业务量不大的时候，还可以把图片存在自己的硬件设备上。再往后可以利用 HDFS 这样的对象存储技术来实现，CDN 回源的请求全部回到我们自己的机房里。

但是再往后，我们在这方面的专业性就不够了。这也是我在《为什么蘑菇街会选择上云？是被动选择还是主动出击？》一文中介绍到的：随着体量的增加，CDN 对于专业技术深度的要求就越来越高，技术层面的投入也会越来越大，这个就与我们的业务发展诉求不一致了。

因为对于蘑菇街来说，我们还是期望能够把更多的人力和物力应用到业务技术层面，而不是一味耗费在专业技术研究上。

在 2013 年左右，业界开始出现专业的云存储厂商。在专业技术层面要比我们精深很多，而且他们聚拢了一大批业界专业人才，积累了各类海量存储场景的实践经验，所以他们在产品研发和服务支持上也是能够持续深入的。

基于此，我们后来就选择了将海量的图片放到专业性更强的云存储之上。

到这个阶段，我们的图片访问和图片存储就近乎完全依赖外部第三方的服务，同时也形成了 CDN 回源访问云存储这样的云应用模式。

再往后发展，随着国内两大公有云巨头腾讯云和阿里云相继杀入 CDN 市场，这对传统的 CDN 厂商和新兴的云存储业务造成了很大的冲击。但究其主要原因，我认为还是由于云生态的规模优势发挥了作用。

云生态的优势

上面讲到，我们使用的 CDN 是专业的 CDN 厂商业务，但在当时它们并不提供云存储业务。

同时，专业的云存储厂商固然在存储技术上更擅长，加上它们大多属于创业公司，也没有太多的财力和人力再杀入 CDN 市场。

所以，这两块紧耦合的业务实际是由两类不同的公司在独立发展。但是，在阿里云和腾讯云这样的公有云巨头进入市场后，就极大地改变了这样一个格局。

因为阿里和腾讯各自都有遍布全球的超大规模的自有业务，在 CDN、存储技术以及资源上也有很深厚的积累。当公有云蓬勃发展起来之后，这样的技术和资源积累就可以从内部通过云平台输出给公有云的用户。

那么，阿里云和腾讯云这种公有云模式有哪些优势呢？我们将 CDN 模式与其对比来看。

1. 技术层面。CDN 模式下，图片上传云存储以及 CDN 回源云存储，基本都是走公网网络，在国内复杂的网络条件下，传输质量就很难保障。

我记得 2015 年我来到蘑菇街接手运维的时候，就经常会遇到网站图片展示不出来或者打开特别慢的情况。这就需要找不同的 CDN 厂商定位一些个例问题，非常耗时且麻烦，令人头痛。

在这种形态下，因为是不同厂商间的协作，所以问题只能在小范围内优化，无法从根本上得到改善。但是，在以阿里云和腾讯云为代表的公有云模式下，这个问题就会迎刃而解。

因为阿里和腾讯这两大巨头各自都有全球规模的业务体量，为了保证自身业务的访问体验，它们一定会在 CDN 和存储技术的优化、整合上下足工夫，因此更具备自我改进的动力。

尤其是上面我们提到的上传和回源过程，在公有云模式下基本都有专线质量保障。即使没有专线，他们也会不断优化中间的线路质量。

上云后我们最明显的感受，就是上传和回源图片的成功率和速度都有非常大的改善，近一年来，我很少再碰到像图片展示慢这类问题了。

2. 成本层面。主要包括三块费用：

CDN 带宽费用。用户访问带来的 CDN 流量费用，由各 CDN 厂商收取。对于传统 CDN 厂商，之前价格相对固定和平稳，但是近两年公有云厂商入局后不断降价，在价格上有非常大的竞争优势，这也整体拉低了 CDN 价格。

回源带宽费用。当 CDN 无法获取到对应图片时，回源到云存储获取，这部分回源带宽费用由云存储厂商收取。但是在云生态模式下，上面提到，CDN 和云存储可以整合到某个公有云内部网络体系内，在这个生态中，这部分费用成本就变得非常低了。

存储空间费用。这一项费用由云存储厂商收取，CDN 和公有云这两种模式在这一点上没有太大区别。

还有其他诸如裁图、HTTPS 等服务，都分别会有不同的计费方式，但是这块不是主要成本。

说到这里，我们从整体的商务角度看一下：如果一位客户在同一个地方购买的服务和资源越多，那么商务运作和议价空间就会越大，得到的优惠力度也会更大。这就跟我们在同一家商店买的东西越多、折扣越多是一个道理。

但是，如果这些服务和资源都是不同厂商的，那就需要多方面沟通。整个过程耗时耗力，且能够得到的优惠空间也非常有限。

所以，整体来看，云生态在 CDN 和云存储这个层面，实实在在地帮我们降低了成本。

3. 生态优势，强者越强。云生态的天然优势在于，云平台上聚集了海量的客户资源，只要进入到这个生态中，一般情况下客户都会首选生态内的产品，而不会再跳出去选择其它独立的产品服务。

甚至即使之前用到了第三方的服务，客户也会逐渐转移回云平台这个生态体系中来。

所以，我们现在可以看到这样一种趋势：很多独立的技术产品，正在向云生态靠拢，选择跟公有云合作，争取让产品进入到某个云生态中，并提供相应的云上解决方案和技术支持。

同时，各大巨头也会寻找在某些特定领域，有相当深度的技术产品进行投资，让这些好的产品和解决方案进入到自己的云生态中，以便进一步为云上的客户提供更全面、灵活和多样性的支持。

总结

通过 CDN 和云存储这个案例，我们可以清晰地看到，随着公有云的深入发展，特别是公有云巨头的飞速进步，公有云已经形成了自有的、独特的生态体系。

这不仅仅体现在技术和产品层面，而且可以预见其最终还会形成商业层面的体系闭环。

所以，利用云计算的优势，拥抱变化，才能够为我们的业务发展和创新带来更多的可能性。

以上分享的这些内容，是我在近两年的工作中真切经历过的案例和感受，希望能在思路拓展上对你有所帮助。

如果你在这方面有什么好的经验和想法，欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

29 | 量体裁衣方得最优解：聊聊页面静态化架构和二级CDN建设

上期文章中我们介绍了 CDN 和云存储的实践，以及云生态的崛起之路，今天，我们继续聊一聊 CDN。

我们通常意义上讲的 CDN，更多的是针对静态资源类的内容分发网络，最典型的就是电商的各类图片，还有 JS 和 CSS 这样的样式文件。通过 CDN 能够让用户就近访问，提升用户体验。

但是这类文件只是以单纯的资源存在，与业务逻辑没有强关联。所以我们在技术上，可以使用业界通用的 CDN 和云存储解决方案。

需要注意的是，本文中我们讲到的实践内容，同样是遵从静态内容，就近访问这个原则的。

但是，因为其中包含了大量的业务逻辑，这就要求我们在面对不同的场景时，要有跟业务逻辑相关的定制化的解决方案。

下面，我们就一起来看看页面静态化架构和二级 CDN 建设。

静态化架构建设的业务场景

我们仍然回到电商的业务场景中来。对于电商，访问量最大的无疑是商品的详情页，绝大多数用户都要通过浏览商品详情，来决定是否下单。所以单就这一类页面，就占到全站 30%+ 的流量。

那么，商品详情一般由哪些部分组成呢？我们看下面两个截图：

￼ ￼ 以上两张图就是某个商品详情页的主要组成部分。我们可以看到，商品详情大致包括了商品名称、商品描述、产品参数描述、价格、SKU、库存、评价、优惠活动、优惠规则以及同款推荐等等信息。

这里我们仔细观察可以发现，其实对于商品描述类的信息，比如商品名称、商品描述、产品参数描述等等，一般在商品发布之后，就很少再变动，属于静态化的内容。

而优惠活动、优惠规则、价格等等则是可以灵活调整的，库存和评价这类信息也是随时变化，处于不断的更新中。

说到这里，我们会想到，如果能够把静态化的内容提取出来单独存放，业务请求时直接返回，而不用再通过调用应用层接口的方式，去访问缓存或者查询数据库，那访问效率一定是会大幅提升的。

所以，我们在参考和调研了业界的解决方案之后，引入了页面静态化架构。

页面静态化架构

静态架构中，我们采用的技术方案是 ATS，也就是 Apache Traffic Server。

ATS 是一个开源产品，本质上跟 Nginx、Squid 以及 Varnish 这样的 HTTP 反向代理是一样的。但是它能对动静态分离的场景提供很好的支持，所以在最初，我们直接引入了这样的开源解决方案。

ATS 的架构示意图如下：

￼ 关键技术点：

动静态分离。将页面上相对固定的静态信息和随时在变化的动态信息区分出来，静态信息直接在 ATS 集群获取，动态信息则回源到应用层。通过 HTTP 请求调用获取，最终通过 ATS 组装后返回给调用方，从而实现了动静态资源的分离。

动态数据获取。直接采用 ATS 的 ESI 标签模式，用来标记那些动态的被请求的数据。

失效机制。分为主动失效、被动失效和定时失效。对于静态信息来说，我们也允许它变化，但因为静态信息自身的特性，决定了它不会频繁变化。所以，我们会有一个失效中心，即 Purge Center。失效消息通过 HTTP 的 Purge 方法发送给 ATS，而失效中心则会通过订阅消息系统中特定的 Topic，或者 MySql 中特定的 binlong 变更，执行失效。

以上就是静态化建设的框架性的解决方案，这个方案在电商大促时往往能够发挥更加突出的作用。下面我就简单说明下。

静态化架构在大促场景中的应用

我们还是以业务场景作为切入点来看。以“双 11”为例，参与大促的商家和商品，一般会在 11 月初完成全部报名。届时所有的商品信息都将确认完毕，且直到“双 11 活动 " 结束，基本不会再发生大的变化。

它跟平时的不同之处在于，商品在大促期间是相对固定的，所以就可以将商品的静态化信息提前预热到 ATS 集群中，大大提升静态化的命中率。

同时，价格、优惠、库存这些动态信息在日常是会经常变化的，但是在大促阶段是必须固定的。即使有变化，也只能体现在最终的订购阶段，而在用户浏览阶段尽量保持不变。

所以，这时可做静态化处理的内容就会更多。换言之，静态化架构对于后端的访问请求就会进一步减少，特别是价格、优惠和库存这样的查询计算类请求。

同时，我们静态化页面的范围可以更广，不仅仅是详情页，还可以包括各类大促活动的页面、秒杀页面、会场页面，甚至是首页。

因为这些页面都是提前配置好再发布的，所以我们完全可以通过静态化解决方案，来分担更大的流量。

以详情页为例。在静态化方案全面铺开推广后，静态化内容在大促阶段的命中率为 95%，RT 时延从原来完全动态获取的 200ms，降低到 50ms。这大大提升了用户体验，同时也大幅提升了整体系统容量。

静态化方案和应用场景我们就介绍到这里。你可能会问：既然是静态化的内容，那是不是仍然可以借鉴 CDN 的思路，让用户就近访问呢？

我们下面就介绍一下页面静态化与公有云相结合的方案：二级 CDN 建设。

二级 CDN 建设

上面我们提到的静态化方案，仅仅是我们自己中心机房的建设方案，也就是说，所有的用户请求还是都要回到中心机房中。

静态化方案提升的是后端的访问体验，但是用户到机房的这段距离的体验并没有改善。

从静态化的角度，这些内容我们完全可以分散到更多的地域节点上，让它们离用户更近，从而真正解决从用户起点到机房终点的距离问题。

所以，我们接下来的方案就是：选择公有云节点，进行静态化与公有云相结合的方案，也就是我们的二级 CDN 方案。简单示意如下：

￼ 引入了这样的二级 CDN 架构后，下面几个技术点需要我们多加关注。

回源线路，公网回源转变为专线回源。之前我们的中心机房还是托管 IDC 模式时，动态回源部分都是通过公网回源，同时，静态化配置的推送也是通过公网推送到公有云节点，这对成功率和访问质量上都会有一些影响。但是我们上云之后，做的第一件事情就是将公网访问模式调整成了内网调用模式，也就是动态回源直接改为专线的动态回源。这样大大提升了访问质量，且进一步节省了部分带宽费用。

弹性伸缩。利用了公有云节点之后，在大促时就可以很方便地进行动态扩缩容，以便真正地按需使用。而且自动化的扩缩容，以及日常的静态化配置推送都需要完善。

高可用保障。为了保障多节点的高可用，在单个节点故障时，要能够快速切换。当前我们的策略仍然是，当某个节点遭遇故障，直接全部切换回中心节点。这里为了能够达到快速切换的目的，需要通过 HttpDNS 这样切换 IP 的方式实现。因为 DNS 缓存生效周期较长，如果是通过域名切换，则造成的影响周期会比较长。

总结

今天分享的页面静态化架构方案和二级 CDN 方案，是我在实际工作中较早跟公有云方案相结合的实践之一，并且在我们的日常和大促活动中，起到了非常好的效果。

同时也可以看到，我们的业务一旦与公有云相结合，云生态的各种优势就会马上体现出来。但是无论选择哪种方案，都要结合具体的业务场景，才能作出最优的方案选择。

公有云也好，云计算也好，都不能为我们提供完美的定制解决方案。正所谓具体问题具体分析，找出问题，优化解决路径，量体裁衣，才能得到最适合我们的“定制方案”。

正如我之前提到的：只有挖掘出对业务有价值的东西，我们的技术才会有创新，才会有生命力。

如果你在这方面有好的实践经验和想法，欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

30 | 云计算时代，我们所说的弹性伸缩，弹的到底是什么？

现在，我们经常听到的一些高大上的词汇，比如弹性伸缩、水平扩展和自动化扩缩容等等，你能否说一说，这些技术手段的主体是谁，也就是谁的水平扩展？弹性伸缩的是什么？同时，这些名词之间又有什么关系呢？

下面我们就从弹性伸缩入手一起来分析讨论。

弹性伸缩的主体是谁？

弹性伸缩，一说到这个词，我们可能很自然地会联想到资源的弹性伸缩，服务器的弹性伸缩，容量的弹性伸缩，应用的弹性伸缩以及业务的弹性伸缩等等。我想这些理解都没有错误，但是可以发现，当弹性伸缩这个动词前面增加了这么多不同的主语之后，我们一下子就不知道到底该做什么了。

其实有这样的困惑很正常。我们在讲标准化的时候就提到，做运维和做架构的思路是相通的，我们碰到问题后，一定要找到问题的主体是什么，通过问题找主体，通过主体的特性制定问题的解决方案。

对于运维，一定要准确识别出日常运维过程中不同的运维对象，然后再进一步去分析这个对象所对应的运维场景是什么，进而才是针对运维场景的分解和开发。

这里可以看到，弹性伸缩其实是一个运维场景，但是我们并没有定义这个场景的主体是谁，所以就会出现上面这些不同的主体。我们来假设以下几种主体。

服务器的弹性伸缩。针对这个场景，假设业务是运行在私有云或公有云上，那我们只要能够通过云平台的 API 申请和释放资源，申请时初始化我们的操作系统，释放时销毁资源就可以。不过，在私有云环境下，为了能够保障弹性，我们必须自己提前采购、上架、装机、配置然后交付资源，需要大量的准备工作，公有云上就可以省去这些步骤，可以即拿即用。

应用的弹性伸缩。这个场景下其实是默认包含第一步的，就是我们首先必须要拿到应用运行的服务器资源才可以，这一步做到了，下面就是应用的部署、启动以及服务上线接入流量。

业务的弹性伸缩。我们可以再进一步思考，通常一个业务可能会包括多个应用，所以为了保障整个业务容量充足，这个时候扩容单个的应用是没有意义的，所以这时要做的就是扩容多个应用，但是这里面就会有一个顺序问题，先扩哪个，后扩哪个，哪些又是可以同时扩容而不会影响业务正常运行的，再进一步，业务承载的服务能力提升了，那网络带宽、缓存、DB 等等这些基础设施需不需要也同时扩容呢？

到这里，这个问题就已经变得非常复杂了，而且已经不仅仅是弹性伸缩这个词的表面含义所能覆盖的了，因为这个问题确实很复杂，所以这里暂时不做详述。

好了，分析到这里，我们就可以看到针对不同的运维对象，弹性伸缩这个概念背后的含义是不一样的，所执行的动作以及制定的方案也是不一样的。通过上面的分析过程，我们在日常思考和工作开展中应该注意以下两点。

第一，一定是从实际问题出发，找到问题的主体，然后才是针对问题的解决方案。要反复问自己和团队，我们解决的问题是什么？解决的是谁的问题？切记，一定不要拿着解决方案来找问题，甚至是制造问题。

比如弹性伸缩这个概念，它就是解决方案，而不是问题本身，问题应该是：业务服务能力不足时，如何快速扩容？业务服务能力冗余时，如何释放资源，节省成本？按照这个思路来，我们自然就提炼出业务服务能力这个主体，面对的场景是快速的扩缩容，然后针对场景进一步细化和分解。

第二，如果问题处于初期，且是发散状态时，主体可能表现出很多个，这时我们一定要找到最本质的那一个，往往这个主体所涉及的运维场景就包括了其它主体的场景。

比如上面我们看到的业务的弹性伸缩，就包含了应用和服务器的弹性伸缩场景，它们只不过是子场景而已。从这个角度出发，我们的思路才能打开，方案才会全面。不然如果只是聚焦在服务器、应用、DB、网络等等这些非本质的主体上，提供出来的解决方案肯定也是片面的，而且经常会出现这样的情况，每个人都只从自己的角度出发说问题，始终无法达成一致。问题的根本还是我们没有一个共同讨论的基础，结果就是工作没少做，却始终没有解决问题。

弹性伸缩、水平扩展和自动化扩缩容，它们之间的关系是什么？

这个问题，我想已经不言自明了，找到它们的主体和要解决的问题，我们就会发现，其实它们之间的含义是一样的。

总结

今天我们以弹性伸缩为例，讨论了如何思考问题和分析问题。我们的讨论和分析归结到一点就是：独立思考和分析的能力很重要，意识也很重要，切忌不可人云亦云随大流，反而迷失了工作的方向。

现在业界各种技术上的 Buzzword（时髦词）层出不穷，让人目不暇接，但是仔细观察和思考，你会发现它们背后常常隐藏着很多共性的特点，一定要抓住它们背后所要解决的问题和本质，这样也就不会乱花渐欲迷人眼了。

而且通过这样的分析，我们会更容易发现工作中还需完善的地方，从而引导我们聚焦到实际问题中来，而不是浮于表面，把一些高大上的词汇挂在嘴边，却不见效果。

关于今天我们讨论的主题，你还有哪些想法和心得，欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

06 | 我是如何走上运维岗位的？

在专栏介绍中，我简单分享了自己为什么会走上运维这个岗位，一是责任心使然，出现问题时总是会主动冲在前面解决，另一个是在这个过程中技能提升得很快，很有成就感。不过当时受篇幅所限，并没有完整说明，所以今天我想再来聊一聊这个话题。

聊这个话题还有一个出发点，就是当下业界对运维的认知和定位还是存在很多问题的，有不少贬低运维的言论，所以我想结合自己的经历谈谈对这个事情的看法，期望能够带给你一些启发。

我是怎么开始做运维工作的？

我做运维是在加入华为 1 年后开始的。在华为内部，我从来没有听说过任何贬低运维的说法，反倒是从华为出来，才开始听到一些言论，比如运维背锅、运维层次低等等，当时感觉还有点怪怪的，这一点下面会再详细讲到。

我当时是在华为电信软件部门，大家熟知的短信、彩信、智能网、BOSS 计费系统以及运营商客服系统等都是这个部门的产品。我到公司没多久就进入了一个新成立的项目组，为运营商开发一个阅读类互联网产品，因为是工作后参与的第一个正式项目，从需求讨论、方案选型、代码开发到上线这样一路跟来下，几乎倾注了我所有的热情。当时完全是封闭式开发，除了吃饭睡觉，其它时间基本都用在这个项目上，周六日都是泡在公司的。

项目上线之后，基于运营商海量用户的积累，业务量很快就增长上来了，按照惯例，各种系统问题、故障宕机也随之而来了。当时我们团队规模不大，大家也都是齐心协力，出现问题我们总是一群人一起冲上去解决问题。之所以有这样的反应，主要是因为不忍心看到自己和团队一手打造出来的系统出问题。在华为，软件质量的荣誉感胜过一切。

因为我经验尚浅，所以一开始都是跟在后面看着主管和老员工解决，后来对于一些疑难问题，我就会主动要求接过来研究一下，有时候一个问题要研究好几天才会有些眉目，不过也是在这样的一个过程中，随着解决的问题越来越多，经验也就越来越丰富，很快就成长了起来。

再加上我一直是出现问题后，第一个做出响应和冲到最前面的那个人，主管和团队也对我有了足够的信任和认可，也正是因为获得了这样的信任和认可，后来我得到的成长机会就越来越多。

这里就分享一点：

要敢于承担责任，敢于表达自己的想法。特别是对于职场新人，只有承担，且敢于承担更多更重要的责任，才能够快速成长起来。一些重要事项，主管肯定是优先安排最稳妥和靠谱的人去做，这个时候老员工的优势会更明显，作为新人或经验尚浅的员工，如果没有积极主动的态度和令人放心的表现，很多好机会往往就与你失之交臂了。

当时，我们解决完问题，不仅仅是内部解决完就好了，还要给客户汇报。说简单点，就是把问题原因、处理过程和后续改进措施，用客户能够听懂的表达方式讲出来。一般都是先用邮件发送正式的报告，然后再当面做解释和汇报。当客户不理解、不认可的时候，你就要花更多的时间和精力想办法去表达清楚。

说实话，我当时认为这是非常浪费时间的事情，我想要是把这些时间都花在技术研发上该多好。不过，多年以后回过头来看，这个过程对于培养、提升自己的“软技能”是很有帮助的，主要锻炼了以下几个能力。

能站在对方的角度考虑问题，或者说要有服务心态。很简单的一点，你不能拿着一堆晦涩难懂的技术术语去给客户解释，而是得用客户听得懂的业务语言解释。

文字表达和口头表达能力。不论是书面的还是口头的，表达一件事情都要有清晰的逻辑，把前因后果理顺畅，先有结论，然后分条陈述。我现在能写这么长篇幅的专栏文章，很大程度上也是受益于这个过程中写报告的锻炼。

从更全面的角度看待问题。有时候有些问题可能不仅仅是技术层面的问题，也可能出在其他方面比如业务逻辑、第三方、用户自身以及信息沟通上。一开始，面对这种问题我都是直接反馈说不是技术问题，跟我们没关系，可以想到这样的回答总是会被客户诟病。慢慢地我才发现，即使问题最终不是由你来解决，也应该全面考虑问题，跟客户一起讨论最终的解决方案，这样才会得到认可。后来我发现这是一个技术人员普遍存在的问题，比如，“我的代码没问题”，“在我的电脑上是好的”等等，其实就是缺乏全面看问题的意识，也是缺少站在对方角度考虑问题的意识。

首问负责，问题闭环。问题找到你，你就要端到端负责解决，最终要给客户一个满意的答复，即使问题解决不了，也要能够获得客户认可的反馈。而且，如果这个事情是比较复杂的，需要时间和一个过程来解决，一定要在过程中及时反馈，而不是迟迟不响应。一个最常见的反模式就是“这个跟我没关系，你去找谁谁谁吧”，一句话就把客户的满意度给消磨没了。

这么多年工作经历下来，我感觉对我个人职业发展帮助最大的，恰恰是上面这些良好的工作习惯，没有这些好习惯的扶持，单纯的技术技能成长很容易遇到瓶颈。而且，如果说技术技能是在不断更迭变化的，上面这些做事的基本原则却可以随时随地迁移使用。趁早养成良好的职业习惯，会对个人发展有巨大的好处。

对这个阶段做个总结，我更愿意承担一些非常具有挑战性的工作，成长得就比较快。同时，在客户层面，我又相对比较愿意表达见解和意见。虽然那个时候没有什么沟通技巧，也没什么表达技巧，甚至有些时候是笨嘴拙舌的，但是，很多时候技巧是次要的，最关键的是要敢于表达，当团队需要这样一个角色时，是不是有人能够站出来承担起这个职责。慢慢地我在客户层面也得到了一定的认可和信任，成为一个真心诚意、关键时刻能靠得住的一个人。通过这样一个阶段，我不但在技能深度上有了积累，在广度上也体现出了明显的优势。

我为什么会把运维当作职业发展的方向？

这个阶段大约也就 1 年左右，我的主管就开始跟我沟通，由我来组建这个产品的运维团队，把线上运维、稳定性和部分客户沟通工作完全交给我。

可能有些人觉得做运维是很低级的事情，让你做运维就是让你去填坑，其实对于这样的言论以及今天开头提到的什么运维背锅论，我是十分反对的。当然，更多的时候我也不是去解释，而是靠做事情来证明。

说回到当时的事情上，当时主管在跟我沟通独立带一个运维团队时，我的感受不仅仅是晋升层面的喜悦，更多的是因为能够做运维而感到非常自豪。

为什么会非常自豪，这就不得不提到华为内部，在当时来讲，就已经有非常完善和先进的运维体系和运作机制了，我们一起来看一下。

在华为内部，运维是非常受尊重而且非常关键的岗位。如果你在研发团队中一直写代码，没有做过运维工作，是很难晋升高级别岗位的。所以华为的架构师、技术经理甚至是更高级别的研发主管，按照不成文的规定，都默认要在运维团队轮岗过，然后再选拔出来。而且这里面最最关键的是，运维这个岗位不是你想做就能做的，是有条件要求的。

下面我们就来看看有什么样的条件要求。我当时是在华为电信业务软件部，华为的运维体系分为一、二、三线，我们分别来看。

1.一线维护

这个团队是负责产品的交付服务和后续的客户服务工作。从技能上，很像传统运维，主要是对网络设备、硬件主机和操作系统层面要熟练。一方面要负责交付的项目管理；另一方面，也是非常重要的一点，要对一线客户满意度负责，也就是客户反馈的所有问题，甚至是客户工作中表现出来的喜怒哀乐都要关注。

一线维护，最重要的就是必须要有非常强的服务意识。

2.二线技术支持

因为一线维护面对的是单个具体的运营商，在遇到一些问题的时候，往往没有经验，但是二线因为要面对某个产品全球的局点问题，所以在经验上更容易沉淀和积累。当某个一线团队遇到没有经验的问题时，二线有可能就可以很快很好地帮忙解决，而不用直接透传到三线。

同时，二线还要做好统筹协调，因为一线过来的问题不仅仅是产品本身问题，也可能是网络设备、硬件、操作系统、存储甚至数据库等的问题，这就需要二线帮助一线协调专家资源进行处理，而不是一线再一个个找人，这时一线只管反馈问题即可。

二线技术支持，大多由产品研发或者一线维护经验的人员抽调上来的，即使没有这些经验，也要下放到一线去锻炼很长时间，两三年都有可能，所以技术和经验上都相对更加全面，同时能够有较强的推进协调能力。

3.三线研发维优

到了三线就是研发团队中的运维团队了，这个团队在华为叫做维优团队。这个团队就很牛了，一般都是从开发骨干精挑细选出来的，一方面是为了锻炼人，另一方面也是为了在出现问题时，能够有最专业、能力最强的人响应处理，因为电信级业务是国计民生的基础设施，一般传递到三线的问题，都是比较严重或者疑难的了，必须投入精兵强将第一时间解决问题。

处理问题的过程中，还会不断完善工具体系，提升日常维护和问题定位的效率。因为三线同样要面对全球局点问题，所以 7*24 响应，而且常年无休，比我们现在互联网运维的工作负荷要大得多，所以这个团队成员一般做个 1~2 年就会转岗晋升，不然身体肯定是承受不住的。

三线研发维优，这个团队的成员就像军队中的突击队或尖刀连一样，总是冲在最前面，在高压状态下，解决最复杂、最棘手的问题，所以从选拔阶段，就有非常高的要求。最终经过这个团队磨练出来的人，技术能力、沟通协作能力以及全面解决问题的能力，都是非常突出的。自然地，在晋升发展方面就会有更大竞争优势。

上述这样一个非常严密的一、二、三线运维机制和协作体系，各条线各司其职，发挥各自优势作用，串联起了客户、产品和研发整个技术支持体系，基本上就支撑起了华为电信软件在全球局点的技术支持和服务工作，这一点还是很强大的。

也因为各自都有独特的价值体现，所以运维岗位上人员的存在感和成就感就会比较强，当然就不会觉得做运维是很低级的事情。同时，因为人员非常优秀，能力突出，这个岗位得到尊重也是必然的，甚至是令人向往的。

其实，能够得到尊重，还有非常重要的一点，就是来自华为对客户和用户的尊重，真正的把“客户第一”融入到了整个公司的组织架构和运作机制中。

这里我们不做过多发散，理解下来就是谁离客户最近，谁对客户负责，谁就能代表客户，谁就有最大的话语权，甚至是指挥权和决策权。体现在上述我们所说的运维机制上，就是：一线的声音，代表了客户声音；一线反馈到二线的问题，二线必须响应；二线传递到三线的问题，三线必须响应。

当然，问题级别不同，响应效率可以不同。同时，三线可以根据客户现场情况，以及问题严重程度，对问题进行升级，以知会到更高层级的主管进行关注。

在考核上，如果一线提交的问题，最终被定性为二线支持问题，或者三线研发质量问题，那二、三线的全年考核将会受到影响，如果是频繁出现问题，那就会受到严重影响，而且各级主管要承担连带责任。

这套机制的根本目的，还是为了促进整个体系能够以尽快解决问题、提升软件质量为目标。整个团队树立起这样的观念，就自然会对质量和问题有敬畏感，研发维优那个时候大多都是远程电话与一、二线沟通，潜意识里就会把一、二线作为他们的客户，同样保持谦卑和尊重。

所以，无论是从对运维的定位上，还是整个公司文化以及运作机制上，都形成了对这个岗位的高度定位和尊重。

说回到我个人，因为当时项目性质的原因（前面提到本质上是一个互联网形态的项目），是高度定制化的，并不是传统电信业务的产品形态，所以当时我们无法直接获得一、二线的支持，所有的运维工作都由研发团队完全独立承担，当时我就是把一、三线的事情都做了，前面很长一段时间是既做开发又做三线维优工作，对我技能上的提升帮助非常大。再往后因为精力有限，在后端维优团队建立起来之后，我就花更多时间做一线工作，贴近客户多一些，这里就对我之前说的职场软技能的提升有很大帮助。

当时华为的三线研发维优，其实很像 Google 的 SRE 岗位，各方面能力要求很高，不仅仅是软件开发这么简单，所以当时让我去做运维，并且给到我足够的授权去组建和带团队，就相当于让我去做 SRE 这样高端的岗位，我自然会觉得非常自豪。

再往后，在这个专业方向上做精做细，形成差异化的优势，自然就会有更大的收获。

给我们的一点启发

这样的一个发展过程并不是我刻意设计过的，机会也不是刻意争取到的，就是平时多做一点，做得认真一点，确保最终能够拿到结果，而且稍微努力一下，尽量拿到比预期好一些的结果。在这个过程中，随着个人能力的提升和全面发展，后续各种机会也就随之而来了。

如果让我总结就是这么平淡无奇，如果让我给出个人发展建议，想要从普通做到优秀的话，就是上面几句话。

岗位上，可能不会跟我一样去做运维，但却一样可以做到优秀的架构师、技术专家、项目经理或产品经理等等，只要你有心即可。

最后，你在个人成长和实际工作中遇到过哪些问题呢，有哪些感悟和心得，欢迎留言和我讨论。如果今天的内容对你有帮助，也请你分享给身边的朋友，我们下期见！

13 | 云计算和AI时代，运维应该如何做好转型？

今天我们来聊一聊，在云计算和 AI 时代，运维应该如何做好转型？今天的内容可以说是我们前面运维组织架构和协作模式转型的姊妹篇。针对运维转型这个话题，谈谈我的思考和建议。

我们先来看业界的三个典型案例，一个来自国外，一个来自国内，最后一个是我自己团队的案例，都非常具有代表性。

先看国外 Netflix 的模式。

Netflix 从一开始就强调开发人员进行自助化运维。我们第一篇文章中就介绍到，Netflix 内部的运维工作全部都由开发人员完成，平台也由开发自己完成，只保留极少的 Core SRE 角色专门响应和处理严重等级的故障。类似的还有亚马逊，无论是其电商业务，还是 AWS 公有云服务，全部都由开发搞定。

这样的团队因为其技术前瞻性，微服务以及分布式这样的技术架构早已落地，再加上其超强的技术能力，所以可以从一开始就这样来做。

再看国内阿里的模式。

阿里技术团队在 2016 年左右，也开始进行“去 PE”的组织架构调整，原来需要 PE 完成的运维工作，全部由开发承担。原来的 PE 要么转岗去做工具平台开发，要么作为运维专家做产品规划和设计，还有一部分无法适应调整的 PE 就只能离开了。之前在业务稳定性保障过程中起到核心作用的 PE，随着各类工具平台的逐步完善，在高度自动化之后，最终也只能面临职业和技能上的转型。

这种模式，与 Netflix 正好相反，也就是一开始技术能力无法满足要求的时候，能靠人就先靠人，然后过程中不断完善各类自动化平台。

最后，再说说我自己的团队，发展过程中的模式。

我大致回顾了一下，发现从去年年初到目前，将近两年的时间里，我自己的团队也没有招聘新的应用运维人员了。并不是没有合适的人，我总结了一下主要有两个原因。

第一个原因，随着自动化逐步完善，效率不断提升，单个 PE 能够支持的业务变得越来越多；同时，很多事情开发都可以自助完成。

第二个原因，我有意识地招聘具备开发能力的人员，他们入职后一方面参与各类平台的开发，另一方面还要定期轮岗做一些运维工作。后来我发现，只要有效进行引导，同时具备运维和开发能力是不成问题的。

所以，结果就是，应用运维的岗位需求已经没有这么强烈了。从趋势上看，跟阿里的发展过程非常相似。不过这个过程，我从来没有刻意地设计过，基本算是顺其自然。

从上面的这几个案例来看，无论哪种情况，就运维来说，随着日常重复的人工操作被逐步自动化之后，如果还是固守原有的工作模式和思路，能做的事情、能够提供的价值，一定会越来越少。终究有一天，我们会面临和阿里 PE 同样的转型问题，而且这个转型是在可预见的短期内就会到来。

既然预见到了趋势，那下面我们就来谈谈应该如何面对。

应用运维的转型

如果只允许给一条建议的话，我给出的建议就是：学会写代码。

我们早期的运维岗位，基本上都不会对代码能力有很强的要求。所以对这个岗位上的同学来说，这一点就成了技能上最大的短板，也成了后续职业发展的瓶颈限制。

但是，运维行业发展到现在，无论是从趋势上看，还是从我们现在所经历的实际现状来看，单纯靠人力维护的投入越来越无效。

所以，无论是我们做运维转型也好，还是做其它技术转型也好，具备代码开发能力，已经成为一项必备技能。

这里多说一点，我们大多数做运维的同学不具备代码开发能力，并不是自身的能力问题。很多情况下都是因为不够自信，对写代码心存畏惧，担心自己写不好，所以一开始就把自己给限制住了。如果是这样，我给的建议再多也没用，关键还是要靠自己先迈出第一步。

现在我自己的团队中，有很多同事做了多年运维工作后，因为乐于尝试和挑战，很快就可以独立编程，而且因为自身有很多一线运维经历和经验，可以说即懂业务又懂开发，反而比单纯做平台和工具的运维开发更有竞争力。

下面是一些具体的建议。

代码开发上，我的建议是可以从 Python、PHP 或 Go 这些上手比较简单的语言开始。这里不是写脚本，一定要能够实现完整的业务功能或流程。一开始尝试去做一些简单的工具，实现一些简单的功能，再往后可以通过一些复杂的业务场景深入下去。一旦场景的复杂度高了，就会涉及到更高的开发技能，比如并发、缓存、消息甚至是服务化框架等等。关键是敢于迈出第一步，然后逐步转变。相信我，真的没有那么困难，我身边有太多的优秀转型案例，都是这么过来的。

提升产品意识。这里不是要求运维同事都成为优秀的产品经理，或者具备很强的产品设计能力，而是一定要有产品意识，只要有这么一点点小转变就会带来大不同。我简单说明一下，我们很多运维同事，甚至是资深级别的，往往还是习惯于处在最末端，前面有什么事情找到我，我就处理什么事情，属于被动响应类型的。但是，如果你有产品意识，能够将你所做的事情整理汇总起来，然后做一下流程上的串联，再把流程中每个环节步骤的功能进行详细描述，同时在梳理的过程中，将一些不合理、不规范的地方进行标准化约定，也就是我们前面说的标准化过程，然后输出的内容就是平台开发所需要的需求分析和产品 PRD 的雏形了。如果能将所做的事情从单纯的运维操作转化到这个维度，那我们呈现的价值就完全不一样了。

提升技术运营意识。这一点跟上面类似，简单来说，就是如何根据需求，把承载了标准化和规范体系的工具平台真正落地应用起来。同时，在落地的过程中，通过问题收集和一定的数据分析，然后再回到产品设计和需求实现流程中进行改进，形成一个良性的闭环。

在阿里的 PE 转型过程中，有一部分转型去做效能工具研发，有一部分经验丰富的资深运维就转型去做了技术产品和技术运营这样的运维专家角色。对于开发人员已经可以自助完成的部分一线运维工作，运维专家还会在这个过程中对开发做一些赋能。

所以，对于当前运维岗位上的同事来说，有这样一个先天优势来承担这样的职责，可以参考阿里 PE 转型的经验，根据自己的优势特点提前做好方向规划。

云计算和 AI 带给我们的挑战

机遇与挑战并存，上面我们更多地讲了机遇，但是与此同时我们也要看到挑战，甚至是危机。

而最大的挑战和危机往往都不是来自内部，当我们还在纠结如何不被开发替代的时候，外面的技术环境已经发生了很大的变化，而这种变化带来的将是颠覆性的改变。

有两个最大的外部因素，一个是云计算，一个是火热的 AI，我们分别来看。

首先，云计算发展到今天，已经不是我们想象中的只能提供 IaaS 服务的云平台了，目前各大公有云上的 PaaS 产品体系也已经非常完善。我们前面讲的各类分布式中间件产品都有覆盖，而且这些产品，还都是各大公有云平台公司在自有业务上锤炼出来的非常优秀的产品。

简单一句话，现在我们去做一个业务，基于这些基础服务，完全无需自研纯技术产品，只要专注业务逻辑开发即可。我了解到国内某新兴的 O2O，每日超过千万笔的订单量，除业务代码外，其它基础层面的服务就完全依赖于某大型公有云的 IaaS、PaaS 以及周边的各类服务体系。

这种情况下，非但不再需要大量的如 SA、网络工程师、DBA 以及应用运维这些岗位，就连技术门槛较高的分布式中间件研发岗位也会大量缩减，所以这个挑战和危机就会非常大了。

这种情况下，我们应该如何面对？其实，我在前面的文章中已经给出答案，大家可以先回顾一下，然后再往下看。

这里的答案就是，从价值呈现的角度来思考我们可以做什么。至于做什么我前面也提到过，比如持续交付以及稳定性保障体系。当然根据业务的不同特点，远不止这些内容。这些都是跟业务自身层面相结合的，与平台无关。与业务结合，就会有个性和独立的地方。如何根据自己的业务特点，找到跟业务相切合的价值呈现点，是我们每一个人应该去思考和探讨的。只有找到这些点，我们做的事情才会有价值和意义，我们所在的岗位才会有价值和意义。

然后，再谈谈 AI。这里说明一下，我们现在谈到的 AI，其实大部分情况是在谈论 AI 的一种实现方式，就是机器学习算法。关于这一点我在 InfoQ 分享过一篇文章，我把链接附在文末，如果你感兴趣可以读一读。

AI 和 Ops 的结合，更多还是场景驱动的。就是我们要处理的数据量越来越多，面对的场景越来越复杂，而且会大大超出我们人力的认知范畴。比如 BAT 这样的公司，几十万台服务器的规模，出现一个问题，我怎么能够快速发现，快速定位，并最终快速恢复？如果是几百甚至几千台服务器，靠人还是可以搞定的，但是几十万台，靠人就不可能了。

所以，这个时候，就需要借助技术的能力，而机器学习算法又正好可以满足我们的诉求。

这里想特别提一点，机器学习算法的应用，是离不开场景和业务特点的，也就是说怎么用还是离不开人，离不开对业务和场景熟悉的人。从我现在了解到的情况来看，很多公司和团队，针对每一个场景都需要投入很大的精力去对某个特定曲线和算法进行调参优化，以确保它们的准确性，也还没有神乎其神地达到完全不靠人的无监督学习。这里面并不是说算法本身不具备这个能力，而是现实场景太复杂，我们不能用简单固化的算法来应对。

说到这里，我想我们应该可以抓住这里面的关键点了，就是懂线上运维实际情况的人做这个事情，会更加适合。当然，这是极其理想的状态，因为机器学习算法的应用还是存在比较高的门槛，不仅仅是技术层面，还要一定的数学基础，需要对大数据产品有所了解等等，是个相对复杂的过程。

所以，这里我的建议就是要多去了解，因为未来随着技术、数据和计算能力的提升，AI 是一个必然的趋势。如果一点都不了解，极有可能就会被卡在门槛外面，这就不是转型的问题了。

总结

上面我结合一些运维发展到目前的现状以及呈现出的趋势，做了一些分析和建议。最后我们总结一下。

新时代下，机遇和挑战并存，我们确实面临着岗位和技能的转型。我给出的建议是：学会写代码，培养产品意识，提升技术运营意识。

当然，转型这个过程也不会完全是绝对和极端的，以后就一定是一个运维都不要，一个 SA 也不要，一个网络工程师也不要。但是，我们应该看到，这些岗位会更加收敛。一个是岗位设置上会收敛到各大云平台厂商这里，做专职的基础和后端的服务维护；同时随着自动化的完善，在岗位数量上也会收敛，不会再出现大批量的岗位需求。最重要的，这些岗位上的价值空间以及成长空间，将会变得极为有限，不管我们愿不愿意承认，这都是我们不得不接受的现实。

同时，在云计算和 AI 时代我们面临的这些挑战和危机是可以预见到的，而未来还会存在大量的不确定和我们预见不到的东西，这种情况我下我们又应该如何应对呢？

或许，唯一的办法就是不断地学习和提升自己的技能，保持对技术发展趋势的敏锐性，及时做出调整和应对，才是根本的解决之道。

关于今天我们分享的主题和内容你有怎样的感想呢？你是否正在面临转型的困惑？是否已经成功转型，有什么经验？欢迎你留言与我分享讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

拓展阅读

AIOps 为什么是运维发展的必然趋势？

AI 时代，我们离 AIOps 还有多远？

14 | 运维需要懂产品和运营吗？

在《云计算和 AI 时代，运维应该如何做好转型》这一期内容中，我提到两个转型建议：一个是技术产品，另一个就是技术运营。今天我就更加聚焦地来分享这个观点。

我们运维接触更多的是软件生命周期中的运行维护阶段，我之前总结过一张图，就是在这个阶段要做的一些事情，把它们串起来就是下图：

这张图的思路应该非常清晰了，而且对照一下我们日常在做的工作，基本上也离不开图中所描述的这些事情。

这里我想表达的是，我们应该从这张图中敏锐地观察到，研发团队对运维团队的诉求，以及运维呈现的价值已经发生了变化，我们更加需要能够帮助团队建设出高效运维体系的角色，而不是能够被动响应更多问题的角色。

运维的角色转变和价值体现

打造一个运维体系，我们完全可以把它类比为一个产品业务体系。我们公司的组织架构中，针对一个产品或业务，如果要对其进行技术上的实现，自然就离不开类似运营提需求，产品分析设计、业务架构师设计建模、开发实现以及测试保障这样一环套一环的配合，每个角色都发挥着独特的价值。

那么，对于一个运维体系，就相当于是面向研发团队内部的一套技术业务体系，只不过我们的需求方和客户是开发人员，而不是业务人员。

我们对照一下可以发现，运维团队中技术环节的角色是不缺的，但是缺少的是业务环节的产品和运营角色。但是我们做事情，不一定非要有岗位上的明确设置才能往下做，只要有能起到这个作用的人承担这样的职责就够了。而这里，最合适做这个事情的，一定是运维，因为运维是日常线上运维的执行者，只有运维最清楚这里面的细节、问题和痛点，换其他人可能很难能够讲清楚。

当然了，我们也不能强制要求运维一定要完全具备产品经理和运营经理的专业素养，这样就本末倒置了。这里我们强调的是运维要有产品和运营意识，总结起来最本质的就两点：第一，能将需求讲清楚；第二，能将产品推广落地。

技术产品

关于技术产品，其实主要就是回答以下几个问题：

是不是能够把原本靠人工完成的很多工作转化成需求？

是不是能够把日常工作中运维和开发的痛点转化成需求？

是不是能够把当前系统存在的问题和隐患找出来，在解决的过程中，经过分析总结提炼成需求？

这个过程中，可以尝试把自己做的事情串一下，用流程图也好，时序图也好，把整个过程梳理一下。过程中每个环节具体要做的事情可以通过文字描述的方式写出来，尽量分条罗列，清晰有条理。这里也可以参考我们前面讲过的内容，把一些标准化和生命周期管理的方法论融进来。这样可以一举两得，我们的标准化制定能力，场景需求分析能力慢慢都提升上来了。

你可以按照我们刚才讲的内容动手做一下，这样整理出来的一份文档或者内容，其实就是一个产品 PRD 的雏形。如果你想要更进一步，有更加专业的输出，也可以参考了解一些产品设计方面的知识。

当需求提炼出来之后，跟对应的运维开发一起合作，将需求真正落地实现。这样一个过程下来，运维的价值和能力体现是不是就跟之前有了很大的不同呢？

技术运营

通过上面技术产品的工作，可以做出一些有针对性的工具和平台来。但是，仅仅有工具和平台还远远不够，因为只有把这个平台真正落地，并产生了实际效果，才是有意义、有价值的。这个“真正落地”就是技术运营要做的事情。

所以，接下来要做的就是落地。

平台推广落地。工具做出来了只是第一步，得要有人用，这就需要去推动落地，让大家都来使用，从而真正给团队带来规模上的效率提升。同时，我们的技术产品也是各种标准和规范的载体，在这个落地过程中，也是标准落地和执行的过程，就需要运维和开发配合做出一些改造，为后续更大规模的效率提升和平台建设打下基础。

线上运行数据分析。通过我们的平台和工具，对线上业务和应用运行时的指标进行数据分析。比如，应用上线或者每次变更上线后，线上运行的情况是怎样的，容量有没有降，RT 有没有上涨，监控有没有异常，用户体验有没有下降，用户和客服的反馈如何等等。以上这些维度和指标就需要通过数据、图表和曲线的方式呈现出来，并基于这些呈现进行分析和判断，做出后续运维决策，比如是否需要扩缩容，是否需要处理问题，是否有改进的地方。在这一点上，应该要形成对整个业务和技术架构体系改进和完善的正反馈才行。想想看，业务运营是不是也非常关注业务的数据报表，也要依赖数据情况决定后续的业务运营手段。

过程改进。平台更多的是一个执行工具，但是工具的使用是要配合大量的标准和流程一起来运作的。比如上面我们提到的，如果一次发布之后流量下降，RT 升高很多，面对这样的问题我们应该有怎样的应对机制，这里就体现出管理和流程的重要性了，要解决好不同角色和团队之间的协作问题。同时，过程中需要改进和完善的内容，能够落实到平台和工具的，也要形成正反馈，来提升我们工具和平台的效率。

这个过程可以用下图来表示：

我们面临的业务场景在不断发展和变化，这就决定了技术运营过程也必然是一个持续发展和完善的过程。所以从这个角度讲，技术运营的生命力和竞争力将会是持久的。

在腾讯，运维就被定义为技术运营，第一次听到这个岗位名称时，感觉还是很贴切的。另外，我在很多大会上听海外的华人工程师分享，Operation 这个词都是被直译成运营，但是在国内我们大多还是把 Operation 翻译成运维，从字面上就把这个岗位的定位给拉低了。

不过，叫什么不重要，只要我们通过今天的内容看到，具备技术产品和技术运营的能力才是最关键的，这一点最重要。

总结

最后，我们再总结一下，运维虽然不是业务系统的实现者和代码的开发者，但是我们参与到了产品技术标准的制定、业务系统运维体系的建设以及后期的技术运营中，这个时候运维已然成了整个技术架构的设计者之一，而且是架构稳定和演进的看护者，这时我们所发挥的作用和呈现的价值已大不相同。

从技术产品和技术运营的角度再来思考一下运维，现在的运维还是之前那个运维吗？欢迎你留言与我一起讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

15 | 冷静下来想想，员工离职这事真能“防得住”吗？

本周主要和你分享几个关于个人成长的话题。前面我们讨论了在新时期运维如何做好转型，运维是不是要懂产品和运营这两个内容，都是为了我们能够成长为技术骨干，最大限度地发挥出自己岗位的价值。

今天我们就往后聊一聊，当你从技术岗位转换到管理岗后，应该如何适应新的角色，做好技术管理。技术管理这个话题很大，不是一下子就能说透彻的。所以，我就把处理员工离职问题做为一个切入点，从这个角度说起。

从员工离职说起

年末年初，对于任何一家公司或者一个团队来说，最令人头疼的事情就是员工离职问题，特别是骨干员工的离职，对团队带来的影响和损失，以及团队氛围和信心上的影响是非常大的。

其实从员工离职这件事情上，我们还是能够反推出一些在日常管理中的问题，甚至是我们作为技术管理者自身存在的问题。同时，我们还应该从这件事情上找出我们的改进措施，不断提升我们的技术管理和团队建设能力。

Design For Failure 的软件架构设计理念，同样也适用于技术管理工作。

因为我在 EGO 会员组（极客邦旗下高级技术管理者社群）专门分享过类似观点，引发了一些讨论。所以今天借着这个问题，详细分享下我在这方面的一些经历和感受，同时我也会给出一些技术管理中的反模式，这些是需要我们引以为戒的。

关于员工离职的两个观点

我先给出对于离职的第一个观点：对于离职这个事情，本质上就是员工个人发展和团队发展不匹配之间的矛盾。

稍微解读一下就是，如果员工个人发展速度很快，而团队提供的空间或机会不足，员工就会调岗甚至离职，寻求更好的利于个人发展的机会；而如果公司和团队发展很快，员工跟不上组织发展的节奏，这种情况极有可能就会被团队淘汰。

反观其它的理由，主管因素、薪酬福利，或者因为世界太大想去看看等等，这些都只能算是表面上的直接因素，或者叫导火索因素。

比如，我们现在经常说的，员工离职最主要的因素之一是与主管不合。如果我们仔细想想，根本上还是因为主管在目标方向上与员工个人诉求达不成一致，或者管理方式上限制了员工个人发展，所以员工选择离开，或者团队主动淘汰，本质上的原因还是离不开发展这个诉求。

但是，有时候员工对于个人成长的不满意和不顺心，无法客观理性地表达，最终就都归因到主管身上；当然作为主管，有时候不考虑员工感受和自身因素，就简单粗暴地进行管理，也不是没有问题。所以看问题要全面，我相信更多的情况是因为双方性格和风格上对不上，并没有什么是非对错，所以一切看开最好。

接着彼此间发展诉求的矛盾这个问题，我再给出第二个观点：对于员工离职，从管理者角度，我们应该理解为必然结果，坦然接受，而不是避而不谈。

每个人在不同阶段，总会有不同的成长和发展诉求，所以总会有一部分员工在一家公司待到一定年限之后，会为了寻求更加适合自己的机会而离开，因为员工和公司之间的发展不可能始终保持匹配，所以从这个角度来讲，员工个体上的离职是一个正常现象，也是必然结果。

上面这个观点来自于领英 CEO 里德·霍夫曼写的《联盟》这本书，这里结合我自己的感受和理解谈一下我个人的看法。

如果能意识到是必然结果，那我们要做的就是 Design For Failure，不要试图去完全避免和杜绝离职，而是要有措施能够有效规避离职带来的问题和风险。也许最大的问题在于，道理我们都懂，但是能做到的不多。

所以，下面就来谈谈应该如何做好技术管理。

谈谈如何做好技术管理

1. 帮助员工做好个人中长期发展目标规划

主管应该跟员工一起确认员工任期内的中长期成长和发展目标，让员工能够在任期内发挥最大的作用和价值，同时能够尽可能地让员工在任期内达成自己期望的成长目标。对管理者来说有一件很重要的事情，就是能够找到团队发展和员工个人发展相契合的价值点。

这里很重要的一点，做技术管理者，一定要从关注事情、管理事情转换到关注人的层面。要关注人的成长发展，关注成长发展中的问题和疑惑，关怀人的工作体验和心理感受，这个才是管理的核心。一定不要忽略人这个核心要素，人的事情搞不定，其它任何事情都无从谈起。

我们很多管理者当前是缺失帮助员工做中长期个人成长这件事情的，更多的是做眼前工作的任务指派，甚至是指令性下达。所以现在很多员工离职，都会提看不到发展目标，看不到空间等等。这里的关键还是上面说的管理工作缺失，大多是我们没有帮员工做，而不是真的没有空间了。

这个事情要放到平时做，从团队人数还不多的时候就开始。我的团队 30 多人，基本每个月都和团队的每一个人做一次一对一沟通。如果实在忙不过来，那就针对核心骨干和有潜力的员工。这个沟通要持续做，并持续调整。如果放到员工要离职了再做，再去承诺，就没有意义了。

2. 进行梯队建设

各层管理者和 HRBP，要有意识做好梯队建设，确保人才能够源源不断地输入。如有有员工离职能够有人顶上来，至少是有 Backup，不至于因为一两个人离职团队就垮掉了。这块就涉及到招聘和“传帮带”机制的建立。

团队成员不一定都是水平很高、能力很强的人，关键是要合适，能形成合力。所以团队中既要有经验丰富和技能突出的明星员工，又要有发展诉求强烈的骨干员工，还得要有对各种事情充满激情和新鲜感的小鲜肉。每个梯队的特点和风格不一样，形成互补，发挥各自独特的价值，这样的团队才能够有生命力。

3. 提升管理意识

我也是从技术转技术管理，说实话栽了很多跟头，吃了很多亏，才慢慢有所转变，这个过程比较漫长。所以，对于刚做技术管理者的员工，HR 团队一定要辅助做好“转身”的培训和赋能，不然就得吃“一将无能，累死千军”的亏。

同时，在这个事情上，更高级主管层面也应该要有些耐心，甚至有些时候要容许一些管理上的失误，不至于一出问题就一竿子打死。因为管理这个事情很多时候是需要管理者个人从一件件事情，甚至是一个个跟头中，一点点去“悟”到的。

技术管理中引以为戒的一些反模式

上面讲了做技术管理应该重点做哪些事情，那下面再说说应该少做甚至不做哪些事。

1. 事必躬亲，不懂授权，不敢授权

最常见的情况就是所有事情都会参与、过问甚至是干涉，更甚者，因为自己做更快，就懒得指导员工，直接亲自上手做。这样下去，久而久之，就相当于剥夺了员工成长的机会，剥夺了员工独立思考的机会。

我的建议是，对于非紧急的事情，还是让员工自己动手完成。你可以指导，可以给建议，但是不要代替员工执行和思考。

2. 总认为自己才是最正确的

懂得授权和分配工作后，往往把自己的想法和经验强加于员工，因为总觉得自己的经验才是最好的，即使思路上和方式方法上仅有一点点不同，也要跟员工争个是非对错。长久下去，员工的主观能动性就没有了，不但容易失去与员工之间的信任，还极容易造成与员工之间的矛盾。

我的建议跟上条相似，可以更多地给员工授权，多从边界条件和目标结果上提问，让员工主动思考。如果员工的方案是可以达成目标的，就可以放手让员工去做，过程中关注进展和风险，多给辅导和建议。

3. 仅仅关注技术层面，忽略全局

因为技术管理者大多是从技术岗位上成长起来的，有时看问题难免会片面。典型的一个问题就是只关注技术层面，不看全局。比如外部的需求澄清、进度要求、服务支持等，这些都是非技术层面的，恰恰可能也是一线员工所不擅长的，所以更需要技术管理者来关注。

我的建议，技术管理者一定要先关注全局，然后再看细节。对于管理者的要求，更多的是要“做成事情”，而不再是技术骨干阶段的“做事情”。

总结

最后，我们来总结一下。

对于离职想表达的两个观点：

员工离职反应了个人发展与团队发展之间的矛盾；

员工离职是个必然结果，坦然接受，做出应对，而不是谈之色变，或避而不谈。

对于技术管理，这其实是个很大的话题，今天我们提炼一个重点：

技术管理者，一定要重点关注人，而不仅仅是事情。这一点是做技术骨干和技术管理者之间的最大差别，也是转变思路的第一步。

在技术管理上，你还有什么疑问，欢迎留言与我沟通讨论。

这里推荐一下我们隔壁的专栏《朱赟的技术管理课》，我订购后阅读了很多文章，产生了很强的共鸣，同时也收获到一些硅谷技术公司的先进管理经验，很有帮助。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

42 | 树立个人品牌意识：从背景调查谈谈职业口碑的重要性

求职者的背景调查是我去年频繁遇到的一个职场场景，经过仔细琢磨，我有了一些自己的感受和思考。同时，这也带给我一些启发，让我对自己后续的职场表现有了一些新的认知和调整。

我在这里分享出来，希望能对你有所帮助。

对求职者的背景调查

2017 年的时候，特别是年初和年中，我陆续接到了几家公司委托的第三方机构，对我所在团队的前成员，甚至是我上家公司团队的员工做非常详细的背景调查。

可能是因为与我相熟，有些公司的主管有时会直接联系我，对某些求职者在我们公司的表现和业绩情况进行了解。

而且这种了解不仅限于我，我团队中的部分员工因为工作年限较长，在同行业的圈子里彼此也非常熟络，所以也会有人直接联系这些员工了解更全面的信息。

背景调查对于关键岗位和高级别岗位，至少在互联网公司，已经成为了必须环节。而且越关键、越高端，背调审计就越严格。

不管来自哪一方面的背调，最终被咨询一方的意见，都有可能影响到求职者的面试结果。

第三方背调，一般都是在候选人经过层层选拔之后，在正式 Offer 发放前做的最后一项审核工作。所以如果在这个环节出现问题，眼睁睁和机会擦肩而过，就十分可惜。

而对于行业同行内的背调，一般会在面试前进行。所以当你参加面试时，面试官极有可能已经对你形成了初步印象和评价，面试过程就可能是这个初步印象的验证过程。

所以，面对这样的情况，我也会非常谨慎。我会尽量客观地给出我的评价标准，比如技术技能、沟通协作能力、态度表现，以及是否有比较突出的业绩贡献等等。

之所以提供这些信息，是为了让对方来判断候选人的自述是否符合真实情况，以便对方做出决策。

但是，两种情况下，我会比较旗帜鲜明地给出我个人的建议。

第一种，对于我认为特别优秀的，我会给出强烈推荐或者非常推荐的建议。

第二种，对于确实存在短板或较大自身问题的，我也会客观反馈，建议对方在候选人面试时或入职后，在管理上多加注意。

我之所以这样做是因为，别人来咨询我，是对我个人的信任，我既要客观不能夸大，也不能藏着掖着掩盖事实。同时，我也要给出更加真实的一手信息。当然，我在向别人求助时，也期望别人能以同样的方式来反馈我。

如何树立个人口碑

谈到这里，你可能会问，既然这个环节我们自己完全不可控，那我们又怎么能确保得到被咨询人正面客观的评价呢？

我的答案是：背调过程不可控，但是我们自身的表现却从来都是可控的。

也就是说，我们应该把注意力放到日常工作的表现上来，因为我们所有的评价依据都来自于此。

我们应该常常自问：我在工作中是否能做到积极主动，具备主人翁意识，敢于承担更多更大的责任？我在工作中是否能够不断取得成果，在团队中或跟团队一起作出较大的贡献，取得较大的业绩？

以我之前公司团队的一位同事为例。

这位同事是我们 Oracle 数据库的 DBA（数据库管理员），当时他入职的时候刚毕业一年多，经验一般，但是到了岗位上很快就融入了，经常会给我提出一些在数据库层面的优化改进建议。并且在我们评审通过之后，他会自己主动去落地执行。

在整个过程中，他跟其他团队成员配合得很好。出结果后，还会主动跟我一起去客户那里作汇报。久而久之，我对于他的工作很放心。后来我就放手让他自己去沟通，在他的协助下，我也减轻了一定的工作压力。

后来随着能力的成长，他基本承担起了 DB 的全部运维职责。他在岗的那两年左右，跟团队密切配合，在确保数据库没有出现过大故障的同时，还输出了很多提升性能和容量的优化案例。（要知道 Oracle 数据库的优化，能够带来的成本收益还是非常巨大的。如果你了解或维护过 Oracle，应该会深有体会。）

在与他共事的时间里，我们更多还是同事关系，但是相比其他人，我会对他抱以更多的信任。后来他转投去别的公司工作。

就在去年，我突然接到一个电话，对方是一家第三方背调公司，代表国内顶级的某支付公司，对他申请 DBA 技术专家岗位进行背景调查。

这时我脑海里涌现出的，都是他以往种种优秀的表现。所以背调问我的每一个问题，例如表现是否突出，工作态度和责任心如何等等，我除了实事求是地回答之外，还会特别用到“非常突出”“非常优秀”之类的赞扬之词。

这是比较突出的一个案例。其实绝大多数情况下，我们只要能够做到尽职尽责，态度认真，把精力投入到工作上，就不用对背调过于担心。

但是如果想要树立个人的好口碑，那就需要我们付出更多，要让团队和其他成员明确你独特的个人价值，就像我上面所讲的这位同事一样。

要引以为戒的反例

讲到这里，我也要举两个反例，这都是我在实际工作中遇到过的情况，请你引以为戒。

第一个，诚信问题，这是高压线，触碰不得。比如填写个人薪酬信息时，为了想获得更高的薪酬定价，故意捏造事实，肆意夸大之前的薪酬待遇。其实这些都是可以通过背调调查清楚的，如果存在造假，用人单位会直接拒绝。

我遇到的一个真实案例就是，候选人经过了终面，但当我们通知他最后一步背调完成，然后准备发放 Offer 时，他却反馈不准备接受 offer 了。

我们当然感觉比较可惜，但通过推荐人了解情况后，才得知他因为虚报薪酬太多，自己感觉心虚而不敢来了。

同样，在工作岗位上千万不要故意制造假数据，或者泄露工作信息谋取个人利益，这类错误触犯的后果将会更加严重。

第二个，消极怠工问题，这一点我认为是职业道德问题，是令人厌恶的。比如有的人在离职前的时间里，消极怠工，交接工作时不积极配合，经常迟到或早退，中途睡大觉或者跑出去不知所踪。

可能他认为反正要离职了，一切都无所谓了，也就不再重视个人行为是否妥帖，是否合乎公司规范，是否符合起码的职业道德和职业素养。

而这一行为恰恰会让团队其他人给他贴上“不负责任”“不靠谱”“职业素养欠缺”的负面标签。如此，他在将来背调时，可能就会因为这么简单的几个形容词，而被否定掉了，造成个人职业生涯莫大的遗憾。

当然，如果你因为意见和思路与团队或他人无法达成一致，而闹情绪，传播负能量，为团队协作制造障碍等等，这种消极表现也是不可取的。

共勉

在职场中，我们个人的职场信息和表现，就像我们的整个求学经历一样，会被详细地记录、跟踪和完善，这就更要求我们必须要学会树立我们的个人品牌，珍视自己的职场口碑。

而职场口碑的树立，关键还是来自于我们日常工作中一点一滴的表现，甚至是通过某些很细微的工作慢慢积累起来的，这是一个渐进的过程。

俗话说“千里之堤溃于蚁穴”，往往一不留神，因为一件负面的事情或行为，就会使你个人职场口碑和个人品牌瞬间坍塌。

所以，请守住职场底线，让我们共勉。

欢迎你留言与我讨论。

如果今天的内容对你有帮助，也欢迎你分享给身边的朋友，我们下期见！

划重点：赵成的运维体系管理课精华（一）

我们的专栏原计划共 36 期，在三个多月的时间里，收到了你的很多反馈，我也对应做了一些补充，所以我们的运维体系管理课算是拖堂了，一直更新了 42 期，至此告一段落。

从今天开始，我们按照专栏的四大模块，分三次来整体梳理一下。我从每一篇文章里选出一句最想告诉你的话，制作成知识卡，帮助你回顾文章内容，点击就可以一键直达原文。

我们专栏的四大模块分别是：

应用运维体系建设

效率和稳定性最佳实践

云计算时代的运维实践

个人成长

愿你已拥有不一样的运维思考！

应用运维体系

划重点：赵成的运维体系管理课精华（三）

今天我们来梳理专栏的另外两部分，“云计算时代的运维实践”和“个人成长”。我从每一篇文章里选出一句最想告诉你的话，制作成知识卡，帮助你回顾文章内容，点击就可以一键直达原文。

我们专栏的四大模块分别是：

应用运维体系建设

效率和稳定性最佳实践

云计算时代的运维实践

个人成长

愿你已拥有不一样的运维思考！

云计算时代的运维实践

个人成长

划重点：赵成的运维体系管理课精华（二）

今天我们来梳理第二模块“效率和稳定性最佳实践”。我从每一篇文章里选出一句最想告诉你的话，制作成知识卡，帮助你回顾文章内容，点击就可以一键直达原文。

我们专栏的四大模块分别是：

应用运维体系建设

效率和稳定性最佳实践

云计算时代的运维实践

个人成长

愿你已拥有不一样的运维思考！

效率和稳定性

新书 |《进化：运维技术变革与实践探索》

你好，我是赵成，久等了。

经过近 5 个月的打磨，《进化：运维技术变革与实践探索》这本书终于和你见面了。

这本书的内容主要来自我的专栏。当编辑告诉我专栏文章可以集结成书出版时，我才意识到，原来我已经不知不觉地输出了一个相对比较完整的运维体系，当时的感觉：一切都是水到渠成。

在专栏的基础上，我们对书的内容做了更加深度的修订。全书共十个章节，重新梳理了章节脉络使之更加清晰，让你能够更系统地阅读这本书。

书稿完成后，我邀请几位好朋友写推荐和序，他们写的内容反过来给了我很多启发。我在专栏的一篇文章里说过，我的很多看法也是和业界的很多专家多次沟通交流后形成的。在这里，我把优维科技 CEO 王津银老师给书写的序分享给你，我们一起听听他说的话，或许你和我一样，也会有很深的共鸣。

随着基础架构服务化越来越成熟，应用架构的服务化正走在路上，应用作为业务需求的第一载体也越来越重要了。什么是应用？为什么需要应用？有了应用，如何构成体系化的管理能力？作者的书恰恰在这些维度上给了我们详细的答案。

从纵向维度——独立以 Ops 的阶段来看应用，应用体系的构建也涉及很多方面。作者从标准化规范体系、组织变革、工具平台、自动化、意识等多个侧面做出了讲解，论述非常全面。从横向维度来说，应用生命周期跨越了研发、测试和运维等多个角色，这里面产生了一条重要的 IT 交付价值链，也就是今天 DevOps 里面讲的持续交付。说到持续交付，看似一个简单的工具链打通，却需要突破诸多障碍——组织上、工具上、文化上等。组织上来说，必须要打破部门墙，否则工具链肯定对接不上。工具平台能力要分解来看，涉及多个方面：项目管理、需求管理、环境管理、配置管理、部署管理、测试管理、监控管理、服务治理等，这些在作者的书中都给出了答案。这是非常难得的总结，是因为作者过去在研发、测试和运维上的综合经历，才能够给出这么一个体系化的指引。

本书还给了我一个更重要的启示，并且作者也一直是这样践行的——对于每一个运维人来说，在如今 IT 业务瞬息万变的环境下，我们更需要深度地思考、总结和分享交流，才能触达问题的本质。

希望你如我一样，能够从书中获取大量的养分，并反哺到你的工作中。让我们一起通过书中的文字来仔细体会作者的思想吧。

最后，开卷有益，期望这本书能够带给你不一样的运维思考，我们共同进步。

5 月 21～23 日首发，三天限时优惠。《进化：运维技术变革与实践探索》新书，原价￥59，现价￥49！你可以从发现页进入极客商城后进行购买。

结束语 | 学习的过程，多些耐心和脚踏实地

我的运维体系管理课专栏，已接近尾声，这是最后一篇，也是我们的结束语。

我打算分两部分来写，一部分来对我们的专栏学习做个总结，另一部分打算写一下专栏文章写作这件事情给我带来的改变，或者说我个人的一些收获。

专栏学习的总结

在学校的时候，曾经有一位历史老师讲过，历史书可以很厚，厚到将每一个历史事件和细节都记录下来，要用图书馆来保存这么多的文字内容；但是历史书也可以很薄，薄到用几句话，几段文字就可以描述，用人的脑子就可以记住，因为历史的发展规律总是相似的。

我想这条规律对于我们的学习也同样适用，学习也是一个从厚到薄的过程。起初我们对一个领域或行业不熟悉，这个时候要学习大量的知识，不断向别人请教。但是在这个过程中，随着我们自己的不断实践和思考，逐步总结提炼出一条条原则和经验，甚至形成自己独有的方法论，然后再通过这些原则和经验举一反三，指导我们来应对在这个领域中所遇到的各类问题。

我想我们专栏中所分享的内容，就是厚的那一部分。希望这个专栏可以给你一个指引，告诉你方向在哪里，应该从何做起，这样就不必在混沌中从头摸索；至于薄的那一部分，虽然在最后几篇文章中我们有一起复习，但是，更希望你能够亲自实践和参与，形成自己的总结。

这个过程，可以多一些耐心，多一些脚踏实地。

对专栏的总结，我借用 Bob 大叔（Robert C·Martin ）最新图书《简洁架构》（Clean Architecture）中的一句话，原文如下：

The goal of software architecture is to minimize the human resources required to bulid an maintain the required system.

翻译过来就是：

软件架构的目的，是将构建和维护所需的人力资源降到最低。

万变不离其宗，我们整个专栏的文章和内容，其实就是围绕着这句话展开的。从厚到薄的学习过程，我想用这句话来总结，再准确不过。

我在专栏写作中的收获

再来谈谈专栏写作给我带来的一些改变，或者说我从中的收获，期望对你也有帮助。

1.专注带来效率提升

当我发现有一件非常重要，且优先级非常高的事情摆在面前时，自然而然地就能意识到哪些事情是不重要的了，也不会再为要做哪些事情，不做哪些事情而反复纠结。

专栏写作对于我来说就是非常重要的事情。在一个相对较短的周期内，持续输出系统化的高质量文章，无论对我的时间，还是精力，都是极大的挑战。

所以，我索性将那些相对不重要的事情暂时放下，不让它们占用我的宝贵时间，消耗太多精力。比如，我大大减少了使用手机的时间，准确来讲是减少了各类社交软件，以及各类资讯软件的使用频率，在工作时间基本不去碰这些软件，高效完成工作。写作过程中就更加坚决，除非电话打过来，否则手机也不碰。

再比如，大大减少不必要的活动和会议。我有一个很简单的原则，就是超过 30 分钟的会议，我就拒绝，而是通过当面沟通的方式了解会议要讨论的内容，通常情况下，5~10 分钟就可以得出有效结论。所以凡事事先充分准备，也成为我这段时间提升效率的关键原则。

找到适合自己的节奏。我个人的习惯是早起早睡，所以我会将写作的时间安排在早上。晚上我一般会思考和策划输出内容的框架，这样第二天一早就可以专注地把内容写出来，在头脑最清醒的时候写作最高效。同时，避免周末不必要的活动和外出，大部分文章都是在周末集中输出的。

总之，当我全身心投入一件事情时，原来担心的精力不足，时间不够这些情况都没有发生，反而会觉得时间更加充足，对计划的掌控更加游刃有余。

2.总结回顾是最好最快的提升方式

我们常常认为不断地学习新知识，一定要跟得上这个时代的所有新热点，才不至于掉队，才会不断提升。保持这种对新知识的敏感，我认为是没有问题的。但我想表达的是，学习再多的新知识，如果不能学以致用，它们都只是停留在纸面的上的内容而已。所以，单纯地学习，并不能提升技能，丰富经验。

相反，对于自己正在做的事情，或者已经完成的事情，能够不断总结和反思，就能帮助我们完整地、体系化地获得提升。讲到这里，我分享下文章写作过程中的一个小细节，让我感受非常深刻，期望对你也有启发。

起初我在规划内容的时候，脑子里梳理出来的东西都是大的框架，比如持续交付部分，按照原计划写 4~5 篇文章。但是，当我真正开始写的时候，我非常详细地回顾了我们经历过的持续交付过程，把中间的建设过程，使用到的工具集，包括如何落地执行，以及如何与外部合作这些都仔仔细细地罗列出来，突然发现我之前罗列的条条框框仍然是很粗的，所以就重新细化分解，最终用更多的篇幅完整细致地详述了整个持续交付体系。

同时，这个过程中，因为要讲清楚一些细节，以及为什么要这样做，我会去翻阅和查询大量的资料，确保我自己的理解是深刻和正确的。同时，还要把以前我们为什么这样选型也重新梳理一遍，提炼出很多方案选型方面的原则。这个过程再次加深了我个人对一些原理和概念的理解，也让我自己对本来模糊或模棱两可的认知，有了更清晰的认识，对我来说也是更进一步。所谓教学相长，我觉得应该就是这个道理。

整个过程下来，我的感觉就是，如果没有这样详细的总结回顾过程，很多细节和有价值的信息就随时间的漂移而遗落了，而这些信息一旦遗落，我个人如果再经历类似的过程，可能还要重走弯路，也就谈不上什么进步了。

所以，在我们不断学习，接收新知识和新内容的同时，也不要忘了时常做一下总结和回顾。而总结和回顾的最好方式就是写作，希望你也可以逐步养成记录日志和博客的习惯，真的会受益匪浅。

最后，感谢你的阅读和反馈。一路相伴，我们共同成长。

希望你能够通过专栏的学习，更进一步！