那些没说出口的研发之痛,做与不做微服务的几大理由

创建一种新的软件项目架构,来封装离散服务,对于全新的项目来说,这是非常简单的。但是,对于大多数软件开发者来说,谁又有大把的奢侈时间一直用在全新项目上呢?

大多数软件开发人员职责更多是维护或增加现有软件系统的功能。但是,如果问开发人员究竟是愿意构建全新的项目,还是维护一个现有的系统,那么支持新项目的呼声肯定会成为压倒性的声音。事实上,希望与新技术或新项目合作也是开发人员离职的原因之一。为什么呢?

1

识别问题容易,但修复很难

维护现有系统时,很容易识别架构的问题。为什么?因为基于良好的架构,系统很容易调整。

当需要去调整一个没有设计封装波动的已有系统时,架构的弱点就不言自明。即使是最小的表层变化也会给整个系统的其他部分带来复杂的涟漪:新的依赖看似要无止境地延续下去,通过臃肿的方法签名获得更多的参数,自动化测试的规模和复杂性爆炸,同时降低了实际效用。

这些问题是不是听起来很熟悉?你企业的架构是这样的吗?

如果答案是肯定的,那么你有一个单体架构。单体架构是大多数软件开发者遇到的最常见架构。

这个单体架构来自那些根本没有设计封装波动的系统,但是随着业务需求和时间的推移,变得越来越复杂。

那么用单体架构做什么呢?

每个人在单体架构中工作时都会感到痛苦,开发和业务人员也是如此。开发者讨厌臃肿的单体架构,因为开发的难度会随着新开发动作的增加而增加。一旦单体架构达到临界值,如何改变会成为一个真正可怕的命题。这会导致生产力和团队士气下降,业务受到影响。企业需要快速行动,单体架构却会随着时间的推移而变得越来越慢。

许多开发人员都希望把已有的架构丢掉,重新开始,但是这种想法无法和业务一起成长。“最好的软件是目前就让企业赚钱的软件,无论设想中的新版本多么伟大!”

所以新的计划不能完全抛弃旧有的单体架构,业务要继续,但不会再增加单体架构的复杂度。

微服务?

微服务是一个流行的词汇,它模糊地表达了一个面向服务的架构,其中包含许多小的离散服务。

从表面上看,微服务似乎是单体架构的对立面(每个人都讨厌单体架构),许多微服务通过提出新的特性请求,并以独立服务的形式出现。这里的问题是:当单体架构封装所有系统的波动性,解耦的独立服务并不能使企业免于任何波动。

以下是用微服务实现单个功能架构,它大概像这个样子:

单体应用变得小了一点,新功能清晰地从系统的其余部分解耦。这很好吗?

当下一个功能请求进入时会发生什么?

有两个功能,我们已经看到一个问题。第二个功能建立在第一个功能之上,所以不能完全隔离。

如果随着功能请求的进入,简单地创建新的微服务,而不是封装整个波动区域:

有改善吗?来看看原始单体应用旁边的微服务:

如果仔细观察,会发现,所有服务依赖线模糊在一起,这只是发明了一个更复杂的单体架构。

小小的改变在整个系统中仍然会带来复杂的涟漪。整个系统的行为改变将涉及到改变多个微服务。所有相同的问题再次出现,甚至可能更糟糕,这加剧了依赖关系难以追踪的事实,而且,精心策划的多服务部署比庞大的单体应用更加可怕。

什么地方出了错?

问题源于微服务本身不是架构。微服务就是一个简单的词,描述了作为独立服务运行的系统,而不是一个单体应用。软件架构的实际实践包括仔细规划,在哪里划分离散服务之间的界限,从而包含波动区域。当简单地拿出一个单体应用,作为独立服务来实施时,就没有必要来考虑整个系统的封装波动。

把系统看作一个整体,才能谈架构

因此,如果单体应用,功能驱动的微服务太小,该怎么做应对?

要知道想去的方向

要像从头开始创建一样,为整个系统设计理想的架构。

企业不能一下子从一个单体架构直接进入微服务架构,但是如果第一次启动的时候,不清楚想达成的方向,那么永远也不会到达那里。

给所有希望拆分现有单体应用的软件开发者提供一些建议,但实际情况是这个路线图对于每个系统都是独一无二的。

Tips

如果只是设计新的功能而忽略已有的单体应用,则无法创建出色的架构;

如果不考虑整个系统,单体应用就不能有效分解;

微服务只是一个流行词。更小并不总是更好。精心拆分服务边界很重要;

2

微服务与团队:康威定律

微服务架构是独特的,随着时间的推移仍然保持灵活性,在一个项目的组织架构中时时发生影响 。对于大多公司而言,这非常具有挑战性,因为它要求企业重新考虑组织模式。当准备开始微服务架构时,可以先问自己:“企业的组织能力是什么?“在早期,先决条件应该是预先准备会遇到的困难,并思考应对之策。

微服务与康威定律:企业需要与团队协同的架构

当涉及到组织团队和微服务,著名的康威定律经常被提到。这项定律,越来越被广泛地接受。

这一定律的缺陷在于,它更多是一种社会学规律,而不是纯粹的科学规律,事实上,它总是以实证、实例的方式,而不是纯粹的科学逻辑来论证。一般来说,社会学的结果很难证明,因为这些论证很大程度上基于假想中的思考和概念,只能通过更多的实例来加以验证。

“组织的系统设计…往往受限于组织架构的产品设计和通信的副本。”从这个规律,可以得出一些简单的结论:

如果想要特定的结构,需要一个与组织团队协同的架构。

如果经常改变架构,组织团队也需要经常修改。

这两个断言,对于康威定律的原则,有着深远的影响。首先是一个企业的适应能力,避免了野心家的倾向,对变革的抵制等等,也引发了机器取代人力的哲学思考。

基于以上结论,要上微服务架构的第一个问题是:“组织团队如何适应这种架构?” Netflix 和亚马逊的情况,当然是很正向的,但是否你的企业是否准备好了?其中重要的是,挖掘技巧和发现问题时的“刹车”措施来规避风险。

其中的技巧能迅速提升团队的能力。在创建一个功能时,负责功能实现的团队汇集了很多不同的技巧。当架构进入微服务模式时,将出现更多的协调性需求。

另一个窍门是开源技术的治理模式。开源项目由于其分散的结构,使它能够创建高度松耦合的软件,这是微服务架构的优点之一。它因此成为与其他团队的协作方式,并推动具有代码能力的小团队,在代码中实现变化。

但是,这个逻辑和组织变革在公司的接受度如何?这些技巧是否足够在全公司范围内协调、积累经验和知识?分散的组织构建松耦合的代码,但技术或功能性的知识和技能不可能极端的解耦。否则,这就像拆东墙补西墙,是在用拆掉的墙来构建松耦合的架构。

真正的僵局会出现在文化和管理风格上,这点在最近几年有了好转。

一个比较好的例子是Spotify的框架(虽然我们应该限制自己使用meta frameworks,原因不再赘述)。Spotify采用通过使用开源组件来架构功能和治理,使用这些工具在一定规模下实现了灵活性矩阵模型。矩阵式组织必须确保知晓不同人具备的知识或技能。

最近流行的新管理方法已初见影响,特别是在那些寻求实现微服务的团队组织中。

Holacracy管理模式:满足业务模式前提下,完成微服务最佳实践

上面谈到了企业文化、主体、和变革的阻力。第一种类型的管理,来源于 Holacracy 管理模式。

Holacracy分为自治和独立,并链接比自己更高的实体。这些圈子以闭环的形式,可以互相重叠,具有自组织而被上层管理的特殊性。每个圈子对于性质和组成的变化非常敏感。

可以想象,例如,底层圈子是微服务的开发队伍,而上一层是架构和产品负责人,最顶端是应用的客户业务线。这将让产品和架构负责人要能在满足业务需求的前提下,才能保证架构的最佳实践。

这种架构方式也是开发者、软件架构师的典型方式。所有可能来自不同或重叠的圈子组织。建立这种类型的组织是为了提高知识传输和构建架构的时间效率。

我们可能会认为,这种管理比较符合传统的层级组织。事实上,即使层次是扁平的,它仍然存在,可以限制其项目团队。总之,最好的方式就是简化人与人之间的链接。

原文链接:

1、Microservices and monoliths: getting service-oriented architectures just right

https://www.tuicool.com/articles/VBzUFfJ

2、Executive Insights on the Current and Future State of Microservices

https://www.tuicool.com/articles/RfuAJn2

http://blog.shurenyun.com/na-xie-mei-shuo-chu-kou-de-yan-fa-zhi-tong-zuo-yu-bu-zuo-wei-fu-wu-de-ji-da-li-you/

