大家好,我是来自普元的叶婉婷。今天由我来和中生代技术的朋友分享一下流程微服务的自动化测试。首先,我给大家分享一下普元多年实践的自动化测试过程与方法;阐述一下我们的测试理念:测试一切、测试驱动开发、测试自动化;1)测试一切文档、配置、环境、发布包,一切皆代码,这个很好理解,我不再赘述;2)测试驱动开发测试提前,敏捷协作,测试用例同步开发;3)测试自动化多种测试技术能力、组件化开发、统一管理,不间断测试执行;为了实现测试驱动开发、测试自动化,我们认为需要以下四个要素:1)敏捷协作的过程;2)测试设计方法;3)全栈测试团队;4)自动化测试服务;普元多年来在产品研发过程中,一直践行敏捷协作的RDT过程,在新一代云平台项目中,我们分为若干RDT小团队,每个团队负责一个或多个领域系统,以实现不同的用户场景;在每个RDT小团队中,采用需求、开发、测试协同并行工作模式;随着产品需要在公有云上部署运维,我们做了一些改进,运维组参与分析用户场景、需求设计测试评审、反馈运维遇到的问题,而且,运维组自身也作为RDT团队直接负责统一监控中心的需求定义和设计开发;那么为什么在敏捷协作的过程中,就能将测试尽量提前呢?从上面过程中我们可以看到,在计划阶段,每个RDT团队对用户场景都有了统一认识,那么在接下来的每个迭代开发中,定义需求规格、设计概念模型/原型界面/API定义/数据模型的同时,测试可以并行进行测试对象分析、测试点分析、测试数据和测试组件设计,并且强调RDT的相互评审;基于这些成果,开发进行编码的同时,测试就可以并行进行测试用例的开发,并且测试用例开始不间断的执行,自动化测试相比传统开发过程大大提前,通过测试尽量提前达到测试驱动开发的目标;自动化测试毕竟不同于手工用例,我们从四个方面定义了自动化测试的设计原则与方法:1)易管理性统一规划、统一版本控制的规范要求;2)易实现性采用分层设计,测试基础服务层、测试能力支撑层、测试组件层、测试用例 层,支持多种技术的测试能力,测试组件复用,用例专注业务逻辑;3)易维护性组件与用例分离、区分变化与不变、测试用例原则上不互相依赖、测试数据 容易维护;4)易定位性测试用例独立、低复杂度、要求断言信息的准确性;自动化测试分层设计对测试团队提出了更高的要求,也就是要求我们必须成为全栈测试团队,具备各层的能力:测试架构师负责总体设计、测试基础服务层,提供统一管理、统一调度的能力;领域技术专家负责测试能力支撑层,对各领域测试技术进行分析和选型,提供测试服务能力以及基础的技术组件;测试专家负责指导测试开发工程师进行测试方案设计、测试组件和用例的实现;除了过程、方法、团队,自动化测试的落地最终还是需要依赖各种自动化测试服务的实现,我们也一直在做这方面的努力,并形成了产品化的自动化测试服务能力;除测试基础服务以外,我们没有选择从零开始,而是评估并引入好的开源技术和公司内部其他产品的可用技术,按照我们的自动化测试设计原则和方法进行相应的改造;比如WebUI测试服务,我们选用了Selenium,为了适应我们的用例开发规范和易用性,我们对其接口进行了重新封装,形成我们的WebUI基础组件库;比如CI工具Jenkins1.x,由于我们产品多、每个产品版本也多,使用时间久了之后其任务管理界面简直就是灾难,任务的调用关系也非常不直观、难以维护,所以我们扩展实现了持续集成项目管理、图形化的持续集成任务流管理,以适应我们的需要;另外,像用例开发/调试,除了支持Java以外,我们还复用了普元的逻辑流图形化开发能力、组件库可视化管理能力,用例开发效率更高、更易维护;在企业级应用中,流程服务的测试一直面临诸多的问题,诸如:— 系统内部任何一个微小的变化,要上线测试;— 外部关联系统变化,引起的业务验证测试;— 如果流程作为一个公共的服务,一旦服务升级,所有业务系统都会有影响,所有业务系统全部都要验证。这些都会给测试造成巨大的工作量,不仅消耗过多的时间,还无法很好的保证质量。当这些问题投射到云环境与分布式架构中,所面临的复杂度与解决难度的升级不言而喻。如图所示,在基于微服务架构的数字化企业云平台中,流程是一类重要的微服务。我们正在尝试将流程微服务的测试自动化,并由DevOps平台高效的验证微服务的改变是否影响原先的业务,从而提供高质量的上线保障,让测试人员告别那些让人生无可恋的重复性操作。基于微服务的自动化测试的本质是通过数据的录制记录既有的测试过程,并通过案例固化过程中的全部测试数据,最终通过对案例的调用回放完成流程微服务测试的自动化。流程微服务的自动化测试并非完全脱离手工测试,这里的自动化是建立初次手工测试的基础上的。第一次手工测试会在数据库中记录下所有的测试信息,我们将收集这些信息录制形成测试数据文件,根据每条流程实例录制一个测试数据文件。每个文件中包含:该流程实例运行过程中的所有相应请求/相应报文,该流程实例运行过程中的上下文变化,该流程实例的流转路径(活动+连线),该流程实例包含的子流程实例。在流程微服务的自动化测试里,我们会根据实际的接口调用来设计多个组件,这些组件放置于一个测试组件微服务中提供给测试人员使用,每个简单的组件都对应一个接口的请求报文。这就犹如搭积木,每个积木是一个简单的接口报文,多个积木搭在一起形成一个房子,即多个接口报文固定调用形成一个复杂组件。多个房子、花坛、汽车形成一个小镇,即多个简单组件和复杂组件结合在一起生成的最终一个“流程实例的自动化测试”案例。有了之前收集的数据文件,就是根据每个数据文件,选择积木的问题了,再根据数据文件给每个组件添加必要的参数,这样就形成了测试案例。在案例生成的过程中测试人员不需要编写任何代码!我们将统一测试平台门户设计为一类领域系统,可以上传我们的测试案例部署,选择案例点击执行即可。每个案例的运行其实就是相应手工测试的一次回放。案例执行完成会形成详细的测试报告,包含了成功、错误、异常的详细信息,案例统计图,以及案例执行时间。清晰明了地达成便捷测试。流程微服务有时也会和其他微服务之间通信,往往测试环境中无法与其他微服务直接交互,这时候我们为了模拟流程微服务引擎与其他微服务交互过程,提供了一个服务挡板功能,服务挡板也是设计中的数字化企业云平台的一类领域系统,由api mock提供挡板能力,即用服务挡板替代生产上的微服务。(未来我们会详细介绍api mock相对于传统mock的优势)当自动化测试进行到其他微服务交互时,流程微服务引擎向挡板发起请求,挡板响应请求,并动态拼写回调报文,当所有的回调报文完成之后,挡板通知测试引擎,测试引擎向流程引擎发送回调报文。对于测试案例,不仅需要模拟流程流转的服务接口过程,还需要验证流转过程中的参数正确性,所以需要验证组件来完成参数的确认。 - 对比服务接口返回报文信息是否一致; - 一个活动完成后循环等待后继活动是否激活; - 一个活动完成后对比当前后继活动与历史测试数据中后继活动是否一致; - 一个活动激活后对比当前活动产生的连线是否与历史测试数据中连线信息一致; - 每当一个可能引起上下文改变的服务接口完成后,对比当前流程实例与历史测试数据中的上下文是否一致。 最后总结回顾一下,我们的测试理念:测试一切、测试驱动开发、测试自动化,以及为了实现这三点所需的四个要素:敏捷协作的过程、测试设计方法、全栈测试团队、自动化测试服务。有了适合自己的过程、方法、团队、工具的保障,自动化测试的实践自然能够水到渠成。以上就是本次分享的全部内容,感谢大家。Q&A Q1:自动化测试在非微服务架构和微服务架构的本质区别是? A1 微服务自动化测试重要的一点就是服务间的交互。我们提供mock组件来模拟服务间调用,而传统的整体架构没有这种问题 Q2:有没有数据支撑,做自动化的数据度量? A2 数据支撑指的是什么?我们在项目中跑4000的用例是没有问题的 Q3:哪些场景下不应该做自动化呢? A3 做不做自动化测试主要看你的用例数量,重复执行率,以及自动化测试难度。当你觉得测试用例少,或者难度过大的时候不建议用 Q4:数据录制是采用什么方式存储和标识的呢?如何做到后续的复用和扩展? A4 数据录制是用数据库记录初次手工测试产生的数据,以流程实例id为标识。我们开发的工具会根据流程实例id取出这些数据形成文件,即使数据库被清,根据文件可以再次生成用例。扩展了新的服务接口我们只要开发新的组件即可。 Q5:自动化测试有压力测试的模拟吗? A5 暂时我们没有提供压力测试的自动化测试 Q6:请问提到的中间mock组件和美团技术博客分享的mock组件类似的功能吗,可以推荐下相关的mock开源组件吗? A6:我们这里的mock组件就是用mock server模拟数据来进行服务间调用。这个组件是我们测试组件的概念。就是自己将mock调用方法封装成的一个组件。 分享者简介:叶婉婷,普元信息SOA产品部高级软件工程师,现为普元微服务应用平台项目开发团队一员。在过去的两年参与了流程平台项目,主要负责Eclipse插件开发及自动化测试平台开发。爱好:旅游、电影、美食、游泳。
什么是大数据? 从具备4V(Volume,Velocity,Variety,Value)特征的大量数据中挖掘用户的潜在价值。 广告系统的数据来源 DSP监听数据(主要是ssp,adx渠道) 广告主数据 广告投放过程中收集的数据 购买/通过交换得到的第三方数据 运营商合作数据 精准广告的系统特点 数据量巨大(广告本身的数据,定向数据,用户特征数据,广告展示环境的特征数据) 响应速度要求特别快 实时性要求特别高(广告数据,定向数据,用户特征数据,广告展示环境的特征数据等实时性) 系统可用性要求特别高(柔性降级,可扩展性) PC广告与移动广告的区别 交互方式的不同 使用位置的不同 用户标识的不同 展现形式的不同 网络环境的不同 受众定向的不同 精准广告中数据的主要应用 DMP 人群/用户画像 个性化创意/推荐引擎 大数据处理分析技术介绍 储存/缓存 计算 算法/规则 储存/缓存 Tair/redis2 -> ssdb/redis3 -> aerospike Kafka/DL Mongodb/hbase Hadoop Mysql 计算 Hive/mr Storm Spark Streaming 算法/规则 协同过滤(UserCF/ItemCF) 文本相似/图片相似 关联规则(支持度和置信度) 逻辑回归模型 兴趣时间衰减 规则引擎(DNA) 心得体会 做工程不易,且做且珍惜(技术+管理+工匠精神) 建立PDCA效果验证闭环 每一个做技术的都应该有崇高的理想,技术只是手段 分享者简介:宋慧庆,时趣互动 移动广告架构师 十余年互联网老司机,具有多年互联网广告系统研发经验,负责研发个性化动态创意系统,用户画像标签系统以及大数据治理;对编程语言有浓厚的兴趣。
一、MySQL+Redis常用部署方式 1.1 拓扑 1.2 特点 业务层通过双写同时写MySQL及Redis。读通常在Redis,若读取不到,则从MySQL读取,然后将数据同步到Redis,Redis通常设置expire或者默认LRU进行数据淘汰。 这种使用方式会有如下问题: 1)MySQL及Redis存在数据不一致风险,尤其是长时间运行的系统 2)业务层需要处理MySQL sql schema与Redis kv数据结构上的逻辑差异 3)无统一运维 4)无法方便扩容/缩容 二、KV化的存储使用理念 2.1 MySQL Is great NoSQL 参考文档: http://www.aviransplace.com/2015/08/12/Mysql-is-a-great-nosql/ 为什么要用MySQL: “在可扩展系统构建时,一个很重要的考量是使用的技术是否成熟,选择成熟的技术意味着出错时能够迅速恢复。当然,开发者也可以在项目中使用最新最牛的NoSQL数据库,而这个数据库在理论上也可以良好地运行,然而在生产环境中出现了问题恢复需要多久?技术上已有的知识和经验积累对于问题缓解至关重要,当然这个积累也包括了Google可以搜索到的内容。 相比之下,关系型数据库已经存在了超过四十年,业界对于关系型数据库的维护也积累了大量的经验。基于这些考虑,在新项目做技术选型时通常会选择Mysql,而不是NoSQL数据库,除非NoSQL真的有非常非常明显的优势。” 2.2 KV理念 对于亿级规模的数据存储,尤其是涉及到水平拆分跨机分库分表的情况下,线上对数据库的访问只能做的越简单越好,group by/order by/分页/通用join/事务等等的支持 在这个量级下的MySQL系统都是不合适的。 基本上目前所有的类proxy的MySQL方案真正上规模线上应用只能使用按拆分键进行读写操作,实际上也是一个用拆分键做的一个kv系统。 若想使用复杂的sql处理,最合理的部署方案是将Mysqlbinlog流水同步服务抽象出来,通过实时同步到OLAP类的系统进行处理。 所以面向海量存储服务,MySQL从一开始就设计为一个KV系统是可行的。value使用mediumblob存储xml/json/protobuf/thrift格式化数据序列化之后的数据。 2.3 MySQL KV化的使用方式 1、用MySQL原来的主键或者索引键当做key 2、其他所有的非主键非索引键,全部包装到value里面,value使用mediumblob存储xml/json/protobuf/thrift格式化数据序列化之后的数据。 3、数据读写操作,均基于key一整行数据做读写,由业务层对里面value的结构做解析及对内部结构做增删改差,而不用变更MySQL本身的schema. 2.4 不适用场景 1、数据量和访问量不大并且业务逻辑依赖MySQL数据库进行处理的业务场景 2、涉及到多表join等的处理 对于此限制,也可以通过将关联表加工成基于关联条件的一张宽表进行KV化。 3、涉及到事务等的处理。 三、将MySQL+Redis设计为统一的KV存储服务 3.1 目标 1)业务层通过统一方式访问MySQL及Redis,不再使用MySQL客户端及Redis客户端访问 2)MySQL集群化/Redis集群化部署 3)将业务双写改为MySQL到Redis底层binlog数据同步方式完成同步 4)异构数据存储支持最终一致性数据读写服务 5)支持存储层面扩容缩容、failover且业务无感知 6)单机群日百亿次QPS/TPS支持(大类业务适度拆分到不同集群中) 3.2 最终实现 基于MySQL+Redis的统一存储服务(UniStore) = MySQL跨机分库分表集群 + Redis集群 + MySQL->Redis实时数据同步服务 + 统一的对外数据访问接口 + 内在的完整运维支持系统(支持在线扩容/缩容、failover等) 3.3 架构图 3.4 架构说明-将存储设计为一种服务 1、将MySQL+Redis做成统一KV存储服务 2、通过acc proxy提供统一的数据访问接口,通过统一协议支持跨语言数据访问 访问协议(自定义协议,protobuf协议,thrift协议等) 3、MySQL cluster支持跨机的分库分表,schemaless设计,所有业务表KV化设计 4、Redis cluster支持跨机的实例拆分 5、Sync数据同步服务提供统一的Mysql到Redis 跨IDC/不跨IDC数据同步服务,小于100ms延时 6、整个系统不涉及到分布式事务处理 3.5 三种部署方式 1、纯MySQL集群部署 此种部署方式等同于其他MySQL proxy跨机分库分表方案,读写均在MySQL 2、纯Redis集群部署 此种部署方式等同于其他Redis proxy跨机分库分表方案,读写均在Redis 3、MySQL+Redis异构部署 写在MySQL,读可以从MySQL读或者Redis读,取决于业务对最新数据的读取要求。 3.6 接口说明 1、int get(int appid, string key,string& value) Redis读操作专用 2、int get_with_version(int appid,string key, string& value, int64& version) MySQL读操作专用,自带版本号,防止写覆盖 3、int set(int appid, string key,string value, int64 version) 通过appid区分MySQL还是Redis,均支持写操作 4、int delete(int appid, string key) 通过appid区分MySQL还是Redis, 不支持批量删除 5、int multiget(int appid,vector<string> keys, map<string, string>& key_value_pairs) 支持批量读操作,内部的数据路由及数据合并不用关心 6、intmultiset(int appid, map<string, string>& key_value_pairs) 不建议支持,涉及到跨机事务问题,无法保证ACID 7、int Redis_op(string cmd, ……) Redis其他原生接口封装(incr/expire/list/setnx等) 四、Cluster Manager服务 4.1 Cluster Manager是一个service cluster manager主要由如下几种功能 1)MySQL/Redis分片路由信息的管理 1、MySQL分库分表路由信息 2、Redis Slot路由信息 3、路由信息变更管理 2)Redis实例的探活及Redis扩容及缩容数据的迁移 比如连续3次,每次间隔30sRedis ping失败,认为实例挂掉,发出报警或者自动切换 3)Cluster manager不建议参与Mysql group主备层面的管理 MySQL主备层面的集群管理方案: 1、MHA+VIP (互联网公司最常用) 2、微信phxsql系统:https://github.com/tencent-wechat/phxsql 金融级可靠性 五、MySQL集群方案 5.1 架构图 5.2 设计原则 1)统一的schemaless表结构 2)跨机的数据分布 支持将单逻辑表水平拆分到多个Mysql服务器中 3)其他说明 1、数据存储可靠性高,所有业务数据通过序列化存储到value列 2、每行数据自带版本号,业务通过cas方式防止业务层多实例同时写造成写覆盖 全局唯一版本号实现:本机微秒时间戳+server_id+proccess_id 3、固定百库百表/百库十表的数据拆分方式,多机跨Mysql实例部署 5.3 路由策略 1) 一致性hash 2) 路由计算算法 crc32/md5/基于字符串的各类hash算法 3) 路由信息格式 CREATETABLE `Mysql_shard_info` ( `appid` int(32) NOT NULL, `begin` int(32) NOT NULL, `end` int(32) NOT NULL, `ip` varchar(20) NOT NULL DEFAULT '', `port` int(11) NOT NULL DEFAULT '0', `user` varchar(50) NOT NULL DEFAULT '', `pwd` varchar(50) NOT NULL DEFAULT '', PRIMARY KEY (`appid`,`begin`) )ENGINE=InnoDB DEFAULT CHARSET=utf8; 5.4 数据迁移/自动扩展 数据迁移: STEP1:利用MySQL主备复制机制进行数据复制 STEP2:数据差异小于某一临界值,停止老分片写操作(read-only) STEP3:等待新分片数据更新完毕 STEP4:更路由规则路由规则,Cluster Manager向所有access proxy更新路由信息 STEP5:删除老分片 自动扩展: 过程类似于数据迁移 六、Redis集群方案 6.1 部署方式 1、异构读写分离-MySQL写,Redis读 1) 数据写操作在MySQL,读操作在Redis 2) 数据通过Sync系统对binlog进行解析从Mysql同步到Redis 3) 数据有同步延迟(小于100ms),实现最终一致性 适用场景:要求数据高可靠,且读量比较大,允许读数据短时间不一致,若期望一直读到最新数据,请使用get_with_version()接口从MySQL读取 2、独立的Redis集群服务 1)读写均在Redis,提供独立的KV存储服务 2) 用户不用关注扩容/缩容/故障恢复等问题 3) 集群内多业务混存,提高内存的使用率 适用场景:独立的Redis集群服务,类似twenproxy/codis 6.2 设计要点 1、一致性hash 支持数据跨Redis实例拆分,固定Slot数进行拆分 2、单机多实例部署 1)每个物理机支持多Redis实例 2)每个Redis实例只服务单个业务 3)Redis实例内存大小取决于业务需求,同时考虑业务访问量和数据量 以RedisIP+port标示唯一实例,对于128G内存机器, 可配置3 Redis实例*每实例30G 或10 Redis实例*每实例10G 或20 Redis实例*每实例5G 拆分原则:单实例最大内存使用 < 本机剩余内存 3、以Slot为单位的平滑扩容/缩容 4、以Redis实例为单位的failover处理 6.3 平滑扩容/缩容 主要步骤如下: STEP1:确认扩容/缩容 Cluster manager通过对系统负载和数据量进行告警,进而确认进行扩容或者缩容 STEP2:修改路由表 1)修改路由表,将对应shard的状态修改为migrate状态,并将新路由推送到所有接入层 2)acc proxy会将写操作转到新的Redis实例中,读操作默认先读新Redis实例,key不存在会继续从老的Redis实例中读取 STEP3:数据迁移 1)Cluster manager通过自动数据迁移工具开始数据迁移,计划依赖Redis的scan命令将相关的key扫出来,通过MIGRATE进行数据迁移 2)多次扫描执行该过程,确认Slot中所有数据迁移完成 STEP4:修改路由表,迁移完成 Cluster manager将读写均切到新Redis实例,不再从老Redis中进行操作 七、Sync数据同步服务 7.1 架构 7.2 应用场景 该服务完全可以抽象成独立的数据同步分发服务,对于因为KV化而丢失的sql处理完全可以通过该服务同步到偏OLAP类的系统中进行处理。除了同步到Redis还可以同步到ElasticSearch或者hbase或者写hdfs文件基于hadoop生态去实现复杂计算和分析。 7.3 设计要点 1、集群对集群的实时数据同步 MySQL统一要求binlog日志为row格式 2、不涉及DDL处理 由于MySQL schemaless的设计,不用考虑DDL处理,简化同步服务(跨/不跨IDC) 3、基于时间戳的同步延迟监控 MySQL binlog row格式日志自带时间戳,基于此时间戳进行同步延迟监控 4、基于binlog文件名+offset的同步位置管理 定时定量持久化保存当前同步的binlog文件名及offset,用于各种场景下的同步恢复 5、基于行的并行同步 多线程同步模式,主线程通过对tableid或者key做hash,将binlogevent时间分发到对应worker线程的队列中,worker线程依次从队列中获取binlog event执行 7.4 实现原理 原理相对比较简单: 1)Sync同步工具模拟Mysql slave的交互协议,伪装自己为MySQLslave,向Mysqlmaster发送dump协议 2)Mysqlmaster收到dump请求,开始推送binary log给slave(也就是同步工具) 3)Sync同步工具解析binary log对象(原始为byte流),并转换成Redis或其他存储(hdfs/hbase/ES等数据库)相应数据操作接口或者作为消息存储到MQ中(rocketmq或者kafka) 7.5 ROW格式events MySQL 5.5 Binlog的事件类型有多种,这里只介绍与ROW模式相关的事件 1) QUERY_EVENT:与STATEMENT模式处理相同,存储的是SQL,主要是一些与数据无关的操作,eg: begin、drop table 2) TABLE_MAP_EVENT:记录了下一条事件所对应的表信息,在其中存储了数据库名和表名 3) WRITE_ROWS_EVENT:操作类型为insert 4) UPDATE_ROWS_EVENT:操作类型为update 5) DELETE_ROWS_EVENT:操作类型为delete 6) XID_EVENT, 用于标识事务提交(commit) 典型的insert语句有如下4个events组成: 7.6 其他开源同步方案 1. tungsten-replicator(JAVA) http://code.google.com/p/tungsten-replicator/ 2. linkedin databus(JAVA) https://github.com/linkedin/databus 3. Alibaba canal(JAVA) https://github.com/alibaba/canal / 分享者简介: 秦波,8年开发及架构经验,之前在华为/京东/小米参与部分核心基础服务的设计与开发工作,目前在九州证券负责大数据平台及风控相关项目的技术研发工作。关注高并发/高可靠/服务监控与治理/分布式存储/大数据相关系统的架构和实现。
内容简介 近两年作者在海外交付中参与 microservices 下的团队,为客户提升 Finance 系统的扩展性。作者所在团队,3 对开发(pair programming, 2 个 dev 为 pair)为客户支撑着 11 个 services,持续部署流水线(CD pipeline)是其中必不可少的一个技术实践。本次分享作者将从实践的角度分享 microservices 架构下的持续部署(CD)。内容概述 1. microservice 概述:简要介绍 microservice 架构下的挑战 2. 持续部署实践:这里会提到『Build Pipeline as Code』,『Infrastructure as Code』等概念。 3. 持续部署了之后呢? 这里会介绍 CD 结合团队的敏捷开发流程的实践经验。 microservices 概述 当提到 microservice 的时候,我们通常会从下图开始:为了从业务和技术方面得到更好的扩展能力,我们将单一架构的系统(Monolithic architecture),拆分成若干的微服务(Microservices architecture),这种拆分是架构演进的一个过程。在整个拆分过程中,对团队的组织架构,数据的管理方式,部署监控技术方面都带来极大的挑战。持续部署(简称 CD)是 microservices 架构中一个必备的实践之一。本文将介绍基于Docker 的 CD 方式。 部署方面带来的挑战 单一架构下(Monolithic),我们的系统 Code base 可以在一个项目中,这个系统采用一个持续集成(简称:CI) pipeline,并且此时我们也可以采用持续集成(简称:CD)pipeline,最终将系统持续部署到生产环境中。在这种情况下,每当系统引入一个改变的时候,CI,CD pipe line 都会执行一次。例如: - 10 mins Unit Test - 2 hours Acceptance Test - 15 mins package - 20 mins deployment 上面列举的例子并不算坏,更庞大的系统可能会需要更多的时间。当我们将 Monolithic 系统拆分成多个 micro services 时,并且将每个 services 进行独立部署。每当系统引入一个改变的时候(code change),它只会影响个别 service,我们只需要部署发生改变的部署,从新运行一个 service 的 CI,CD pipeline: - 1 mins Unit Test - 1 mins Integration test - 5 mins package - 5 mins deployment 这种拆分之后,更符合我们对解耦的追求:『当代码引入一个改变的时候,它应该影响的改动最小』此时所提到的改变涉及整个开发流程,从代码到部署的影响做到了最小。拆分 services 之后的代价是,每个 service 都需要独立部署,我们需要为每个 service 搭建 CD pipeline。在 microservices 场景下,不同的 service 按照需求可能会采用不同的技术栈。并且在每次新建 service 时,配套的日志,监控,报警系统也需要进行配置。这个对 CD 提出了很大的挑战。持续部署方面的实践 当我们谈持续部署的时候,此时也会包括持续集成。持续部署的整个过程会从代码 push 到 master 开始:我们采用 Docker 来解决技术栈差异的问题,DevOps 创建部署工具将部署,监控,报警等配置模板化。实践: - 使用 Docker 构建和发布 service - 采用 Docker Compose 运行测试 - 使用 Docker 进行部署 准则: - Build pipe line as Code - Infrastructure as Code(base on AWS) - 共享构建脚本 使用 Docker 构建和发布 service - 使用 Docker 构建 service,service 已 docker image 的方式发布 - 将 docker 发布到 docker registry - 从 docker registry 上 pull docker image 进行部署 使用 Docker Compose 运行测试 Docker Compose可以将多个 docker image 进行组合。有些 service 需要访问数据,我们可以通过 docker compose 将 service image 和 database image 组合在一起。组合之后,我们可以采用 docker compose 运行持续集成。下面这个实例展示如何进行这种组合:https://gist.github.com/lvjian700/7c295e6a596e96526049f831d0eb8b13#file-docker-compose-ymlBuild pipeline as Code 通常我们使用 Jenkins 或者 Bamboo 来搭建 CI/CD pipeline,每次创建 pipeline 需要进行大量的手工配置,此时很难自动化 CI 服务器配置。Build pipeline as Code,即使用代码来描述 pipeline,这样做可以带来非常好的可读性和重用性。我们可以很容易的做到 CI 服务器配置。今年团队将所有 pipeline 从 Bamboo 迁移到了 BuildKite。在 BuildKite 上可以使用如下代码描述上图的 pipeline:https://gist.github.com/lvjian700/7c295e6a596e96526049f831d0eb8b13#file-buildkite-ymlInfrastructure as Code 如果我们要发布一个基于 HTTP 协议的 REST-ful API service,我们需要 service 准备如下基础设施(Infrastructure): - 可部署的机器 - 机器的 IP 和网络配置 - 设备硬件监控服务(GPU,Memory 等) - 负载均衡(Load Balancer) - DNS - AutoScaling (services 自动伸缩服务) - Splunk 日志收集 - NewRelic 性能监控 - Sentry.io 和 PagerDuty 报警 这些基础设施的搭建和配置我们希望将其模板化,自动化。我们才用代码描述基础设施,DevOps 提供工具模板化基础设施的描述。实践: - 采用 AWS 云服务进行部署 - 采用 AWS CloudFormation 描述和创建资源 - 将对资源操作的脚本进行 source control 准则: - 对资源的描述和操作应该在 git 中 - 在所有环境中采用相同的部署流程 - 使用 ssh 等手动操作资源的方式,只能用于测试环境和做一些 debug。 共享构建脚本 在为多个 services 搭建 CD pipeline 之后,我们将 CD pipeline 归纳为三部: 1. 运行测试 2. 构建发布 docker image 3. 部署 分别为这三步提取出 shell scripts: 1. test.sh 2. docker-tag.sh 3. deploy <test|prod> 之后为上述脚本创建 git repository,并且将其以 git submodule 的方式引入各个项目。持续部署了之后呢? 让 CD pipeline 服务团队的工作流程 我们搭建好 CD pipeline,需要让它在团队的敏捷开发流程中发挥为威力:团队职责: - 团队主要分为 BA,Developer(简称 Dev),Tech Lead(简称TL) - BA 负责分析业务,并在故事墙上创建 Story - Dev 负责开发,QA,运维(跨能型团队) - Tech Lead 负责技术 工作流程: 1. Dev 从 Backlog 中拿卡进行分析,分析完成后跟 BA,TL一起 kickoff 确定需求、技术实现。 2. kickoff 之后, Dev 在 repository 上创建 Pull Request(简称 PR) 开始工作。此时在 PR 上的每一次 git push 会触发 PR 的 pipeline,此时在 CI 机器上只会运行单元测试和集成测试。 3. Dev 开发完成后,其他 Dev 对 PR 进行 Review,Review 通过之后将 PR merge 到 master 分支,此时会 trigger master 分支上的 pipeline,将最新代码自动部署到 test 环境。 4. 部署 test 环境成功后,Dev 基于 test 环境进行 QA。 5. QA 完成后向 BA, TL 做 showcase 进行 user acceptance test。 6. 通过 user acceptance test 之后,在 BuildKite 上点击部署到 production 按钮完成发布。 按照以上流程,团队可以快速从 CI/CD pipeline 上得到反馈,高度自动化的 CD pipeline 可以让团队做到按照 Story 进行 service 发布。Summary Microsservices 在业务和技术的扩展性方面带来了极大的便利,同时在组织和技术层面带来的极大的挑战。由于在架构的演进过程中,会有很多新服务产生,持续部署是技术层面的挑战之一,追求极致的自动化,可以让团队从基础设施抽离出来,关注与产生业务价值的功能实现。Q&AQ1:你们的docker是用什么来管理的?k8s,swarm 还是其他什么? A1: K8S, Swarm 都没使用,对这两个服务我也只是听说过。 每个独立的 service Docker image 会单独运行在 AWS EC 2 Instance。管理一般也都是围绕 EC 2 Instance 来做。关于 Docker Images 仓库,采用自建的 Docker Registry 服务来 push 和 pull docker image。================Q2:如何做跨语言的服务集成A2: 我们做过 Ruby 和 Node.js 的集成。服务器间通信采用 HTTP 协议,JSON 作为传输格式, JSON 基于 hyper media link 的实现之一 HAL 。 如何解决 service 之间的约定,我们采用 Consumer Driven Contract 的方式,使用单元测试代替集成测试,这部分实现采用 Pact 。================Q3:service的粒度如何确定A3: 这是一个非常好的问题,也是很难回答的问题。 我个人觉得 microservices 中最难回答的两个问题是:1. 什么拆分出一个 service?2. 怎么拆分?(也就是拆分多细,系统边界如何确定)service 粒度如何确定,一句话来回答(TL;DR):『采用领域驱动设计(DDD)的方式拆分』。更长版本,我们项目是为客户解决已运行10年以上财务生态系统的拆分问题。也就是老系统改造,也是我觉得最适合实施 micro services 的场景。老系统存在很多痛点,并且需求较为稳定。那么如何拆:1. 需要引入业务专家,技术专家,相关利益人一起分析业务场景,系统构成确定领域语言对业务进行建模。2. 将以前以业务切分系统的思路转为按照数据模型切分的思路。3. 每个类数据模型可以划分多种子模型来辅助主数据模型。4. service 的粒度一般以数据模型的粒度来确认。还有一些按照非功能性需求来切分的原则,比如实施 CQRS 的时候,将读写拆成两部分,采用 Even Sourcing 解决分布式系统数据状态同步的问题。================Q4:为什么没有考虑gocd,gocd可是first class的CI/CD工具A4: 好问题,这个我需要找 ThoughtWorks 负责 GoCD 的同时聊聊销售问题。BTW,我个人还没机会使用过 GoCD================Q5:目前发现从esb soa转microservice,原本进程内的调用关系变成了网络调用,一次rpc变成了几次或者几十次rpc,同等条件下性能损失严重。这个问题如何得到解决?A5: 好问题,性能问题也是被同事问得最多的问题。关于性能问题我没遇见过高并发的场景,当时对于降低 services 依赖,控制网络请求我们是有一些解决方案。1. 所有 services 基本都部署在同一个网络,比如 AWS 的网络上,可以讲起想想成内部局网,HTTP call 带来的性能损耗目前为止还算可以接受。2. 从系统设计的角度讲,与其降低HTTP请求的消耗时间,不如减少HTTP 请求的发送次数。从系统设计上考虑,大部数据模型都是 immutable (不可变得),在系统系统间我们将数据缓存,减少 HTTP 请求的次数。
各位晚上好,我是数人云的褚向阳,接下来要跟大家分享的主题是《容器网络Calico进阶实践》. 距离上次聊 Calico 已经过去快半年的时间了,数人云也一直在努力将容器网络方案应用到企业客户的环境中,Calico v2.0 也马上就要发布了,这次跟大家一起感受下新版. 需要说明下,本人跟 Calico 没有任何直接关系,也只是个"吃瓜群众",做为使用者,想跟大家聊聊心得而已。 这次分享的内容主要包括: 简单总结下作为使用者我看到的 Calico 的变化,包括组件,文档和 calicoctl ; Demo 一些简单的例子,会和 MacVLAN 做一下对比说明原理; 最后总结下适合 Calico 的使用场景; Calico 简介回顾 首先,还是简单的回顾下 Calico 的架构和关键组件,方便大家理解。 Calico 架构 Calico 是一个三层的数据中心网络方案,而且方便集成 OpenStack 这种 IaaS 云架构,能够提供高效可控的 VM、容器、裸机之间的通信。 结合上面这张图,我们来过一遍 Calico 的核心组件: Felix,Calico agent,跑在每台需要运行 workload 的节点上,主要负责配置路由及 ACLs 等信息来确保 endpoint 的连通状态; etcd,分布式键值存储,主要负责网络元数据一致性,确保 Calico 网络状态的准确性; BGP Client(BIRD), 主要负责把 Felix 写入 kernel 的路由信息分发到当前 Calico 网络,确保 workload 间的通信的有效性; BGP Route Reflector(BIRD), 大规模部署时使用,摒弃所有节点互联的 mesh 模式,通过一个或者多个 BGP Route Reflector 来完成集中式的路由分发; 通过将整个互联网的可扩展 IP 网络原则压缩到数据中心级别,Calico 在每一个计算节点利用 Linux kernel 实现了一个高效的 vRouter 来负责数据转发 而每个 vRouter 通过 BGP 协议负责把自己上运行的 workload 的路由信息像整个 Calico 网络内传播 - 小规模部署可以直接互联,大规模下可通过指定的 BGP route reflector 来完成。 这样保证最终所有的 workload 之间的数据流量都是通过 IP 包的方式完成互联的。 Calico 节点组网可以直接利用数据中心的网络结构(支持 L2 或者 L3),不需要额外的 NAT,隧道或者 VXLAN overlay network。 如上图所示,这样保证这个方案的简单可控,而且没有封包解包,节约 CPU 计算资源的同时,提高了整个网络的性能。 此外,Calico 基于 iptables 还提供了丰富而灵活的网络 policy, 保证通过各个节点上的 ACLs 来提供 workload 的多租户隔离、安全组以及其他可达性限制等功能。 更详细的介绍大家可以参考之前的分享: http://edgedef.com/docker-networking.html 或者 http://dockone.io/article/1489 Calico 的新版变化 接下来简单介绍下 Calico 新版带来了哪些变化 组件层面: 先看一下 v2.0.0-rc2 中包含的组件列表: v2.0.0-rc2 felix 2.0.0-rc4 calicoctl v1.0.0-rc2 calico/node v1.0.0-rc2 calico/cni v1.5.3 libcalico v0.19.0 libcalico-go v1.0.0-rc4 calico-bird v0.2.0-rc1 calico-bgp-daemon v0.1.1-rc2 libnetwork-plugin v1.0.0-rc3 calico/kube-policy-controller v0.5.1 networking-calico 889cfff 对比下 v1.5 或者之前的版本: v1.5.0 felix v1.4.1b2 calicoctl v0.22.0 calico/node v0.22.0 calico/node-libnetwork v0.9.0 calico/cni v1.4.2 ibcalico v0.17.0 calico-bird v0.1.0 calico/kube-policy-controller v0.3.0 可以看到组件层面 Calico 也发生了比较大的变化,其中新增: libcalico-go (Golang Calico library function, used by both calicoctl, calico-cni and felix) calico-bgp-daemon (GoBGP based Calico BGP Daemon,alternative to BIRD) libnetwork-plugin (Docker libnetwork plugin for Project Calico, integrated with the calico/node image) networking-calico (OpenStack/Neutron integration for Calico networking) 总结来看,就是组件语言栈转向 Golang,包括原来 Python 的 calicoctl 也用 Golang 重写了; 顺便说一下,这也和数人云的语言栈从 Python Golang 统一到 Golang 是差不多的周期,可以看出 Golang 在容器圈的影响力之大; 同时面向开源,给使用者提供更好的扩展性(兼容 GoBGP)和集成能力(OpenStack/Neutron)。 使用层面: 更好的文档和积极响应的 Slack: http://docs.projectcalico.org/v2.0/introduction/ 开源软件的文档对于使用者来说很重要,Calico 的文档正在变的越来越好,尽量保证每种使用场景(docker,Mesos, CoreOS, K8s, OpenStack 等) 都能找到可用的参考。 除此之外,Calico 还维护了一个很快响应的 Slack,有问题可以随时到里边提问,这种交互对开源的使用者来说也是很好的体验。 重新面向 Kubernetes 改写的 calicoctl UX 模型 毫无疑问,这是 Calico 为了更好的集成到 Kubernetes 所做出的努力和改变,也是对越来越多使用 k8s 同时又想尝试 Calico 网络的用户的好消息,这样大家就可以像在 k8s 中定义 资源模型一样通过 YAML 文件来定义 Calico 中的 Pool,Policy 这些模型了,同时也支持 label&selector 模式,保证了使用上的一致性。 具体的 Calico 定义资源模型的例子在后面的 Demo 中会有体现。 Calico CNI 及 Canal 还有一个变化,就是 Canal 的出现,面向 CNI 的基于访问控制的容器网络方案。 Container Network Interface CNI 容器网络 spec 是由 CoreOS 提出的,被 Mesos, Kubernetes 以及 rkt 等接受引入 使用。 Calico 在对 Docker 家的 CNM 和 libnetwork 提供更好的支持的同时,为了更亲和 Kubernetes ,和更好的对 CNI 的支持,Metaswitch 和 CoreOS 一起组建了 新的公司 TiGERA(https://www.tigera.io/),主推 Canal 将 Calico 的 policy 功能加入到 Flannel 的网络中,为和 k8s 的网络提供更好的 ACL 控制。 Calico 组件原理 Demo 为了理解 Calico 工作原理,顺便体验新版 Calico,我们准备了两套 Demo 环境,一套是新版 Calico,另一套是对比环境 MacVLAN。 Calico 以测试为目的集群搭建,步骤很简单,这里不展开了, 大家可以直接参考 http://docs.projectcalico.org/master/getting-started/docker/installation/manual MacVlan 的集群搭建,步骤也相对简单, 参考:https://github.com/alfredhuang211/study-docker-doc/blob/master/docker跨主机macVLAN网络配置.md 这里默认已经有了两套 Docker Demo 集群: Calico 网络的集群,分别是:10.1.1.103(calico01) 和 10.1.1.104(calico02) MacVLAN 集群,分别是:10.1.1.105 和 10.1.1.106 Demo 1: Calico 三层互联 calicoctl node status 截图: 同时,已经有 IP Pool 创建好,是:192.168.0.0/16 calicoctl get pool 截图: 当前集群也已经通过使用 calico driver 和 IPAM 创建了不同的 docker network,本次 demo 只需要使用 net1 docker network ls 截图: calicoctl get profile 截图: 下面我们使用 net1 这个网络,在两台机器上各启动一个容器: 在 calico01 上: docker run --net net1 --name workload-A -tid busybox 在 calico02 上: docker run --net net1 --name workload-B -tid busybox 容器连通性测试截图: Demo 2: MacVLAN 二层互联 创建 MacVLAN 网络,分别在两台主机上使用相同命令 docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=enp0s3 -o macvlan_mode=bridge 192_1 创建容器: 10.1.1.105: docker run --net=192_1 --ip=192.168.1.168 -id --name test01 busybox sh 10.1.1.106: docker run --net=192_1 --ip=192.168.1.188 -id --name test11 busybox sh 测试网络连通性: docker exec test01 ping -c 4 192.168.1.188 Calico IP 路由实现及 Wireshark 抓包 根据上面这个 Calico 数据平面概念图,结合我们的例子,我们来看看 Calico 是如何实现跨主机互通的: 两台 slave route 截图: 对照两台主机的路由表,我们就知道,如果主机 1 上的容器(192.168.147.195)想要发送数据到主机 2 上的容器(192.168.38.195), 那它就会 match 到响应的路由规则 192.168.38.192/26 via 10.1.1.104,将数据包转发给主机 2,主机 2 在根据 192.168.38.195 dev cali2f648c3dc3f 把数据包发到对应的 veth pair 上,交给 kernel。 那整个数据流就是: container -> calico01 -> one or more hops -> calico02 -> container 最后,让我们来看看 Wireshark 抓包的截图对比: Calico: MacVLAN: 从上图对比中也能看出,不同于 MacVLAN,Calico 网络中容器的通信的数据包在节点之间使用节点的 MAC 地址,这样没有额外的 ARP 广播的,这是 Calico 作为三层方案的特点之一。 但这同时也表明了,节点之间网络部分如果想对于容器间通信在二层做 filter 或者控制在 Calico 方案中是不起作用的。 这样,一个简单的跨主机的 Calico 容期间三层通信就 Demo 完了,其他的 Calico 特性这里就一一介绍了,鼓励大家可以自己使用 VMs 搭起来亲自试试,遇到问题随时到 Slack 去聊聊。 Calico 使用场景 Calico 既可以用在公有云,也可以部署在私有环境,我们接下来主要集中讨论下 Calico 在私有云中的使用场景2。 二层网络 Calico 适用于二层网络,原因首先就是不会因为容器数量的变化带来 ARP 广播风暴,上面的 Demo 中,我们已经看出了,Calico 中容器间的相关通信在二层使用的是节点的 MAC 地址, 这样也就是说,广播上的增长只是主机层上的增减,这在数据中心本来就是可控的;其次,就是网络扰动,同样的道理,使用 Calico 也不用担心因为容器的频繁启动停止所带来的网络扰动; 最后,Calico 的 IP 空间使用是相对自由的,这样保证足够的 IP 资源使用。 当然,任何事情都是两面,使用 Calico 要理解,Calico 的 IP 是集群内,也就是说如果需要使用容器 IP 和 外部互联网进行通讯,还需要进行相应的配置。 比如:如果有对外通讯需求,则要开启 nat-outgoing;如果需要对内可达,需要配置和维护对应的路由规则或者通过支持 BGP 的外部交换/路由设备,具体可以参考3。 此外,上面的 Demo 也说明了,如果有需求对容器间通信二层数据包有分析和控制的化,Calico 也是没办法的,这样也就是说如果 DC 已经集成了一些商业网络控制模块或者 SDN,则要通盘考虑, 是否合适引入 Calico。 最后,提一个小点,Calico 的数据存储,需要对每个 calico node 指定唯一标示,默认需要使用 hostname ,也可以在 calicoctl node run 时通过 --name 指定, 如果使用默认的 hostname,就要求在初始化 Calico 集群之前,规划好各个主机的 hostname。 三层网络 Calico 也能使用在三层的网络中,但是相比二层是要复杂,需要更多的 net-eng 介入,个人水平有限,就不展开说了,有兴趣的可以直接参考: http://docs.projectcalico.org/master/reference/private-cloud/l3-interconnect-fabric 总结: 随着容器网络的发展,数人云会越来越多的关注如何把先进的容器网络技术更好的"落地"企业,数人云年底新版本也会加入了适配数人云的 Calico 安装配置手册给最终用户。 我们会一直关注开源,包括 Calico, Cisco Contiv, DPDK等,相信后面各个开源方案都会在易用性、易维护性上继续提升,同时也一定会加强对各个容器编排方案的支持。 回过头看 Calico 的新版本发展,也印证了这些要求: 易用性,兼容 k8s 的 calicoctl UX; 易维护性,Golang 重写;Calico 本身为三层方案,而且Calico 能够兼容二层和三层的网络设计,可以和现有 DC 网络的整合和维护; 更好的和现有方案的集成,包括 OpenStack,CNI/Canal,Mesos 等,Calico 在网络方案的适用性方案还是很有竞争力的; 2016年马上就要过去了,作为容器网络的爱好者使用者,个人希望在 2017 年数人云能将真正成熟稳定的容器网络方案带给大家。 能力所限,文中难免有错误,随时欢迎指正。谢谢! 问答环节 问题1:画网络拓扑图,有什么好用的开源工具么?最好是免费的,开源的(来自:中生代技术(成渝一家)@邹晨-佳网) 答:其实我个人不怎么画网络拓扑图的,不过如果是 windows 以前就是用 Visio,最近画图都用 Gliffy,Chrome 有插件的。如果是放在页面中的动态生成图,建议看看 D3. 问题2:calico有具体的性能数据吗?(来自:中生代技术(西安)- @李钊-ZTE-研发) 答:之前做过简单的性能对比测试,总体来看还是很不错的,具体见图: 问题3:遇到问题随时到 Slack 去聊聊,想请教下这个跟slack有什么关系?(来自:中生代技术(成渝一家)@邹晨-佳网) 答:这里指的是 calico 的 slack:https://slack.projectcalico.org/ , 中生代技术群分享第四十七期 讲师:褚向阳,数人云研发工程师,接触开源及Openstack比较早,曾在红帽PnT(原HSS)部门负责红帽内部工具链的开发及维护工作。现负责数人云的研发工作,对Docker,Mesos有所研究,熟悉和热爱云计算、分布式、SDN等领域相关技术。