实录分享|微服务落地践行渐进,4个Q&A一窥金融微服务现状

1月13日,中国双态运维用户大会在北京举办。来自银行、保险、证券、政府、央企等多个行业的330多位企业用户参加,其中工商银行信息科技部副总经理张艳,国泰君安信息技术部总经理俞枫、海关总署科技发展司运行安全处处长张芳、平安科技系统运营部总经理陈亚殊等分别发表了演讲。本文为数人云CEO王璞在双态运维用户大会DevOps、容器与微服务分论坛上的演讲实录。演讲结束,与在座金融客户展开了精彩的Q&A分享。

容器、微服务、DevOps三者,业内的共识是密不可分。没有微服务,DevOps落地不下去,没有容器,DevOps也无法真正实现敏捷运维、自动化运维。DevOps、容器、微服务为更好的构建PaaS提供了方法论和技术手段。

1、PaaS之承上启下

PaaS作为云计算的承上启下要素,向上支撑各环境应用,向下跟IaaS、计算环境、计算资源对接,是企业云化的必由之路。

PaaS三大技术趋势

1.应用容器化,容器正在成为云计算原生应用的标准交付方式。

2.微服务网格化,随着企业对微服务的认知越来越深入,下一代微服务着重把应用管理作为核心。因为企业应用一定要有很强的管理在微服务架构上,不能让应用去“裸奔”。数人云没有提微服务化,因为微服务化已经是不争的事实。应用微服务缺乏强大的管理,需要服务网格这样的下一代微服务技术。

3.行业生态化,PaaS技术本质上是支持应用的,应用跟业务紧密结合,所以PaaS最终是要和业务层面融合,行业需要生态化。

PaaS落地三大要素:

PaaS要在企业客户方面落地不可或缺三要素:规模化、统一化、标准化。企业客户落地云计算平台、技术,本质上是希望提高效率,对业务有更好的敏捷支撑。

所有应用,比如容器应用、微服务应用,都实现标准化。标准化以后进行统一化管理,包括部署、发布、故障恢复、监控告警等都实现统一化管理。最后实现模块化,整个系统都是轻量的,微小模块化的。只有基于这三点的PaaS平台和云计算平台,才能够让IT系统真正实现敏捷轻量,提高IT对业务支撑的效果。

2、企业IT架构转型之开发&运维

企业客户目前在架构转型应用中面临的现状是,企业里大量传统应用,客户希望先实现轻量的单体架构,即摆脱很多中间件,摆脱外部服务,MVC架构、单体复杂架构等首先实现轻量化。

数人云日常接触的客户中,走的比较靠前的客户已经在用Spring Cloud、Dubbo等架构,部分客户相当数量的应用已经微服务化,不过处于中间状态,正在考虑评估微服务架构的客户比例还是最大。总之,企业目前的现状是为服务应用、轻量单体应用,以及传统的巨石应用并存。

在架构转型过程中,正确和常态的路径一定是一步步走过来,而不是传统架构丢掉直接上微服务。

DevOps和容器@轻量单体应用架构

在单体应用架构下,DevOps、容器帮助企业实现敏捷IT。首先,持续集成持续交付CI/CD,只要应用是相对轻量的,就能加快中间件应用。CI/CD其中重要的一点是变更发布管理。

数人云某客户上了容器的应用都是轻量化的,基于 Tomcat 和微服务的应用。当基于容器实现快速发布以后,企业发现,所有发布里有一半的发布失败是由于配置不正确引起的。所以,如果没有发布变更管理,发布失败的中间环节有方方面面的因素。

当基于容器实现快速发布之后,容器对环境的异构做了一层屏蔽,这时如果出现处理的问题就是配置管理的问题了,由于涉及不同的环境和应用,配置环境变成应用发布很容易出错的环节。

DevOps和容器@微服务应用架构

数人云做了企业客户微服务落地状况的调研(微服务2017年度报告出炉:4大客户画像,15%传统企业已领跑),在报告中,有15%左右的企业引入了Spring Cloud、Dubbo。微服务在企业里首当其冲的是敏捷开发,因为微服务是一种切实的敏捷开发的方法。

敏捷开发在IT界已经推广多年,但很多时候敏捷开发推的都是方法论,比如Scrum。微服务是一套切实能够落地到IT人员、开发人员开发过程中的实践方法,这是微服务首当其冲的好处,很多企业的开发部门对微服务非常欢迎。不过,15%还是偏小的一个采用比例,微服务还不是企业客户主流的IT架构。

开发人员都比较欢迎微服务,因为能够提升开发效率,落地敏捷开发,但微服务的阻碍还是不小的,微服务对开发运维来说,带来的复杂度急剧上升。传统运维管理的服务器数量、应用数量有限。企业决定采用微服务本身就表明业务很复杂,单体应用做传统的瀑布式开发效率太低,微服务将应用拆分成较小的模块,因此微服务应用一旦上线,程序的数量呈现爆炸式增长。

例如,数人云某个传统企业的客户,目前部署了微服务相关的应用,基于Spring Cloud、Spring Boot,跑在几千个容器上,几千个容器如果通过传统运维方式去管理的话几乎是不可能的。这就是很多微服务无法落地的原因——很多企业客户缺乏相应的运维能力,没有相应的平台、工具、方式、方法管理微服务应用。

微服务落地的必要条件

微服务应用落地,首当其冲是配套工具链的完善。开发人员采用微服务的影响相对改变小一些。采用SpringCloud或者Dubbo、gRPC等,只是开发框架上的并更。其他开发流程如代码托管、代码审查、测试等并不涉及,所以开发流程相对简单。但微服务对运维功能的要求就会复杂,相应的快速配置能力、完备的监控能力、快速部署能力等对传统运维来说都是缺失的,容器能够补足这方面的能力,让运维部门具有DevOps的能力。

关于微服务的拆分,其实是业务部门需要真正解决的问题。微服务对组织上也有变更,将团队化整为零。通常每个单独的微服务程序都由7-10人的小团队来负责维护,这些都是微服务落地的必要条件。

对于数人云来说,直接能够给客户提供的帮助,首先是工具链方面,数人云产品层面具备丰富的微服务配套工具链,从监控、日志、调度、故障自动化修复等等都有完备的工具链。在落地方法上,数人云搭建了自己的生态圈,和很多合作伙伴合作,例如跟埃森哲公司在合作,帮助企业客户落地微服务,进行业务的梳理。

容器和微服务共生

容器技术补齐了微服务相关的工具链,对企业全面向云计算转型提供了很大帮助。应用架构是微服务分布式的,相应的运维也要有自动化、敏捷运维的能力。微服务跑在容器上才能发挥它最好的特性。容器是目前最流行的应用环境,基于容器的微服务部署和更新更快,更轻量,服务之间的调用、服务发现、负载均衡等更灵活。

不过,微服务不是万能的。简单的业务场景单体应用其实足够,微服务一定是应用在复杂的业务场景下,只有复杂的业务场景才有很大的维护成本、维护压力,微服务是用来降低复杂业务场景的维护成本。

基于容器云的微服务运行时管理体系

一个完整的微服务管理体系,除了开发框架之外,对运维部门来说,运维微服务应用最基本的路由、负载均衡等功能,容器可以提供,不过容器提供的只是一部分跟微服务相关的能力和工具链。周围还有一大批需要配套的工具,比如配置管理、API网关、注册发现、应用监控等等。这里的监控不是容器CPU内存的监控,而是业务逻辑的监控,更准确一点是全链路跟踪的全链路监控。容器满足了微服务运行时管理的需求,不过周边许多权限、网关、配置等尚无余力满足。

统一配置中心是微服务体系的核心

统一配置管理,是微服务落地时很核心的点。要在平台工具上落地微服务首先要具备快速配置能力,因为客户采用微服务和容器平台以后,很快会发现50%以上的发布失败是因为配置没搞对,因此配置管理是微服务里首当其冲的问题。

因为每个企业客户都有开发环境、测试环境、生产环境等很多环境,同一个应用不同版本在不同环境下的配置不同。几何级数的配置项、配置元素的增长会导致配置管理的复杂度急剧上升,需要统一的配置中心进行管理。数人云在帮助企业客户落地微服务时,首先会做的是把配置搞定,没有灵活快速的配置管理能力,微服务运行不起来。

变更发布管理(灰度发布 v.s. 蓝绿部署)

在发布管理方面,数人云帮助企业落地的发布管理主要是蓝绿部署,因为很多企业的应用本身不支持灰度发布。蓝绿部署也是切切实实的快速发布,发布用变更窗口的方式来实现。

例如,周五晚上12点起进行发布变更,12点就要停服务中心。蓝绿部署可以显著地缩短服务不可用的变更窗口。怎么做呢?客户在线上有两个版本,蓝版本和绿版本。现在负载均衡器将流量指向对外提供服务的绿版本,蓝版本作为备用的方案。同时,新程序往蓝版本上部署推送,更新时只需要把流量切换到蓝版本。发布流程最后简化为只需要进行流量的切换。流量可以快速切换,中间的窗口期只有短短几分钟,如果流量切换过来一切正常发布即完成,如果流量切换过来发现问题,可以再将流量切回去。这样开发人员、运维人员不必当场熬夜去修复,极大地减轻了发布的压力。

传统发布方式下,每次变更窗口有好几个应用排队发布,一个应用发布完成后才可以发布下一个应用,一旦中间某一个应用发布失败现场修复的压力非常大,短短的发布窗口需要几个小时内完成抢修,非常不可控,团队经常需要晚上熬夜排队。而结果往往等了半天,前面的应用没发布成功,后面的还得继续排队等。

3、金融行业之践行渐进

数人云在金融、能源、制造、快消、政企等行业的基础上,继续深耕强监管、强安全,高复杂度的金融行业。以某商业银行为例,数人云帮助落地了大规模微服务容器平台。该商业银行近年来互联网业务发展迅猛,原有系统架构无法支撑其未来规划。2016年6月开始全面实施应用微服务化,已实现蓝绿发布。

首先,营销系统全部是轻量化的应用,基于Spring Boot、Tomcat、SpringCloud等,跑在容器平台上。该银行对外营销频次非常高,通过线上微信公众号、手机APP、线上门户、合作伙伴等渠道,每月对外营销达上百场。

每次营销活动或多或少都对IT系统有变更,哪怕是配置变更,因此每次营销活动对IT系统都是一次不小的挑战。发布的时候仅仅靠容器是不够的,需要实现模板的批量发布。每次发布看起来只是一个个的容器程序,实则不然,其实是一组组一批批的容器,只有帮客户做到批量的应用发布,才能显著提升发布效率。

蓝绿部署方面,该银行密集的线上营销中,每一天会有一个重点营销活动,那么营销活动的流量如何分到特别的人群、区域?在后台应用的上千个实例中,并不是每一个实例都分配同等的流量,要通过流量分发,做线上流量控制。数人云借鉴Google做灰度发布的方式为客户提供图形化的流量控制,这和微服务实施后的限流分流是息息相关的。

另外,该银行客户的数据流量非常大,对日志收集带来非常大的的压力。数人云建议客户将应用程序的日志全部交给Kafka采集,Kafka可以做到很大数据流量的分布式消息应用。

分布式数据传输分布式消息应用很难保证每一个消息都可靠地传递。Kafka有两种模式:一种保证消息传递至少一次,但也可能多次,对很大的日志量来说偶尔丢一两条可以忽略不计。Kafka的并发量很大,可能带来偶尔很小的数据量丢失,也可能带来日志的乱序,这在分布式系统下都是可以容忍的,“鱼和熊掌不可兼得”。

关于快速建立支撑微服务体系,数人云有几点总结:

1.开发框架不能用重量级的应用体系,要么是轻量化单体架构的Tomcat等,要么采用Spring Cloud等微服务架构。

2.要有微服务平台,具备快速配置管理能力、部署能力、监控能力、应用管理能力等配套管理能力。很多企业的痛点是,开发人员快速学习微服务开发技术,基于Spring Cloud做业务系统后,业务系统无法上线,因为运维部门缺乏配套的工具、平台支撑微服务线上运行管理。

3.DevOps融合,平台管理需要把链条全打通,实现快速发布、快速上线、自动修复等。容器经过几年的普及企业已经相对了解,但容器本身是纯技术平台,基于容器、DevOps的落地还有很长的路要走。

数人云微服务On PaaS 产品体系

数人云现在的重点是微服务、轻量单体应用。以前数人云帮企业客户落地重应用的容器平台,但后来发现价值不大,反而对企业来说,除了维护重的应用外还需要维护容器,容器平台并不能实现自动化运维。经过几年的实践和摸索,数人云跟企业客户达成的共识是,传统应用不经过改造无法上到云PaaS平台。

轻量架构下的应用如何基于PaaS平台支撑?以敏捷开发为例,企业客户通常选择 Spring Cloud、gRPC 等主流的开发框架,然后在微服务工具链层面配置监控、报警、部署、快速发布等方方面面的能力,最下面承载的则是容器平台。

数人云现在还可以帮助客户落地服务网格化技术。它能够进行异构架构的兼容,gRPC就是服务网格的一部分,Google推的 Istio,Linkerd的Kubernetes 都支持 gRPC,gRPC成为通讯协议的一部分。基于通讯协议相应周边的管理,在服务网格这一层可以做灰度发布、A/B测试、流量控制、高级熔断、加密、白/黑名单机制、权限访问控制等等。

服务网格被称作下一代的微服务,因为用了服务网格以后,所有微服务管理的诉求都自动化地满足了。80%-90%的应用管理需求都在服务网格里自动涵盖。这对开发人员来讲,微服务开发的门槛急剧降低,不需要考虑未来应用上线时流量控制、灰度发布等等,只需要考虑业务。数人云微服务On PaaS 目的就是帮助企业客户降低微服务架构、上云转型的门槛。

Q&A

Q1:感觉对DevOps的理解不太到位,能不能具体地讲一下? 
A1:DevOps准确来讲,现在业内还没有统一的认识。互联网公司的DevOps目前是比较统一的,比如Goolge,但是互联网公司的DevOps,我个人理解没办法在企业直接落地。

在Google,程序员不止要负责应用的开发,还要负责相应的测试,单元测试、集成测试等等。另外,应用的部署、发布、上线也是开发人员自己做。所以互联网公司讲DevOps,更多讲的是开发运维的融合。我之前在Google时,不仅要做代码开发,也要把测试的代码全写出来。

Google有一个理念,开发人员每写一行业务代码,测试代码要写十行。然后,开发人员利用各种发布平台定期发布,比如每周做发布,在Google 运维的人员叫“SRE”。SRE部门准备好各种平台,开发人员可以用这些平台做发布、监控、日志管理等工作。

Google目前有三万名左右的IT人员,其中SRE的运维人员只有一千多,比例很低。所以在Google运维人员不可能帮每一个开发人员或者业务部门做上线。像传统IT开发人员提工单给运维,在Google是不可能的。Google这种做法,它让开发做更多的事情,运维人员很少,只是负责维护平台。所以,Google一千多人管理着几百万台服务器,平均每人管两千台。

但传统企业目前不是这样,传统企业开发和运维之间壁垒比较大。数人云帮助客户落地DevOps 时,基于的理念是,不要破坏现有开发的流程。DevOps应该是开发和运维深度融合才能做到的。讲DevOps,首先要讲理念、组织的变革,但是要想把文化变革、组织变革打破要很长时间。

从落地的角度,DevOps更多落地在运维部门,很具象的工作就是,帮助运维部门去实现DevOps的能力,比如快速部署、快速上线,应用的快速配置,自动化管理能力、故障的自动化处理等等。把以前的运维工作尽可能的自动化,提高效率,这是狭义的DevOps理念,也是我们现在接触到的。数人云不会帮客户落地像互联网公司那样的DevOps,开发做很多事情,运维可做的很少,并不是这样的。

Q&A

Q2:微服务适合复杂的场景,那么一个简单的促销是不是适合?微服务有多“微”呢?微服务和ESB 服务相比,有什么差别? 
A2:第一个促销场景,促销场景本身有些条件,促销很重要一点就是必须特别频繁,促销内容在平台要发生变化。比如,今天的促销内容和明天的不太一样,或者这周的促销和下周的不太一样,业务平台需要频繁变更,这时候微服务是适合的。

因为微服务是一种敏捷开发的落地实践方法,只要业务频繁变更,对开发的要求就必须敏捷开发,快速实现。所以,只要业务场景在不停地快速变化,促销又是互联网线上的方式,肯定是适合的。

关于复杂性,如果业务逻辑简单,逻辑变化少,并不适合微服务。比如数人云和很多银行客户合作,银行核心系统很复杂,但是银行系统并不是需求频繁变化的场景。很多银行在做“瘦核心系统”,就是银行核心系统的功能越来越单一,越来越瘦,并不是把复杂的周边的业务也放到银行核心系统里。银行核心系统虽然复杂,但业务不会频繁变化,也不一定要上到微服务场景下。复杂的业务系统,业务需求又不停变化,这种场景适合微服务。

第二个问题是和ESB 比,服务网格和 ESB 有很多相像的地方。ESB有业务逻辑串起来,很多不同的业务系统都上到ESB,互相的权限通过ESB打通。从功能角度讲,ESB和服务网格之间很相像,不同点在于ESB是传统架构下的,并没有考虑频繁迭代、流量集中爆发等问题。

但是微服务情况下,整个之间的互相请求、依赖、通讯等等都会进行统一的管理,这种情况下也很像ESB把不同业务之间的流量进行统一管理,但是服务网格更看重的是面向大规模的控制,那流量突发怎么做限流,或者突然故障怎么做熔断等等。最本质的问题是类似的,但是具体的问题表象和需求不同。 Q&A

Q3:在实际部署过程中,PaaS平台在底层资源的调用一定要用分布式云架构,传统主机是否可以?两者在最后效果上有没有什么异同? 
A3:数人云当初两种情况都有,有些场景比如业务量比较大,企业客户为了减少复杂度,容器PaaS平台直接落地到物理服务器上。还有客户为了方便管理,把PaaS落地到IaaS上,两种情况都有。

这其中的考虑是,首先业务量大如果再引入虚拟化这一层会引来额外的复杂度,此时用物理服务器更好。其次,客户有很大规模的物理服务器,直接在上面部署PaaS,在物理服务器上去调用。

第三种,资源动态的调整或资源频繁调配,这个场景很常见,需要IaaS。比如银行客户,内部业务系统分不同的域,不同域的业务复杂性随时间变化经常会发生变化,需要不停地做资源动态的调整。如果用物理机太麻烦,企业客户会选择下面有一层IaaS来做。

基于PaaS也能做一部分的资源动态调配,但是调配维度不同。数人云帮客户落地PaaS时会做资源的整合。从划分的维度,PaaS平台是按照应用程序来划分,IaaS的资源划分是按照业务系统。

Q&A

Q4:微服务重新开发,最佳的开发框架或者实践有什么可以分享的?第二,旧有的系统改造到微服务这块有没有什么经验?第三,DevOps以前也有很多像敏捷开发的方法论,它们之间有没有什么关系? 
A4:首先第一个问题,微服务的开发框架。企业客户在做选择时都希望降低风险,选最主流的框架,现在看最主流的开发框架就是Spring cloud,这也是业界的自然选择结果。其他语言也都有些微服务开发,但是用的人少一些。如果是Java应用,目前比较好的选择是Spring Cloud,也有很多客户用了Dubbo,其他架构都是偏小众的架构,主要还是看客户自己的需求。

第二个问题,传统业务要转到微服务架构上,一定要循序渐进。比如Java应用,首先Java中间件的应用,先脱掉,不要再基于这么重的Java中间件。目前相对流行的是Spring Boot这套逻辑。

有了轻量的单体化应用之后(基于Tomcat),往后走基于微服务的框架,上到Spring Boot,再上到Spring Cloud,这是比较平滑的方式。Spring Boot 在很企业客户中用的非常多,是很方便的一套单体开发架构。

企业客户目前的现状是老的应用很多,不会一次就改造完,传统的应用可以先选择一部分容易转的转到轻量单体架构上,然后再转到微服务框架上。目前企业客户是轻量的单体架构、微服务架构,以及大量传统的架构应用并存。老的架构应用目前上不到PaaS平台,只有轻量的单体化加微服务应用才能上到PaaS平台。

现在业内的共识是,微服务、容器、DevOps这三者是密不可分的。微服务更多是针对开发人员,是一种真正落地的云开发方法。很多企业客户也讲敏捷开发,派团队成员学习敏捷开发的方法论,但是敏捷开发仍然无法在企业当中落地。

这是因为,只学会了方法,但没办法落地到具体的编程,即开发环节上去,自然没办法做到敏捷开发。很多开发者回来写的程序依然是J2EE。J2EE 编程的理念和方法并不是敏捷开发的,是偏向于瀑布式的。

微服务是具体的开发环节上的敏捷开发方法,开发能力化整为零,每个团队做简单、具象、单一的逻辑。微服务首先是一个具像的敏捷开发方法,实践方法。

微服务在落地时,比如程序运行时,复杂度很高,因为不是一个程序,是一批程序一起运行,对运维的管理就比较复杂,这时候可以利用容器实现微服务应用的自动化管理。微服务一般都会上到容器,因为微服务应用不再是单体的部署方式,不再是部署到Java中间件上。基于微服务架构,几百个进程进来,用容器的方式实现快速部署动态调度,微服务部署到容器上,实现基础的轻量化运维。

轻量化运维,快速部署、自动化调度,逐步往DevOps方向走。DevOps更多强调自动化的运维能力,提高运维的效率,快速部署,出了问题自动化修复。需要用到工具和平台,这就是数人云现在帮客户去做的。

把微服务业务在运行时缺失的管理方式方法、工具平台,工具链补齐。首先是配置管理能力、完备的监控能力等等,普及之后运维人员就有能力来管微服务应用。这其实是DevOps里面最狭义的,让运维的能力变得轻量。

如果要真正实现DevOps,就像目前一些互联网公司做到的,开发和运维真正的深度融合在一起。企业目前的运维一般不具有编程能力,所以真正的DevOps还需要很长时间去落地。

HTTP直播HTTP Live Streaming (HLS)

增加EXT-X-MEDIA-SEQUENCE或EXT-X 
      -DISCONTINUITY-SEQUENCE标签的值(第6.2.2节)。

      添加或删除EXT-X-STREAM-INF标签或EXT-XI-FRAME-STREAM-INF 
      标签(第6.2.4节)。请注意,客户端不需要
      重新加载主播放列表文件,因此更改它们可能不会
      立即生效。

      将EXT-X-ENDLIST标记添加到播放列表(第6.2.1节)。

   此外,播放列表文件可以包含EXT-X-PLAYLIST-TYPE标记
   ,其值为EVENT或VOD。如果标签存在且
   值为EVENT,则服务器不得更改或删除任何部分
   播放列表文件(尽管它可以向其添加行)。如果标签
   存在且值为VOD,则播放列表文件不得更改。

   播放列表中的每个媒体片段都必须应用EXTINF标记,以
   指示媒体片段的持续时间。

   媒体播放列表中的每个片段都具有整数不连续
   序列号。
   除了媒体内的时间戳之外,还可以使用不连续序列号来
   跨不同的再现来同步媒体段。Pantos&May将于2014年10月16日到期[第23页]

 
Internet-Draft HTTP Live Streaming 2014年4月

 
   段的不连续序列号是EXT-X 
   -DISCONTINUITY-SEQUENCE标记的值(如果没有,则为零)加上
   URI行之前的播放列表中的EXT-X-DISCONTINUITY标记的数量
   细分市场。

   包含EXT-X-PLAYLIST-TYPE标记的媒体播放列表,其
   值为EVENT或VOD,不得包含EXT-X-DISCONTINUITY- 
   SEQUENCE标记。

   服务器可以
   通过对其应用EXT-X-PROGRAM-DATE-TIME标记将绝对日期和时间与媒体段相关联。这
   定义了(挂钟)日期和时间的信息映射
   由标签指定给段中的第一媒体时间戳,
   其可以用作寻找,显示或用于其他
   目的的基础。如果服务器提供此映射,它应该将
   EXT-X-PROGRAM-DATE-TIME 
   标记应用于应用了EXT-X-DISCONTINUITY标记的每个段。

   如果媒体播放列表包含
   演示文稿的最终媒体段,则播放列表文件必须包含EXT-X-ENDLIST 
   标记。

   如果媒体播放列表不包含EXT-X-ENDLIST标记,则
   服务器必须使新版本的播放列表文件可用,
   其中包含至少一个新媒体段。它必须可用
   相对于以前版本的播放列表文件
   可用的时间:不早于该时间
   之后的目标持续时间的一半,并且不晚于该时间
   之后的目标持续时间的1.5倍。

   如果服务器希望删除整个演示文稿,则必须使
   播放列表文件对客户端不可用。它应该确保
   播放列表文件中的所有媒体段
   至少在删除时播放列表文件的持续时间内仍然可供客户端使用。

6.2.2。现场播放列表

   服务器可以通过
   从播放列表文件中删除媒体段来限制媒体段的可用性(第6.2.1节)。如果
   要删除媒体段,播放列表文件必须只包含
   一个EXT-X-MEDIA-SEQUENCE标记。对于
   从播放列表文件中删除的每个媒体段,其值必须递增1 。

   媒体片段必须按照
   它们在播放列表中出现的顺序从播放列表文件中删除。

   如果
   播放列表文件的持续时间减去段的持续时间
   小于目标持续时间的三倍,则服务器不得从播放列表文件中删除媒体段。

Pantos&May将于2014年10月16日到期[第24页]
 
Internet-Draft HTTP Live Streaming 2014年4月

 
   当服务器从播放列表中删除媒体段时,
   相应的媒体URI应该对客户端保持可用
   的时间段,该时间段等于段的持续时间加上
   分发的最长播放列表文件的持续时间。包含
   该段的服务器。

   如果服务器希望从
   包含EXT-X-DISCONTINUITY标签的媒体播放列表中删除段,则播放列表必须包含
   EXT-X-DISCONTINUITY-SEQUENCE标记。

   如果服务器从媒体
   播放列表中删除EXT-X-DISCONTINUITY标记,它必须增加EXT-X-DISCONTINUITY-的值 –
   SEQUENCE标记,以便
   仍然在播放列表中的段的不连续序列号保持不变。

   如果服务器计划在
   通过HTTP 将媒体段传递给客户端后将其删除,则应该确保HTTP响应包含
   反映计划生存时间的Expires标头。

   实时播放列表不得包含EXT-X-PLAYLIST-TYPE标记。

如何使用FFmpeg连接两个MP4文件

我正在尝试用ffmpeg连接3个MP4文件。我需要这是一个自动的过程,因此我选择了ffmpeg。我正在将这3个文件转换成.ts文件,然后将它们连接起来,然后尝试对连接的.ts文件进行编码。这些文件是H 264和AAC编码的,我希望尽可能保持质量不变或接近原版。

FFmpeg有三种级联方法。

1.级联视频滤波器

ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \ -filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" \ -map "[v]" -map "[a]" output.mkv

请注意,此方法执行重新编码。

2.凹式破碎机

$ cat mylist.txt
file '/path/to/file1' 
file '/path/to/file2' 
file '/path/to/file3' 
$ ffmpeg -f concat -i mylist.txt -c copy output

Windows操作系统:

(echo file ../../../../1.mp4 & echo file ../../../../2.mp4 )>%tmp%/list.txt
ffmpeg -safe 0 -f concat -i %tmp%/list.txt -c copy c:/output.mp4

3.COAT协议

ffmpeg -i "concat:input1|input2" -codec copy output

该方法不适用于许多格式,包括MP4,因为这些格式的性质以及该方法执行的简单级联。

该用哪一个

  • 级联滤波器:如果输入没有相同的参数(宽度、高度等),或者格式/编解码不相同,或者要执行任何筛选,则使用。
  • 凹式破碎机:当想避免重新编码并且你的格式不支持文件级连接时使用(一般用户使用的大多数文件不支持文件级连接)。
  • COAT协议:使用支持文件级连接的格式(MPEG-1,MPEG-2 PS,DV).不要与MP4一起使用。

如果有疑问,可以试试减刑演示程序。

安装Composer PHP Warning: copy(): SSL operation failed with code 1.

报错信息

[root@localhost ~]# php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" PHP Warning:  copy(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in Command line code on line 1 Warning: copy(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in Command line code on line 1 PHP Warning:  copy(): Failed to enable crypto in Command line code on line 1 Warning: copy(): Failed to enable crypto in Command line code on line 1 PHP Warning:  copy(https://install.phpcomposer.com/installer): failed to open stream: operation failed in Command line code on line 1 Warning: copy(https://install.phpcomposer.com/installer): failed to open stream: operation failed in Command line code on line 1

解决方法

  • 应该是CA证书验证失败造成的错误,下载个CA证书
[root@localhost ~]# wget http://curl.haxx.se/ca/cacert.pem [root@localhost ~]# mv cacert.pem /usr/local/openssl/ssl/certs/cacert.pem [root@localhost ~]# vim /yourpath/php.ini
  • 修改cafile路径,保存
[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context ; option.
;openssl.cafile=
openssl.cafile=/usr/local/openssl/ssl/certs/cacert.pem

使用nginx配置多个php-fastcgi负载均衡

配置还是非常简单的,充分体现了nginx的强大与配置的简单。

应用的最前端是一台nginx服务器,所有静态的内容都由nginx来处理,而将所有php的 请求都分摊到下游的若干台

运行PHP fastcgi守护进程的服务器中,这样可以以一种廉价的方案来实现对系统负载的分摊,扩展系统的负载能力。

三台php-fastcgi服务器的ip地址分别为:

          172.16.236.110 ,   172.16.236.111,     172.16.236.112

运行php-fastcgi进程时,需要让php-cgi监听到服务器的局域网地址(分别如上所示),而不是之前一般都是监听的

本地地址(127.0.0.1)。

以 172.16.236.110这台服务器为例:

 
/usr/local/php5/bin/php-cgi -b 172.16.236.110:9000

或许你用spawn-fcgi来启动php-fcgi,那么就是这样(供参考,其实也就是修改监听的地址和端口即可):

 
/usr/local/lighttpd/bin/spawn-fcgi -f /usr/local/php5/bin/php-cgi -a 172.16.236.110 -p 9000

又或许你是用php-fpm来管理php-fcgi,那么你需要修改php-fpm的配置:

 
vim  /usr/local/php5/etc/php-fpm.conf

找到这个配置项(其中的地址可能需要根据你自己环境来调整)



<value< span=”” style=”word-wrap: break-word;”> name=”listen_address“>127.0.0.1:9000>

修改为:

<value< span=”” style=”word-wrap: break-word;”> name=”listen_address>172.16.236.110:9000>



修改完毕后,重启你的php-fpm进程。

然后按照上面的步骤,依次修改其他php fastcgi服务器。

php方面的工作暂时就是这些,下面修改nginx。

 
vim  /usr/local/nginx/conf/nginx.conf

在配置文件的http段内增加类似如下的配置:

1
2
3
4
5
upstream myfastcgi { server 172.16.236.110 weight=1; server 172.16.236.111 weight=1; server 172.16.236.112 weight=1; }

我这里三台php fastcgi服务器的权重是相同的,所以其中的weight值都是1,如果你的php fastcgi服务器需要分主次,那么

可以通过调整其weight值来达到目的。比如以第一台服务器为主,其他两台为辅,则就是这样:

1
2
3
4
5
upstream myfastcgi { server 172.16.236.110 weight=1; server 172.16.236.111 weight=2; server 172.16.236.112 weight=2; }

然后找到原来nginx关于php fastcgi配置的部分,比如:

1
2
3
4
5
6
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }

将其中的fastcgi_pass那一段改为:



fastcgi_pass myfastcgi;

其中的myfastcgi也就是上面刚刚配置的php fastcgi均衡器的名字了。

完了以后,重启nginx即可。

简单吧,就通过这么几个简单的配置,就可以实现一个经济高效的nginx、多php-fcgi的负载均衡解决方案了。

当然了,这样的方案运用到实际项目中 还需要进行一些细化的配置,主要是php方面还需要进一步配置

Google的DevOps理念及实践(上)

SRE(Site Reliability Engineering)是最早由Google提出,又经由Google发展完善的一个崭新运维理念。如今SRE已成为一个涵盖运维理念、思路、组织架构和具体实践的完整体系。数人云推出SRE系列教程,由SRE经验丰富的技术大牛们为大家分享运维一线的独家干货,揭示SRE背后的秘密。

今天为系列教程第一期,我们邀请了前Google SRE、《SRE Google运维解密》的译者孙宇聪与大家进行了线上分享。本文为上篇,讲述了SRE的基本概念和核心原理。与孙老师本人一样风趣幽默的文章,小数希望大家阅读愉快:)

今天与大家分享的内容是关于最近我翻译的这本书,据说反响还不错,今天借这个机会聊一聊书中的内容,并与大家分享一下我回国两年多以来,Google经验在国内的一些思考和落地实践。

什么是SRE?

很多时候国内把DevOps的范围定得有点狭窄, DevOps这件事情在国外更多是整个行业内的一个趋势。DevOps是一种模式,主要是让IT相关的东西与商业结合得更紧密一些,迭代速度变得更快一些,所以它适用于各个行业。今天说的SRE,我认为也是在运维行业上的一部分。

概括来说,我认为《SRE Google运维解密》这本书是一个文集。GoogleSRE全球一千多人,这个组织在公司里相对比较小众,但又是一个比较重要的部门,整个Google所有业务线的运维环境都由SRE来负责。SRE是一个非常分散的组织,每个业务线、每个部门其实都有自己的SRE小团队。这本书里共有一百多个作者联合写成,其中也包括我以前所在的团队,我们做过的一些Project也在书中也有提到,所以它是一本文集。我与原著的三个编辑聊天时,他们说成书最大的难处就是删减内容,当时征集来的内容大概有一千多页,最后删到了五百多页。这也是这本书比较有意思的一个花絮。

回到这本书的宗旨, SRE到底是什么?SRE是Google发明的一个词语或者新定义的一个职业。以前这个运维角色,大家叫运维,美国叫Operation。现在Google把这个职位扩展为SRE,就是用软件工程师的方法和手段,招了一些软件工程师来解决运维的难题,这是SRE的官方定义。

传统运维模式的弱点

现在传统的计算机行业的运维方式,大部分都是采用系统管理员的模式。大家最熟悉的运维方式是这样:招聘一些系统管理员,他们有负责采购机器的,有负责维护数据中心的,也有专门维护数据库的等等。系统管理员模式有几个特点,他们只是把一些现成的组件组装起来,并不会自己开发和创造新的系统,比如拿了MySQL把它跑起来,或是研发部门开发出来的新代码组装成之后提供这样一个服务。这是运维部门的一个特色,负责把这个东西运行好。

举一个例子,在美国的时候我们经常自嘲,说自己是流水线上的工人。因为这个流水线实际上是别人设计出来的,总得有人去操作这个机器,而我们就是一线的操作流水线的工人。又比如,我们好像是发电站里的工作人员,又或者是飞机驾驶员。飞机驾驶员就是开别人造出来的飞机,这和运维部门的职责很像。

那么这样一个运维部门的职责包括哪些呢?首先最重要的是应急事件的处理,这是重中之重,也是最唯一的职责。其次是常规更新,现在的业务发展越来越快,每周都有新的东西上线,比如说今天要买新机器,明天要改IP地址,大家可能80%的投入都是在这些事上,这就是系统管理员或者是现在运维行业的工作模式。

但是系统管理员模式有一个最大的弊端,按照传统的组织架构模式或者是这种运维模式运行会导致这个团队持续扩张,业务越来越多,需要不停的招人去应付各种各样的事。刚开始接手生产的时候,也许一周就出一次事或者是需要更新一次。因为人的沟通能力总是有限的,招了五个人之后,这五个人之间的传达问题就形成了一个困难。当你把一个精神传达给这五个人,他们事后执行出来的结果都不一样,这就是传统模型一直想要解决的问题。但是这种模型也有好处,就是市场招聘比较容易。

Google有几个比较重要的特点,首先它的部署规模非常大。Google到今天已经十八年了,刚开始前几年公司所有的人平时写代码,周末去机房接机器。因为它扩展速度特别快,部署规模非常大。如果按照传统的系统管理员的那种模式操作,这个机柜归你,这个机柜归他,再下一个归另外一个人,那么Google招人的速度一定赶不上机器增加的速度,所以Google是被逼迫创造了这样的职位,因为没有办法安排团队做如此大规模的运维。

传统的运维模式还有一个更大的问题,它过于强调专业化。比如一个人是做网络的,他只做网络其他都不管,全公司可能只有他懂网络,因为他不停的在网络上投入时间,集中力气把这个事情做好。这样一个结果就是会发现运维部门没人能休假,一出事只有一个人能解决问题。不仅仅是网络,特殊硬件、一些第三方服务都存在这个问题。这就导致了知识没法共享,人灵活性受到限制,整个组织的灵活性也受限制。这个问题,我认为它最终形成了一个负反馈的循环,每个人之间越是互相隔离,越是没有办法提高,导致服务质量上不去。最大的问题是,招来更多的人其实也不解决问题,因为这个部署规模不断扩大,人之间的知识不能共享,所以招来的人只能运维新的设备,旧的设备还是这些人在做。

这是一个怪圈。回国之后我与很多公司的朋友都聊过这个问题。以前大家讲Oracle这样的公司存在老DBA,说老DBA都是难得一见的,深居简出,但是你有什么问题,只有他能解决,其实这在Google这个语境里这是一个比较不健康的状态。SRE的一大特点就是想请假的时候随时请假,每一个人都可以请假;当出现紧急情况的时候,当天值班的人真的可以处理他负责的这个服务所有的问题。

Google SRE的起源与特点

回到最开始,Google SRE的VP叫Ben Treynor,他是一个资深的软件开发经理。2003年他加入公司第一个任务,是组建一个7人的“生产运维小组”。很快他发现如果想把这件事情做好,也就是把搜索服务运维好的话,按照Google机器增加的速度,传统的模式绝对是不可能的。机器增加的速度,系统复杂度增加的速度远比人增加的速度要多得多。所以他组建的团队有以下三个特点,注意,这里我认为其实更多的是事后的总结。首先,他的执行方式是像组建一个研发团队一样来组建这个运维团队。他招了很多他熟悉的研发工程师,这些研发工程师从开发能力上没有任何问题,用现在流行的话就是全栈工程师,什么都会做。第二点,这些人对系统管理比较有热情,懂一些Linux内核知识、网络层的知识。第三点,最关键的是这些人鄙视重复性劳动,码农最痛恨的是什么事,就是反复做同一件事。他把这些人聚到一块,然后让他们执行以前传统公司运维人员来做的事情,很自然这些人不愿意手动干,于是就写程序干。多快好省,同时写程序还有一个好处,就是可以把一些最佳实践、方式、流程、方法都固化成代码,用这种方式去应对规模性的扩张,去应对复杂度的上升。

这些是SRE跟传统的运维模式最不同的一点,就是招的人研发为主,做的事也是以研发为主。这是当时SRE成立背后的故事,这些年来我认为他们做得最好的一点是一直在维持了一种平衡。将运维部门从传统执行部门往上提升,打破了传统的界限。就像刚才说的DevOps,很多人理解为就是让研发部门做运维的事,或者运维部门做研发的事情,但实际上DevOps在国外的定义更宽泛一点。DevOps的思想更多的是说把整个开发流程的界限打通,产品有的时候也要干一些研发的事,研发有时候把这个信息要很快的反馈给这个产品,开发和运维或者QA和运维之间的界限也打通。所以现在去搜DevOps的图片,会发现IBM这些人都在讲圈圈,说以前是产品研发都是一条线直着来,而现在都是转圈的,这就是DevOps理论。

按照这个理论来说,SRE就是DevOps的思想在开发和运维之间的一个平衡。

SRE的工作职责

这个图是我发明的,书中没有提到。书里大概有二十多章的内容是在讲SRE的各种日常工作,简单提了一下它的金字塔模型,于是我归纳总结了一下。这里是由下至上,下面的事份额比较大一点,上面的事份额比较小一点,分了三类。第一类,运维部门最重要的是应急响应这个问题,因为业务越来越大,与运营的结合越来越紧密,很多时候要处理的事情更多的是商业和运营上的事,也包括软件上的问题,这个部门最特殊或者最唯一的职责就是应急响应。之上是日常运维,保证机器能够正常更新、快速迭代。再往上是输出一些工程研发,无论是做工具,还是做高可用架构、提高可靠性,这些都是最上层的东西,只有把底下全部做好了才能说到上面。

应急响应

应急响应是运维部门在公司最独特的一点,表现为当公司出现问题时,应该找谁或者流程应该是怎样的。我回国之后见了不少初创企业,他们网站出问题了,往往是CEO先发现,CEO打电话“哎,这个到底是怎么回事啊”,然后每一个人都说“不知道啊,不是我负责呀,我得找谁谁”。不管多大一件事都得传遍整个公司,整个效率非常混乱。

我在Google待了八年时间,这样的流程也经历过,但是最近这几年Google非常重视这一点,建立了一整套应急事件处理方式。首先要有全面监控,监控这件事情是持久不断的,重中之重。SRE所有人都要非常了解整个监控系统在所有业务中的部署实施,其实这是我们平时花精力最多的地方。监控系统里面对整个系统所有方面都有监控,不光包括业务指标,也包括性能指标、效率指标。监控应该平台化、系统化,不停的往上积累,多做一些模板,同质化的系统就可以用同样的方法去做监控。

第二点是应急事务处理,应急事务处理分两部分,第一部分是演习,另外一部分是真正的处理流程。如何把它做好?实际上就是要不停的去演习、去做这个事情。像刚才举的例子,网站挂了,首先不应该CEO先发现,而应该是监控系统或者报警系统先告警,在发现之前就很应该明确这个东西应该谁排查,谁处理,这个信息应该早就发给合适的人去处理,甚至他应该早就在做了。如果发生特别大的,需要跨部门之间协作的问题,那不应该只是领导现场调配,而是整个组织每个人都明白这个流程应该是怎么样的,直接就做。Google甚至可以做到在一次事故中间两地交班,某个团队处理一半,然后我交接给另外一边团队,就下班回家了,持续不停的有人继续跟踪处理这件事情,而不会出现问题。这样一个模式是我觉得非常值得我们思考的。

处理完问题之后,要总结。之前听过的一个故事是,某公司业务出现了一个事故,大家加班加点,十几个小时没睡觉把这事搞定,然后领导过来就说了一句“大家辛苦了,回家睡觉吧”。但是,其实在这个时候我要说,领导光说这个其实恰恰是不够的。领导在这里应该问:为什么加班啊?这个事情为什么会发生啊,下次能不能不发生,大家能不能不加班,能不能不熬夜?这样才对, 能做到事后总结这个事情很难,但只有把这个做好了,才能降低以后问题发生的几率。

日常运维

日常运维做得最多的可能是变更管理。业务现在发展非常快,迭代速度、迭代周期非常快。其实这件事情能做好,能够做到无缝、安全、不停的变更管理,是运维部门能给公司做的最大贡献。

第二个,容量规划,当规模大到一定程度的时候,就需要有人来回答这个问题——到底要买多少新机器,能否保证明年的性能、效率,那谁来负责这件事呢?SRE部门提出这些方案,然后要确保这些指标、这些东西是有数据支撑的,确实能解决问题的。

工程研发

工程研发虽然做得少,但是工作很关键。SRE在工程研发上主要的工作,首先是帮产品部门确定一个SLO。SLO是一个服务指标,每一个产品都有一个服务指标。任何系统都不可能是百分之百可靠的,也没有必要做到百分之百可靠。这里得有一个目标,比如说可以每个月中断几分钟。这件事情是要产品部门考虑清楚的。比如我之前在YouTube做视频存储、视频点播的时候,要考虑每个视频到底是存一份还是存两份的问题,将这种问题放到一个非常大的部署规模里面的时候,只有产品部门能够拍板。说到底是要不要花这个预算,要不要花这么多钱去提高0.1%的可靠性或者0.01%的可靠性。

另外一点是无人化运维。大家都看过《黑客帝国》吧?一醒来发现大家都是电池,都是为机器服务的。其实把这个比喻放在运维部门非常合适。因为如果不停的开发出需要人来操作运维的系统,结果大家最后都是电池,明显是不可持续的。如果不停的产生这种需要人来操作的东西,不停的招人,最后就变成不停的运维这个东西。把整个流程自动化,建立一个能够应对复杂业务的平台,这就是工程研发上最需要的东西。

SRE模型成功的关键要素

SRE在Google有十几年的历史了。这个模型是如何成功的?我总结如下几点:

职业化

运维行业从来都说不清楚自己是干嘛的,这是不对的。很多人认为会操作Linux,或者是DBA、会配网络,就算运维了。实际上运维的范围要比这个大得多。运维应该是负责公司业务正常运转的角色,这才是真正的运维。在出问题的时候能解决问题,保障业务连续性,甚至避免问题发生,这才是运维职业的定义。

具体如何做呢?推演和演习。

推演是给你一套系统,你要分析出来它会有什么样的失败模式。我们当时经常在黑板上画系统图,大家一起讨论如果这个组件出问题了会发生什么情况,用户到底还能不能看视频了,用户购买流程还能不能走通。实际上这些过程很多时候软件开发是不考虑的,但是如何拆分、如何去保证每个环节的可靠,这才反是运维这个行业最关键的一点,所以一定要做这种推演。只有这种推演才能输出改变,让系统更可靠。

第二点是演习。我们当时每周都会进行一次小型灾难演习,例如把以前出现的问题拿出来一个,让新加入团队的人去演习,所有其他的人也都要去参加。这里主要是观察新人到底是怎么思考这个系统的,新人做出的决定到底是不是正确的。因为一个人做出的决定是不是正确的实际上取决于系统给的反馈到底是不是对的。Google认为运维复杂系统不是一个靠智商和记忆力就能解决的问题,不能依赖人一定要知道这段话或这个知识点,而是要知道一种方法,知道如何去排除问题或排查问题。运维系统应该提供足够的信息,让轮值的人能够用正确的方法去处理问题。这很像是背英语辞典和会用英语聊天的区别,你再怎么背辞典关键时刻也是要查辞典的,但是真正能运用这些信息解决问题,是比较难的。

此外,要区分责任和指责。责任和指责是两个事情,但是很多公司的运维经常分不清楚。什么叫责任,就是这个事到底谁负责。但是指责是另外一回事。例如一个员工敲错了一个命令,大家说 “都是因为他的错,给他扣工资、扣奖金,让他三天不吃饭”,但这其实并不真正解决问题。再例如,比如说一个系统设计电源插座,没有仔细考虑,很容易被人踢到,结果有人真踢到了,整个机房断电了出了很大的事故。那么从Google的理念来说这里不是人的问题,而是系统设计的问题。这里是不是应该有两套电源,是不是应该有保护?只有从系统设计问题的角度出发才能真正解决问题,而指责这个踢到插座的人,让他一个月不上班,甚至当时开除也并不能解决系统的设计问题,下回总会还有人踢到。

说一个故事,故事的内容是一个事故。某个数据中心有一排机器要断电,数据中心的人发了一个工单告诉操作员要把这个开关给关了。然后这个操作员去关,他关掉了开关,但是发现这一排机器的灯没灭,另外一排的灯却灭了——按错开关了。他检查一下发现按错了,“啪”把另外一个开关也关了,然后再把这一排机器给启动,结果由于启动时候过载导致整个数据中心都断电了,扩大了问题。如果单纯只是指责,这个人肯定完了,起码奖金没有了,能不能保证工作都不知道。但是Google 更关注的是这个东西为什么会容易出错,要么是开关颜色不对,要么是相同机器的操作方式靠得太近了,会让人产生这种错误的判断。所以你看Google的机房里都是五颜六色的,因为这样确实有用,比如热水管是红色的,制冷管是蓝色的,所以查起来很容易,区分起来很容易,尽量减少了这个问题。这个设计的思想在SRE日常工作里贯彻得非常深,每人在流程或工作的时候都要考虑到有没有被误用的可能,然后如何避免误用。

专业化

专业化体现在什么程度呢?要真正的去写代码,要能给业务系统或者给研发写的东西挑出问题,提高可靠性。

第一,减少琐事。运维中有很多虚假的工作。每天很忙,然而又不解决问题,做了很多假的工作。大家看起来好像很忙,一个屏幕上十几个窗口,各种刷屏,但完全不解决问题。更好的方式是用自动化、系统化、工具化的方式去消除这种琐事的存在。如果永远靠人工,那永远都闲不下来。

第二,回到SRE,SRE制度里有一条红线,运维的人只能把一半的时间花在运维上,另外一半的时间必须搞工程上、研发上的东西。研发可以是写工具,可以是参与系统设计,参与可靠性的提高,但是要保证运维不能只干运维。

第三点,我认为也是比较缺少的,运维部门光有责任没有决策权,所以大家都说一出事故,运维就背黑锅。怎么不背黑锅呢?说改这儿、改那儿,然后发现没有人批准改动,这是最大的问题。SRE做的最好的一点是管理层对SRE的工作方式非常认可、非常支持,他们认为服务质量是服务的一个重要指标。一旦上升到这个高度,SRE部门提出一些要求就比较容易理解,得到支持,因为他们是有事实根据的。当GoogleSRE发现生产出现问题的时候,标准的解决办法就是暂停所有更新,确保业务稳定。举个比较极端的例子,像刚才说的如果发现线上系统有问题的情况下,SRE是有权利拒绝接受业务更新的,只允许研发部门修bug,不允许加新功能。这个争议我在过去八年见过为数不多的几次,开发可以一直闹到 VP,SVP 这个级别。每一次都是听SRE的。

打通与产品团队的反馈回路

所有东西不都是百分之百稳定的,稳定性的提高要消耗成本,要增加更多的冗余,更多的容量,甚至只能花钱解决。运维部门的任务就是提供这些数据和方案。比如搞三个9、四个9,要如何达到,这在投入和系统设计上有很大区别。这个部分公司里没有其他人可以提出,必须要由运维部门提出。如果没有这个反馈回路的话,你会发现大家都很痛苦,很多时候做出的决定都是违背自然规律的。我看过很多这样的案例,上面拍脑门决定某个业务要100%稳定,完全不管下面怎么搞,由于反馈回路不存在或者这个反馈回路的信息流动不够顺畅,导致了这个东西最终实际做不好,这是SRE模型相当关键的一个地方。

UDP Jitter测试

UDP Jitter测试是以UDP报文为承载,通过记录在报文中的时间戳信息来统计时延、抖动、单向丢包的一种测试方法。Jitter(抖动时间)是指相邻两个报文的接收时间间隔减去这两个报文的发送时间间隔的差值。

图1 UDP Jitter测试原理图 

图1所示,UDP Jitter测试的过程如下:

  1. 源端(ME60A)向目的端(ME60B)发送数据包。发送时,在报文中记录时间戳t1。

  2. 目的端(ME60B)收到报文后,在报文中记录时间戳t1’。

  3. 目的端(ME60B)将收到的报文发回到源端,在报文中记录时间戳t2’。

  4. 源端(ME60A)收到报文,在报文中记录时间戳t2。

从源端接收到的信息中计算出:

  • 数据包从源端到目的端和从目的端到源端的最大抖动时间、最小抖动时间及平均抖动时间。

  • 从目的端到源端或从源端到目的端的最大单向延时。

从而清晰的反映出网络状况。

双向时延:RTT=(t2-t1)-(t2′- t1’)

当双向时延>用户配置的超时时间时,表示网络不畅通。此时,报文将被统计为丢包。

丢包率=丢包个数/发送报文总数

UDP Jitter测试可以测试2个方向的抖动(Jitter)值:

  • SD(源到目的)方向:Jitter=(t3’-t1’)-(t3-t1)

    计算出来的结果,如果大于0,则统计为正向抖动值;如果小于0,则统计为负向抖动值。

  • DS(目的到源)方向:Jitter=(t4-t2)-(t4’-t2’)

    计算出来的结果,如果大于0,则统计为正向抖动值;如果小于0,则统计为负向抖动值。

UDP Jitter测试例还支持统计单向丢包。

图2 UDP Jitter测试统计单向丢包原理图 

图2所示,在Server(ME60B)端会统计收到报文的个数,当Client(ME60A)端口收到的报文个数与从报文中获取的Server(ME60B)端收到报文的个数不同时,会自动发起单向丢包查询,获取Server(ME60B)端接收报文的个数:

Packet Loss SD是源到目的的丢包

Packet Loss SD=Client(ME60A)端发送的报文个数-Server(ME60B)接收报文个数

Packet Loss DS是目的到源的丢包

Packet Loss DS=Server(ME60B)接收报文的个数-Client(ME60A)接收报文的个数

Client(ME60A)端收不到查询报文时,会将丢包记录到Packet Loss Unknown。

php连接mysql是否应该使用存储过程以及优劣势和使用场景

利弊是相对的,使用存储过程来实现不一定是什么“滔天大罪”,这完全取决于系统的规模,扩展性以及产品的发展方向。
通常情况来说,把业务逻辑写到存储过程中不利于系统分层设计和维护,更不利于数据库的迁移(当然没有谁总想着换个数据库玩儿玩儿),这么做的原因很可能是他认为可以提高性能(存储过程的性能确实优于SQL访问的性能),不过为了解决性能问题有很多种方案,这种方式可能会差一些。

先说一下优劣势,再说一下使用场景吧

1、存储过程的优势

(1)、减少连接数

(2)、调用相对程序方比较简单,由DB管理员加,程序方只是需要传递参数即可

(3)、方便DBA查看

2.使用存储过程的劣势

(1)、程序极大耦合,业务一旦更改,需要都进行更改

(2)、牵扯到复杂计算的情况下,需要数据库进行运算,而数据库的优势是存取,循环等逻辑判断服务的情况是数据库的一个硬伤

(3)、调试困难,无法知道运行sql的情况,尤其是数据库有专门DBA的情况

(4)、主从分离的情况无法使用

(5)、无法适应数据库的切割(水平或垂直切割)。数据库切割之后,存储过程并不清楚数据存储在哪个数据库中。

3、使用场景

存储过程只是适用在php和mysql都是同一个人管理的不太进行业务变更的小网站上。稍微复杂一点的网站并不适合存储过程

公司开发定的数据库MYSQL规范

我们公司相当多的项目用的是mysql数据库,但是大家在开发过程中对mysql的认识问题,往往在数据库设计时对字段的定义不一致,在开发时对sql语句的执行出现问题,特地把一些通用性的、值得注意的问题做一下总结
一、数据库的设计规范
1、必须使用InnoDB存储引擎
原因:支持事务安全、行级锁、并发性能更好(查询不加锁,完全不影响查询),内存缓存页优化使得资源利用率更高,mysql5.6版本开始支持 全文索引
2、必须使用utf-8的字符编码
原因:这个无需过多解释,和网站以及其他系统完全统一,避免转码带来不必要的麻烦,而且系统数据接口都是使用json格式。
3、数据库、表、字段名必须有意义并且必须加入中文注释
原因:避免自己遗忘,方便他人进行开发,要不然一段时间之后谁还知道这是用来干什么的
4、禁止使用存储过程、视图、触发器
原因:高并发大数据的互联网业务,架构设计思路是“解放数据库CPU,将计算转移到服务层”,并发量大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现“增机器就加性能”。数据库擅长存储与索引,计算还是使用程序来实现。使用存储过程等非常难于进行调试和测试。
5、禁止存储文件和图片
原因:存储路径在速度和空间方面会有更好的提升
6、数据库中表的数量不能高于500
原因:做好前期设计,尽量把一些相关度低的表进行分库处理
7、库名、表名、字段名的命名规则
所有的名字都使用小写并且间隔使用下划线风格,不超过32个字符,必须要见名知意,尽量使用英文,但是绝对禁止拼音英文混用命名。
 二、表的设计规则
8、表中的字段数不能超过30
原因:如果字段过多,就要把一些不常用的字段进行分表处理
9、表明和索引名统一
例如:表名table_xxx,非唯一索引名index_xxx,唯一索引名unique_xxx
10、所有表必须至少有一个主键,例如自增主键
原因:
a)主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用
b)主键要选择较短的数据类型, Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率
c) 无主键的表删除,在row模式的主从架构,会导致备库夯住
11、禁止使用外键,如果要有外键完整性约束,必须使用程序进行控制
原因:外键会导致表之间耦合度增加,update与delete操作都会涉及相关联的表,非常影响sql 的性能,甚至会造成死锁。高并发情况下非常影响数据库性能,大数据高并发业务场景数据库使用以性能优先
三、字段的设计规范
12、所有字段都要定义为NOT NULL并提供默认值
原因:
1)null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化
2)null 这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多
3)null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识
4)对null 的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符号。如:where name!=’shenjian’,如果存在name为null值的记录,查询结果就不会包含name为null值的记录
13、在多字段的表中禁止使用TEXT、BLOB类型
原因:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能
14、使用整数禁止使用小数存储货币
原因:价格乘以100来使用整数存储,小数在运算过程中会导致钱对不上
15、手机号必须使用varchar(20)进行存储
原因:
1)涉及到国家代号,可能出现类似+86
2)手机号会去做数学运算么?不会,所以不要使用int(11)
3)varchar可以支持模糊查询,例如:like“138%”
16、禁止使用ENUM,可使用TINYINT代替
原因:
1)增加新的ENUM值要做DDL操作
2)ENUM的内部实际存储就是整数,你以为自己定义的是字符串?
四、索引的设计规范
17、表中索引的数量最好控制在5个以内
原因:
1)、索引也占用很大的空间
2)、索引在创建修改数据的情况需要大量更新索引
18、一个索引关联的字段在5个以内
原因:字段超过5个时,实际已经起不到有效过滤数据的作用了
19、禁止在更新十分频繁、或者区分度不高的属性上建立索引
原因:
1)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能
2)“性别”这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似
20、建立组合索引,必须把区分度高的字段放在前面
解读:能够更加有效的过滤数据
五、sql优化
21、禁止使用SELECT *,只获取必要的字段,需要显示说明列属性
原因:
1)读取不需要的列会增加CPU、IO、NET消耗
2)不能有效的利用覆盖索引
3)使用SELECT *容易在增加或者删除字段后出现程序BUG
22、禁止使用INSERT INTO t_xxx VALUES(yyy),必须显示指定插入的列属性
原因:容易在增加或者删除字段后出现程序BUG
23、禁止使用属性隐式转换
原因:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引,
where 条件语句里,字段属性和赋给的条件,当数据类型不一样,这时候是没法直接比较的,需要进行一致转换,这种情况是无法使用索引的。
24、禁止在WHERE条件的属性上使用函数或者表达式
原因:SELECT uid FROM t_user WHERE from_unixtime(day)>=’2017-02-15′ 会导致全表扫描,而不能使用索引
正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp(‘2017-02-15 00:00:00’)
25、禁止负向查询,以及%开头的模糊查询
解读:
a)负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描,而不使用索引
b)%开头的模糊查询,同样会导致全表扫描,不能使用索引
26、禁止在大表中使用JOIN查询,禁止大表使用子查询
解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能
27、禁止使用OR条件,都改为IN查询
原因:旧版本Mysql的OR查询是不能命中索引的,即使新版能命中索引,为何要让数据库耗费更多的CPU呢?

28、应用程序必须捕获SQL异常的功能,并有相应处理

http://www.architecy.com/archives/456