关于持续集成:定位任意时刻性能问题持续性能分析实践解析

01 继续性能分析简介更好的利用性能,能够提供更好的用户体验,能够升高企业IT老本,能够让零碎更稳固和牢靠。在利用性能分析技术呈现以前,开发人员排查问题只能依赖各种日志和监控,这须要提前在利用代码中埋点,岂但对利用代码侵入性较大且可能因为埋点不全而无奈提供足够信息,诊断问题十分费时,很多时候无奈找出起因。 随着利用性能分析技术呈现,开发人员能够很不便的找出应用程序性能瓶颈(如CPU利用率高、内存占用低等),从而进行优化。但因为晚期利用性能分析技术开销较大,只能在开发环境而不能在生产长时间开启,生产环境出问题时很可能没有被记录下来,开发人员在开发环境模拟和复现问题很艰难,导致解决问题的效率很低,也很有可能无奈解决。 近些年来,性能分析技术继续倒退,性能越来越丰盛,开销也显著改善,达到生产环境继续开启水准,不过离宽泛遍及还存在诸多阻碍。性能分析个别过程有三步:生产环境抓取、保留性能分析文件、性能分析文件可视化。当利用体量较大时,这3个步骤每步都存在着难度,须要解决大量计算、存储、产品设计等多方面问题。 ARMS Continuous Profiler[1]应运而生,由阿里云ARMS(利用实时监控服务[2])团队和Dragonwell[3]团队联结研发。它基于以后最成熟的性能分析技术,将整个性能分析过程产品化,适宜在生成环境继续开启。与惯例性能分析相比,ARMS Continuous Profiler减少工夫维度,外围性能如下:• 定位任意时刻的性能问题(比方CPU占用高、内存占用高)• 反对两个时段的性能比照,找出利用演进过程中的性能差别• 观测利用的调用栈,以便更好的扫视和了解代码设计 残缺内容请点击下方链接查看: https://developer.aliyun.com/article/1174927?utm_content=g_10... 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 25, 2023 · 1 min · jiezi

关于持续集成:建木v270缓存功能上线

新增性能大家心心念念心心念念的缓存性能终于上线了! 有了缓存之后可能防止反复下载依赖,让节点执行速度变快,上面以maven节点为例,给大家演示一下如何增加缓存 两种形式都是两步走:1、定义缓存 2、在节点中援用缓存并填写缓存目录 情谊提醒:缓存目录很重要,写不对你可能会发现所有白干... 图形化编排 DSL DSL具体应用形式能够参考文档 第一次执行流程须要下载缓存,第二次节点执行速度就会变快很多。快去试试吧! 性能优化优化慢SQL BUG修复1、已有我的项目增加cron触发器,下次执行工夫展现有误 2、webhook触发器批改为cron触发器时,未革除Trigger中的webhook数据 3、在事务内,@Retryble重试机制触发异样,Transaction rolled back because it has been marked as rollback-only 4、2.6.3版本 icon隐没 5、右侧抽屉点进去后,页面右侧无余白 6、上游节点有雷同ref的输出/输入参数时,上游节点有可能会援用上游节点的输出参数反复登录问题 7、终止流程,无奈删除volume 8、Worker重启之后,如果有运行中的工作,Worker会阻塞,期待工作执行实现,无奈执行新的工作 9、重启worker时,复原中的工作,终止流程时无奈终止 官⽹:https://jianmu.dev代码:https://gitee.com/jianmu-dev文档:https://docs.jianmu.dev示例:https://ci.jianmu.dev

March 20, 2023 · 1 min · jiezi

关于持续集成:新一代-CI-即将到来

本文转载 CodeSheep。作者受邀加入 Techo Day 腾讯技术开放日线上流动,播种颇丰,有感而发。前言上期 Techo Day 腾讯技术开放日流动讲的是「轻量级工具」,这一期次要讲的是「云原生」。 在所有课题里,集体比较关心的是 CI 设计这个课题——CODING CI 3.0,比传统 CI 好在哪里? 传统 CI 的问题和痛点CI 的概念CI 全称 Continuous Integration,名为「继续集成」,传统的 CI 含意指的是代码仓库只有有代码变更(或者说有人想推代码入库),就会主动执行事后设计好的查看、防护流程,运行一系列构建、测试、部署等流程,并最终告知每一步的运行后果,确保人提交上来的代码没有问题后,才有机会将新代码合并到骨干分支,而骨干分支无论何时都肯定是正确可运行的高质量版本,能够随时交付客户应用。 继续集成的词面意思其实某一水平上也道出了该做法思维的精华:即小步快走,继续地去做代码集成。 不得不说继续集成在古代软件研发流程中,表演了非常重要的角色。 平时的工程中,总有一部分工作是绝对机械化,易出错的(例如打包、部署),咱们能够把这部分工作交给机器来做。让继续集成构建打算进行自动化的单元测试、代码查看、编译构建、契约测试,甚至主动部署,可能大大降低开发人员的工作累赘,缩小许多不必要的重复劳动,继续晋升代码品质和开发效率。 传统 CI 问题和痛点聊到 CI 零碎,那不得不提的就是 Jenkins 了,它是一个应用宽泛的继续集成工具。 然而不少团队或我的项目应用 Jenkins 零碎的眼光还局限于在 Jenkins 上建各种各样的 Job 来实现 CI 工作,所以仍然存在不少痛点,典型的比方: 配置繁琐且不灵便,尤其是对于新拉分支的 CI 部署比拟麻烦,配置的可扩展性和可复用性有待进步。传统的 Jenkins Job 难以灵便高效地并行(包含 Job 间、节点间、工作间、甚至工作内等各个维度的并行),所以工作执行效率有待进步。传统的 Jenkins Job 日益失控的趋势让咱们措手不及,Job 太多,CI 脚本太离散,保护老本切实太高了,而且很危险,一旦 Jenkins Server 挂了,所有都 Game Over 了,须要从新搭建了。现在很多的业务上云了当前,如何对云端代码疾速构建一个高效的 CI 零碎也成了一个必须要面对的问题。什么是 CODING CI 3.0CODING 继续集成是 CODING DevOps 的子产品,其全面兼容 Jenkins 的继续集成服务,反对 Java、Python、Node.js 等支流语言,并且反对 Docker 镜像构建,图形化编排,高配集群多打算并行构建全面提速您的构建工作。反对支流的 Git 代码仓库,包含 CODING 代码托管、GitHub、GitLab 等等。在构建依赖拉取方面,应用专用网络优化包含 Maven,NPM 等支流镜像源,保障拉取速度,进一步晋升构建速度。 ...

November 4, 2022 · 2 min · jiezi

关于持续集成:引擎上新|卡片焕新升级信息高效呈现

各位GitLink的小伙伴,最近有没有发现引擎模块的流水线卡片有所变动呢~ 旧版-Old 新版-New 为了给用户更好的应用体验,建木团队的小伙伴实现了这次卡片降级。最新版的卡片丰盛了展现信息,重要内容高深莫测,相比旧版卡片更加直观。具体做了哪些调整呢?一起来看看吧! 执行状态不再困惑 降级前 黑的白的红的黄的紫的绿的蓝的灰的你的我的他的她的...这条流水线当初到底是什么状态?只依据色彩辨别真的很让人抓狂有木有? 降级后 保留色彩的同时,减少了文字标识,无须再盲猜执行状态。 流水线执行状态有: (1)未启动:流水线新建后未触发执行 (2)待启动 (3)执行中:正在执行 (4)挂起 (5)失败 (6)胜利 注:待启动、挂起、执行中的流水线可手动终止,终止后主动失败 执行次数分明明了 卡片展现了最近一次触发的次数,流水线应用高频低频高深莫测 执行工夫残缺展现 降级前 展现了最初执行工夫 降级后展现了最近执行开始工夫+执行/挂起时长 定时配置更加清晰 定时配置极大地加重了人们对工夫记忆的累赘,置信很多小伙伴都会设置定时流水线。降级前定时流水线会展现下次执行的具体工夫;非定时流水线下次执行工夫为“无” 降级后(1)定时流水线减少⏰标识,可无效与非定时流水线辨别开来。 (2)鼠标滑过闹钟标识,有下次执行的精确工夫 (3)卡片上显示间隔下次执行剩余时间 以上,就是GitLink引擎卡片降级的内容啦,心愿这次的优化你能喜爱~ 点击下方链接,新版卡片,快来体验! https://www.gitlink.org.cn/ji... 体验账号:jianmu明码:jianmu.dev 建木与GitLink单干详情,速戳建木×GitLink,解锁高效开发新体验 官⽹:https://jianmu.dev代码:https://gitee.com/jianmu-dev文档:https://docs.jianmu.dev示例:https://ci.jianmu.dev

October 31, 2022 · 1 min · jiezi

关于持续集成:自动化集成Pipeline整合Docker容器

前言:该系列文章,围绕继续集成:Jenkins+Docker+K8S相干组件,实现自动化治理源码编译、打包、镜像构建、部署等操作;本篇文章次要形容流水线集成Docker用法。 一、背景形容微服务架构是以后支流的技术选型,在业务具体落地时,会存在很多业务服务,不论是在开发、测试、上线的任意节点中,如果基于手动编译的形式打包服务,操作老本不仅极高,而且很容易呈现纰漏。 通过Pipeline流水线的形式,将服务镜像构建编排成一键触发执行,实现自动化的治理流程,是微服务架构中的必要的功能模块。 二、流程设计本篇中的流程节点,次要针对打包好的利用Jar包,在docker模块中的解决流程,次要是镜像构建治理与容器运行: 构建docker文件目录与内容;拷贝Jar包,创立Dockerfile脚本文件;执行docker镜像构建,推送云仓库;拉取镜像文件并运行docker容器;整个流程的都放在Pipeline流水线中,连接在本地Jar包生成之后。 三、实现过程1、插件装置首先装置流程中Docker集成的相干插件:Docker Pipeline,Docker plugin,CloudBees Docker Hub/Registry Notification。 在之前的流水线篇幅中,曾经通过流水线实现Gitee仓库代码pull和本地打包,上面开始解决docker环节。 2、镜像构建脚本对于Dockerfile的脚本语法也能够参考之前docker篇幅,上面看流水线中的用法: environment { docker_directory = 'docker-app' docker_repository = '仓库URL' } stage('Dockerfile') { steps { sh ''' rm -rf ${docker_directory} mkdir -p ${docker_directory} cp auto-client/target/auto-client-1.0-SNAPSHOT.jar ${docker_directory}/auto-client.jar cd ${docker_directory}cat>Dockerfile<<EOFFROM java:8MAINTAINER cicadasmileVOLUME /data/docker/logsADD auto-client.jar application.jarENTRYPOINT ["java","-Dspring.profiles.active=dev","-Djava.security.egd=file:/dev/./urandom","-jar","/application.jar"]EOF cat Dockerfile ''' echo "create Dockerfile success" } }脚本阐明: 在流水线的工作空间创立目录docker-app;每次执行都清空一次docker目录,再把Jar包和Docker脚本放进去;cat-EOF-EOF:即创立Dockerfile文件,并把两头的内容写入;脚本中的内容必须在文件中顶行写入;3、打包推送这里即进入docker目录,执行镜像打包的操作,并把镜像推送到云端仓库,很多仓库都是公有的,须要身份验证,通过配置凭据去拜访: stage('DockerImage'){ steps { script { dir("${docker_directory}") { sh 'ls' docker.withRegistry("${docker_directory}", '拜访凭据') { docker.build("doc-line-app:latest").push() } } echo "build DockerImage success" } }}4、凭据配置关上Manage Jenkins界面,Manage Credentials选项; ...

January 2, 2022 · 1 min · jiezi

关于持续集成:一站式交付体验云效Kubernetes

背景云效依靠于阿里巴巴研发效力多年规模化继续交付,赋能云上开发者专为云端用户提供的一站式研发合作平台。Kubernetes,由Google开源的容器集群治理平台,面向运维侧提供自动化的集群和利用治理解决方案。 一站式交付体验:云效+Kubernetes,云效继续集成流水线 Flow属于企业级继续集成和继续交付工具,通过构建自动化、集成自动化、验证自动化、部署自动化,实现从开发到上线CICD过程。通过继续向团队提供及时反馈,让交付过程高效顺畅。 外围能力通过联合云效与Kubernetes能够无效买通从研发合作,继续交付以及自动化运维的整个软件交付生命周期。 研发治理:通过看板继续治理和跟踪团队需要,缺点。并通过继续度量发现研发中的瓶颈并作出改良。 继续交付:通过流水线治理代码的继续集成,测试,部署以及公布行为,通过自动化的形式定义软件的整个交付过程。 Kubernetes: 屏蔽云端基础设施差别,提供多云的一致性基础设施和利用治理体验。 全功能团队合作在一个典型的全功能团队中,个别会蕴含以下角色: 开发人员:继续提交代码并且通过继续集成运行单元测试,构建等工作,疾速获取反馈。在实现继续集成后,可能主动部署代码到开发测试环境,以便在须要的时候可能对新开发的性能进行疾速验证。测试人员:绝对于开发来说,测试心愿有一个绝对较稳固的验收测试环境,并且能按需部署代码到测试环境(个别是开发人员自测实现后)。运维人员:惟一领有将版本部署到生产环境改的权限,能一键实现生产环境部署,但对权限和平安公布有更高的要求。继续交付流水线 继续交付流水线专一于从代码到公布的端到端自动化过程。基于云效提供的流水线编排能力,如上所示,基于云效继续交付流水线,咱们能够疾速编排一个继续交付流水线来承载全功能团队合作的需要。 阐明立刻体验:云效流水线Flow 基于流水线的团队合作 在流水线中咱们别离创立:CI(继续集成),Dev(开发环境部署),Test(测试环境部署),Prod(生产环境部署)4个阶段。同时为了实现不同角色之间的合作与工作流转。咱们将CI,Dev阶段设置为主动执行,Test,Prod为手动执行,并且减少了相应的人工卡点以确保只有相应角色的人员可能确认开始执行部署动作。 如下所示,每次开发人员提交代码后都可能触发并主动实现CI以及Dev环境的部署,如果CI流程有工作的异样都可能通过钉钉以及其余形式疾速获取到反馈。 因为Test阶段定义为手动执行,因而当须要部署测试环境时,测试人员能够手动触发该阶段的部署,为了确保测试环境不被其它角色进行误操作,在执行部署动作前须要具备测试owner角色的人员来手动验证,以开始测试环境部署。 当Dev以及Prod阶段均胜利当前,运维人员就能够按需对生产环境进行部署。 上述咱们定义了一个最简略的反对开发,测试,运维进行协同工作的继续交付流水线。 更多扩大玩法 基于流水线的流程编排能力,咱们能够在上述流水线根底上按需扩大更多的玩法。 例如:在生产公布之前,咱们能够增加一个Beta测试环境减少更多的环境来确保生产环境的平安部署。 或者在Beta以及Prod阶段再减少一个只蕴含人工卡点的阶段,在这种场景中咱们能够由专门角色的人员负责正式部署前Beta环境的验证,并且只有在验证通过之后能力进行Prod环境的公布: 一站式交付体验:云效+Kubernetes,云效继续集成流水线 Flow属于企业级继续集成和继续交付工具,通过构建自动化、集成自动化、验证自动化、部署自动化,实现从开发到上线CICD过程。通过继续向团队提供及时反馈,让交付过程高效顺畅。

October 21, 2021 · 1 min · jiezi

关于持续集成:什么是云效持续集成如何关联Jenkins进行持续集成

什么是云效继续集成?如何关联Jenkins进行继续集成?云效流水线 Flow是一款企业级、自动化的研发交付流水线, 提供灵便易用的继续集成、继续验证、 继续公布性能,帮忙企业高质量、高效率的交付业务。本文介绍如何应用 Codeup 代码库关联 Jenkins 进行继续集成。次要波及内容包含关联代码源、配置触发器的过程。 什么是云效继续集成? 继续集成/CI: 继续集成(英语:Continuous integration,缩写为 CI),一种软件工程流程,将所有工程师对于软件的工作复本,每天集成数次到共用主线(mainline)上。这个名称最早由葛来迪·布区(Grady Booch)在他的布区办法中提出,然而他并没有提到要每天集成数次。之后成为极限编程(extreme programming,缩写为XP)的一部分。在测试驱动开发(TDD)的作法中,通常还会搭配主动单元测试。继续集成的提出,次要是为了解决软件进行系统集成时面临的各项问题,极限编程称这些问题为集成天堂(integration hell)。ps:阐明来自维基百科 Jenkins插件装置 插件治理点击①处「系统管理」,接着点击②处「插件治理」: Git 源码治理在③处「可选插件」中输出“Git plugin”找到代码源治理的插件并装置: WebHook 插件同理,在可选插件中搜寻 “Generic Webhook Trigger Plugin”,并装置。 装置后需重启Jenkins。Jenkins 代码源配置 Step1:新建 Jenkins 工作 首先,新建冀望的 Jenkins 工作,而后筹备配置代码源。 Step2:进入工作配置页面 抉择源码治理-Git: Step3:源码治理配置 抉择Git,填入Codeup仓库地址,例如:https://codeup.aliyun.com/xxx...此时须要填写认证信息: 抉择Credentials,如果没有,须要新建: 这里须要填写的用户名和明码,就是Codeup代码仓库的克隆用户名和明码。获取地位如下图所示: 配置实现后如页面不再报错,则鉴权通过。 Step4:配置触发器 持续在设置页中找到「构建触发器」: 抉择「Generic Webhook Trigger」: 配置获取 Codeup Webhook 的申请参数: 参数阐明:以 Codeup Push 事件为例,push webhook 申请 body 如下。如上在 Variable 中填 ref,示意获取 post 申请 body 中 ref 字段,Expression 中填 $.ref 示意获取 body 中 ref 的 value 值。 ...

September 7, 2021 · 1 min · jiezi

关于持续集成:云效DevOps实践8分钟快速实现持续交付

导读:云效DevOps实际-8分钟疾速实现继续交付,随着企业疾速倒退和竞争的加剧,产品和合作的复杂度晋升,业务对研发效力的冀望越来越高,如何进步团队软件交付速度都要求企业具备疾速响应的能力,这正是推动继续集成、继续交付、继续部署的能源。利用云效DevOps帮忙你疾速实现继续交付。 1、用户的诉求或问题 团队没有对立的研发治理流程,工具无约束,恪守流程标准根本靠盲目;公布工夫长,须要人工染指多,无论从工夫老本,还是因为人工染指带来的危险都很大?不足对立的研发平台,自动化水平低,没有无效的品质保障体系,基础设施保障的建设往往落后于企业的疾速倒退?业界有很多很好的实际,然而复用到本人团队却很难,无从下手。2、云效继续交付架构图 云效,企业级一站式DevOps解决方案,源于阿里巴巴先进的治理理念和工程实际,提供从“需要->开发->测试->公布->运维”端到端的协同服务和研发工具,反对多种部署状态。通过代码扫描、代码评审等能力,助力企业继续、疾速、高质量地交付软件。步骤1.晨会上团队基于精益看板进行需要、工作对齐,实现工作指派;2.开发同学依据个性开发,创立变更分支;3.通过线下或云端开发环境进行编程工作,而后提交代码;4.代码提交主动触发代码扫描,并做完分支级别的验证,发送给指定代码评审员进行评审;5.实现评审的代码主动触发集成公布流水线,自动化的实现构建,生成Docker镜像,别离在开发环境、集成环境及预发环境进行部署,实现相应的验证工作;验证完之后处于待发布状态,触发上线审核流程,运维实现审核公布上线;6.过程中任何问题通过钉钉,遵循no news is good news的准则,自动化地及时反馈到指定负责人,做到精确反馈、即时响应,疾速复原。尽量避免垃圾短信式反馈,过多的乐音,反而会升高合作的效率。 3、场景介绍及操作指南 第一步:通过代码平台进行代码托管和评审 阐明立刻体验:云效代码治理 Codeup创立一个代码库 于个性分支编码 基于平台新建分支,开发进入编码阶段,能够通过代码平台在线形式或者本地编码模式,代码实现后提交远端分支;在代码提交时能够应用#ID语法建设代码和工作的关联,如gitcommit -m "#id" 开始代码扫描 因为设置了代码提交触发扫描查看,这里能够清晰看到查看的运行状况; 发动代码评审 通过新建合并申请发动代码评审,强制代码评审有利于进步代码品质,帮忙开发人员尽早发现问题,进步问题修复的效率; 代码合入集成分支 分支通过代码评审后,合并到集成分支,行将进入编译、部署、验证、公布阶段; 第二步:通过流水线实现继续交付 阐明 立刻体验:云效流水线Flow创立一条流水线点击流水线列表右上角【新建流水线】按钮,您能够疾速抉择一款适宜企业场景的模版; 编辑流水线场景 通过流水线编辑性能,联合企业场景疾速配置以下2条流水线: •集成环境流水线 【步骤阐明】 *触发形式抉择:代码提交触发;*集成分支开始代码扫描和单元测试;*测试通过开始代码构建;*编译通过部署测试环境;*测试同学测试验证;*验证通过代码合并公布分支;•公布环境流水线 【步骤阐明】 *公布分支开始构建编译;*编译通过部署预发环境;*预发环境验收测试;*验证通过开始公布单审核;*审核通过部署生产环境; 配置品质红线 增加红线卡点,以后测试工作必须达到规范能力进入下阶段;例如【代码扫描】抉择“增加红线”,能够设置: •Blocker的问题为0•Major的问题为0•Critial的问题为0 开始运行流水线 开始触发集成分支流水线,发展代码扫描和单元测试,通过流水线能够直观看到扫描后果是否胜利,具体后果能够通过测试报告查看; 品质红线后果 测试工作会依据对应的品质红线判断,如果不通过,无奈进入流水线下一阶段;思考在一些非凡的状况下,未通过品质红线的流程也须要持续往下执行,云效也提供了“跳过”的能力,能够由管理员将红线跳过。 查看流水线运行后果 所见即所得,流水线运行过程直观展现,企业可残缺看到以后流水线运行所处阶段和场景; •集成分支流水线 •公布分支流水线 钉钉音讯告诉 基于工作能够疾速配置钉钉音讯告诉,能够便于在流水线执行过程中及时接管音讯告诉,疾速定位排查和解决问题; 总结 通过【代码平台和流水线】组合出击标准代码治理和利用公布,疾速实现继续交付。云效DevOps实际-如何疾速实现继续交付,进步团队软件交付速度都要求企业具备疾速响应的能力而阿里云云效就可能做到,属于云原生时代新DevOps平台,反对公共云、专有云和混合云多种部署状态,通过云原生新技术和研发新模式,助力翻新守业和数字化转型企业疾速实现研发麻利和组织麻利,打造“双敏”组织,实现多倍效力晋升。

September 3, 2021 · 1 min · jiezi

关于持续集成:持续集成和交付流水线的8个反模式-IDCF

一、CI/CD & Pipeline随着DevOps的理念在泛滥公司的驳回,CI/CD也慢慢落地。 CI(Continuous Integration)继续集成,是把代码变更主动集成到骨干的一种实际。CI的呈现解决了集成天堂的问题,让产品能够疾速迭代,同时还能放弃高质量。它的外围措施是,代码集成到骨干之前,必须通过一系列自动化测试,比方编译、单元测试、lint、代码格调查看。CD包含继续交付和继续部署。继续交付(Continuous Delivery)指的是团队主动地、频繁地、可预测地交付高质量软件版本的过程,能够看做继续集成的下一个阶段,强调的是无论代码怎么更新,软件都是随时能够交付的;继续部署(continuous deployment)更强调的是应用自动化测试来保障变更的正确性和稳定性,以便在测试通过后立刻部署,是继续交付的更进一步。二者的区别是,继续交付须要人为染指,须要确保能够部署到生产环境时,才去进行部署。 图1 继续集成 & 继续交付 & 继续部署 CI/CD Pipeline是软件开发过程中避免浪费的一种实际,展示了从代码提交、构建、部署、测试到公布的整个过程,为团队提供可视化和及时反馈。Pipeline举荐的施行形式是,把软件部署的过程分为不同的阶段(Stage),其中工作(Step)在每个阶段中运行。在同一阶段,能够并行执行工作,帮忙疾速反馈,只有一个阶段中所有工作都通过时,下一阶段的工作才能够启动。比方图中,从git push到deploy to production的整个流程,就是一条CD Pipeline。能够利用Pipeline工具,如Jenkins、Buildkite、Bamboo,来帮忙咱们更不便的施行C/ICD。 图2 CI/CD Pipeline 二、CI/CD Pipeline的反模式尽管有Pipeline宽泛的利用,但咱们却会听见开发人员埋怨蹩脚的Pipeline对他们的挫伤,如阻塞开发流程,影响变更的部署效率,升高交付品质。咱们收集了我的项目上经常出现的Pipeline的八大反模式,依照呈现频率排序,别离论述这些坏滋味,剖析可能产生的起因、影响及解决形式,心愿可能缩小埋怨,让Pipeline更大程度上晋升工作效率。 2.1 没有代码化反模式:Pipeline的定义没有齐全代码化,进行版本控制,存储在代码仓库,而是在Pipeline 工具上间接输出shell脚本定义Pipeline的运行过程。 起因:因为晚期的CI工具不反对代码化,始终可能保留到当初,没有做重构和降级。 影响:Pipeline的创立和治理都是通过CI工具的界面交互来的,难以保护,因而须要专门的管理员来保护,而有人工操作的局部就会出错,因而会升高Pipeline的可靠性。如果Pipeline因为一些起因失落就没有方法很快复原,就会影响交付速率。 解决方案:Pipeline as code这个理念曾经提了很多年了,在ThoughtWorks 2016年的技术雷达里就曾经驳回了,须要强调的是,用于构建、测试和部署咱们应用程序或基础设施的交付Pipeline的配置,都应以代码模式展示。随着组织逐步演变为构建微服务或微前端的去中心化自治团队,人们越来越须要以代码模式治理Pipeline这种工程实际,来保障组织外部构建和部署软件的一致性。 通常,针对某个我的项目的Pipeline配置,应和我的项目代码放在我的项目的源码治理仓库中。同业务代码一样要做code review。这种需要使得业界呈现了很多反对Pipeline工具,它们能够以规范的形式构建、部署服务和利用,如Jenkins、Buildkite、Bamboo。这些工具用大多有一个Pipeline的蓝图,来执行一个交付生命周期中不同阶段的工作,如构建、测试和部署,而不必关怀实现细节。以代码模式来实现构建、测试和部署流水线的能力,应该成为抉择CI/CD工具的评估规范之一。 2.2 运行速度慢反模式:一条Pipeline的执行工夫超过半小时,就属于运行速度慢的Pipeline。(这里的运行速度与交付的产品无关,在不同的我的项目中,运行时长的限定也有所不同) 起因:很多起因都会导致运行一次Pipeline工夫很长,比方: 该并行的工作没有并行执行,期待的工作拉长了执行工夫;执行Pipeline的agent节点太少,或者性能有余,导致排队工夫太长,效率太低;执行的工作太重,雷同测试场景被不同的测试笼罩了很屡次。比方同样的逻辑在不同测试中都测了一遍;没有正当利用缓存,比方每个工作里都要下载全副依赖,在构建Dockerfile时没有正当利用layer,每次都会构建一个全新的image。影响:这是开发人员埋怨最多的一个反模式。麻利开发模式须要Pipeline疾速反馈后果,受这一反模式制约,在个性开发过程中,经常出现开发人员改一行代码,等半天CI的成果。如果呈现一个线上事变须要批改一行代码来修复,最终须要很长的周期能力让这一更改利用在生产环境。 解决:不同的起因导致的Pipeline速度慢,有不同的解决办法。比方针对下面的问题,咱们能够去: 查看Pipeline的设计是否正当,尽可能让工作并行;对代码的各种测试深刻理解,让测试尽量正交,防止过多的反复;查看代码中的依赖,正当利用好缓存。包含Docker Image、Gradle、Yarn、Rubygem的缓存,以及Dockerfile是否正当的设计,最大化的将不可变的layer集中的开始阶段;查看执行构建的节点资源是否短缺,是否在任务量大时做弹性伸缩,缩小期待和执行工夫。2.3 执行后果不稳固 图3 执行屡次后果不稳固 反模式:构建雷同代码的Pipeline运行屡次,失去后果不同。比方,基于同一代码基线,一条Pipeline构建了5次,只有最初一次通过了。 起因:呈现执行后果不稳固的起因也多种多样,比方测试用例的实现不合理,导致测试后果时过期不过;代码中应用了不牢靠的依赖源,比方来自国外的依赖源,下载依赖常常超时;由或是在Pipeline运行过程中没有正当设计各个阶段,导致有些工作同时运行抵触了。 影响:Pipeline作为代码公布的最初一道防火墙,最根本的个性是幂等性,即在一个雷同的代码基线,执行Pipeline的任意工作,不论是10次、100次,失去的后果都雷同。Pipeline不稳固会间接导致代码的部署速率升高。更重要的是,影响开发人员对Pipeline的信赖。如果不稳固Pipeline不及时解决,缓缓这条Pipeline会失去保护,开发最初会转向手工部署。 解决 要构建幂等的、牢靠的Pipeline,就要剖析这些不稳固因素呈现的起因。晋升测试的稳定性,比方用mock代替不稳固的源。采纳Pipeline的重试性能,或者采纳稳固的镜像源,或者提前构建好根底镜像。引入Pipeline的插件保障工作不会并行执行。2.4 滥用job解决生产环境数据反模式:应用Pipeline的定时工作的个性,运行生产环境的负载。比方常常会定期做数据备份、数据迁徙,数据抓取。 起因:因为对Pipeline的意识不够清晰,将重要的工作交由Pipeline做。Pipeline一旦有了某个生产环境的拜访权限,做这些数据处理相干的工作就很不便,缩小了很多人为的操作。 影响:Pipeline是用来做构建、部署的工具,不能用于业务逻辑的执行。因为Pipeline是一个外部服务,他的SLO/SLI必然和生产环境不同,如果强依赖势必影响生产环境的SLO。如果某天Pipeline挂掉了,生产环境就无奈失去想要的数据。另外,工作和Pipeline严密耦合,是咱们前面会探讨的另一个反模式。 解决办法:用生产环境本身的工具解决这种数据问题,比方 采纳AWS的lambda,定时触发数据处理工作。 2.5 简单难懂 图4 Pipeline的定义逻辑简单 反模式:Pipeline的定义蕴含了太多的逻辑,简单难懂。只有在一条Pipeline运行起来能力晓得这里会运行哪些步骤,会将这个版本部署到哪些环境。 起因:Pipeline的代码不够整洁。有人认为Pipeline只是给CI工具提供的,就随便编写,认为能实现指定的工作就够了。 影响:Pipeline的复杂性,会间接晋升学习老本。如果想反复执行上一次构建,会破费较长时间。 解决:Pipeline的代码要简洁,把复杂性放在部署脚本或代码侧。通过每个阶段的的题目能够间接理解所要执行的工作。如果存在很多雷同的逻辑,能够通过开发Pipeline的Plugin来简化配置。 2.6 耦合太高 图5 (左)耦合太高的Pipeline定义 (右)期待的Pipeline定义 ...

August 10, 2021 · 1 min · jiezi

关于devops:一篇文章了解CICD管道全流程

从CI/CD过程开始,蕴含所有阶段并负责创立自动化和无缝的软件交付的一系列步骤称为CI/CD管道工作流。应用CI/CD管道,软件公布工件能够从代码提交阶段到测试、构建、部署和生产阶段在管道中挪动和后退。这个概念十分弱小,因为一旦指定了一个管道,它的一部分或全副就能够实现自动化,从而放慢流程并缩小谬误。换句话说,CI/CD管道使企业更容易一天主动屡次交付软件。 DevOps工程师常常会因为CI/CD中各个阶段的自动化而与CI/CD管道混同。尽管不同的工具能够使CI/CD中的各个简单阶段实现自动化,但因为人工干预,CI/CD的整个软件供应链依然可能被突破。那么,就首先理解CI/CD过程中的各个阶段,以及CI/CD管道为什么对于组织疾速、大规模地交付代码至关重要。 CI/CD阶段:理解人员、过程和技术企业应用程序开发团队通常由开发人员、测试人员/QA工程师、经营工程师和SRE(站点可靠性工程师)或IT经营团队组成。他们严密单干,将高质量的软件交付给客户。CI/CD是两个独立过程的组合:继续集成和继续部署。上面列出了其中的次要步骤。 CI继续集成继续集成(CI)是构建软件并实现初始测试的过程。继续部署(CD)是将代码与基础设施联合起来的过程,确保实现所有测试并遵循策略,而后将代码部署到预期的环境中。当然,许多公司都有本人的流程,但次要步骤如下。 CI:代码提交 人员:开发人员和工程师、数据库管理员(DBA)、基础架构团队 技术:GitHub、Gitlab、BitBucket过程:代码提交阶段也称为版本控制。提交是将开发人员编写的最新更改发送到存储库的操作。开发人员编写的代码的每个版本都被无限期地存储。在与合作者探讨和审查变更之后,开发人员将编写代码,并在软件需要、性能加强、bug修复或变更申请实现后提交。治理编辑和提交变更的存储库被称为源代码治理(SCM工具)。在开发人员提交代码(代码推送申请)后,代码更改被合并到存储在地方存储库(如GitHub)中的根本代码分支中。 CI:动态代码剖析人员:开发人员和工程师、数据库管理员(DBA)、基础设施团队、测试人员 技术:GitHub、Gitlab、BitBucket过程:一旦开发人员编写了代码并将其推送到存储库,零碎就会主动触发,开始下一个代码剖析过程。设想一下这样一个步骤:提交的代码间接进行构建,但在构建或部署过程中失败了。就资源利用率而言,无论是机器还是人力,这都是一个迟缓而低廉的过程。必须查看代码的动态策略。SAST(Static Application Security Test):SAST是一种白盒测试方法,应用SonarQube、Veracode、Appscan等SAST工具从外部查看代码,以发现软件缺陷、破绽和弱点(如SQL注入等)。这是一个疾速查看过程,查看代码是否有语法错误。尽管此阶段短少查看运行时谬误的性能,但这将在稍后的阶段执行。 将附加的策略查看放到自动化管道中能够显著缩小稍后在该过程中发现的谬误数。 CI:build人员:开发人员和工程师 技术:Jenkins,、Bamboo CI、Circle CI、Travis CI、Maven、Azure DevOps过程:继续集成流程的指标是承受惯例的代码提交,并继续构建二进制工件。继续集成过程通过查看增加的新模块是否与现有模块配合良好,有助于更快地发现bug。这有助于缩小验证新代码更改的工夫。构建工具有助于编译和创立可执行文件或包(.exe、。dll, .jar等)取决于用于编写源代码的编程语言。在构建过程中,还会生成SQL脚本,而后与基础设施配置文件一起测试。简而言之,构建阶段是编译应用程序的阶段。构建过程的其余子流动包含工件存储、构建验证和单元测试。 CI:测试阶段人员:测试人员和QA工程师 技术:Selenium、Appium、 Jmeter、SOAP UI、Tarantula过程:公布一个构建过程一系列自动化测试来验证代码的准确性。这一阶段有助于避免谬误达到产品。依据构建的大小,此查看能够继续数秒到数小时。对于由多个团队提交和构建代码的大型组织,这些查看将在并行环境中运行,以节俭贵重的工夫并尽早将Bug告诉给开发人员。 这些自动化测试是由测试人员(或者称为QA工程师)建设的,他们曾经依据用户故事建设了测试用例和场景。他们进行回归剖析,压力测试,以查看与预期产出的偏差。测试中波及的流动有健全性测试、集成测试和压力测试。这是一个十分先进的测试程度。在这里会发现开发代码的开发人员可能不晓得的问题。 集成测试:集成测试是应用Cucumber、Selenium等工具来执行的,其中各个利用程序模块作为一个组进行组合和测试,同时评估是否合乎指定的性能需要。在集成测试之后,须要有人批准将该组中的更新集挪动到下一阶段,这通常是性能测试。这个验证过程可能很麻烦,但它是整个过程的重要组成部分。核查过程中呈现了一些新的解决办法。 负载和压力测试:负载平衡和压力测试也应用自动化测试工具(如Selenium、JMeter等)来执行,以查看应用程序在高流量环境下是否稳固和性能良好。此测试通常不会在每个更新上运行,因为残缺的压力测试是长期运行的。在公布次要的新性能时,将对多个更新进行分组,并实现残缺的性能测试。在单个更新被转移到下一个阶段的状况下,管道可能包含金丝雀测试作为代替计划。 继续部署:bake和部署人员:基础设施工程师、现场可靠性工程师(SRE)、运维工程师 技术:Spinnaker、Argo CD、Tekton CD过程:测试阶段实现后,革除了规范的代码就能够部署到服务器中,在那里它们将与主应用程序集成。在部署到生产环境之前,它们将被部署到产品团队外部应用的测试/暂存或beta环境中。在将构建挪动到这些环境之前,构建必须通过两个子阶段Bake和Deploy。这两个阶段都是Spinnaker固有的。 CD:BakeBake是指从源代码中创立一个不可变的映像实例,该实例在生产环境中具备以后配置。这些配置可能是数据库更改和其余基础设施更新之类的内容。Spinnaker能够触发Jenkins来执行这个工作,有些组织更喜爱应用Packer。 CD:部署Spinnaker将主动将烘焙的映像传递到部署阶段。这是将服务器组设置为部署到集群的地位。与上述测试过程相似,在部署阶段执行性能雷同的过程。部署首先转移到测试、阶段,最初转移到生产环境,而后进行批准和查看。整个过程由Spinnaker之类的工具解决。 CD:验证这也是团队优化整个CI/CD流程的关键所在。因为当初曾经进行了很多测试,所以失败应该很少。但此时的任何故障都须要尽快解决,以便将对最终客户的影响降到最低。团队也应该思考自动化这部分流程。 部署到生产环境是应用部署策略(如蓝绿部署、金丝雀剖析、滚动更新等)执行的。在部署阶段,将监督正在运行的应用程序,以验证以后部署是否正确或是否须要回滚。 CD:监控人员:SRE,运维团队 技术:Zabbix、Nagios、Prometheus、Elastic Search、Splunk、Appdynamics、Tivoli过程:要使一个软件发行版具备故障安全性和健壮性,在生产环境中跟踪发行版的运行状况是至关重要的。应用程序监控工具将跟踪CPU利用率和公布提早等性能指标。日志分析器将扫描底层中间件和操作系统产生的日志流,以辨认行为并跟踪问题的起源。在生产过程中呈现任何问题时,都会告诉相干人员,以确保生产环境的安全性和可靠性。此外,监督阶段帮忙企业收集无关新软件更改如何为支出做出奉献的信息,并帮忙基础架构团队跟踪零碎行为趋势和进行容量布局。 继续部署:反馈和合作工具 人员:SRE、Ops和保护团队 技术:禅道、ServiceNow、Slack、Email、HipchatDevOps团队的指标是更迅速、继续地公布,而后一直缩小谬误和性能问题。这是通过slack或电子邮件频繁地向开发人员和项目经理反馈新版本的品质和性能,并在ITSM工具中及时进步票价来实现的。通常,反馈系统是整个软件交付过程的一部分;因而交付过程中的任何更改都会频繁地记录到零碎中,以便交付团队能够对其采取行动。 企业必须评估一个整体的继续交付解决方案,它能够自动化或促成上述阶段的自动化。

April 15, 2021 · 1 min · jiezi

关于持续集成:如何自动同步博客到-Github-主页

前言Github 反对通过创立同名仓库的模式自定义主页。比方我的 Github 用户名是 azl397985856,那么新建一个名为 azl397985856 的仓库即可。接下来你能够通过批改此仓库的 README 文件来自定义 Github 主页。也就是说,你想要自定义主页就新建一个同名仓库并批改 README 就行了。 批改 README 能玩出什么花色呢?请接着往下看。 装修成果先上一下我的装修成果: 开始入手增加数据统计上图的那几个 Github 数据统计以及奖杯应用的是一个内部服务。想要显示哪个就增加相应代码即可: 数据统计: ![](https://github-readme-stats.vercel.app/api?username=azl397985856&show_icons=true)留神将 username 改成本人的用户名哦(上面也是一样,不再赘述),不然就显示的 lucifer 我的信息啦。奖杯: ![](https://github-profile-trophy.vercel.app/?username=azl397985856&theme=flat&column=7)自动更新博客如上图我的装修主页,其中博客的文章列表不是写死的,而是每隔一个小时定时读取我的博客 内容,并提取前 5 篇文章。 如果你也想要这个性能,就在 README 中增加如下代码即可: ## ???? Latest Blog Posts<!-- BLOG-POST-LIST:START --><!-- BLOG-POST-LIST:END -->之后读取的博客列表会填充在两个正文之间,也就是说你能够通过扭转正文的地位,将其放到页面任意地位。 为了实现每个小时定时更新的性能,咱们能够应用 Github Action 的定时工作来实现。 具体操作步骤如下: 接下来将如下内容复制粘贴进去: name: Blog Postson: # Run workflow automatically schedule: # Runs every hour, on the hour - cron: "0 * * * *"jobs: update-readme-with-blog: name: Update this repo's README with latest blog posts runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: gautamkrishnar/blog-post-workflow@master with: # comma-separated list of RSS feed urls feed_list: "https://lucifer.ren/blog/atom.xml"留神:这里的 cron: "0 * * * *" 的意思是每个小时进行一次,并且是每个小时的 0 分。 因为你须要等到下一个整点能力看到成果,有时候 Github 会有延时,晚几分钟也失常,大家不要焦急,急躁期待即可。请将 feed_list 替换为你本人的 RSS 订阅地址。如果有多个订阅地址,则用英文半角逗号宰割。 ...

February 27, 2021 · 1 min · jiezi

关于持续集成:DevOps进行时某银行大型管理系统端到端持续集成和交付实践-IDCF

背景传统的银行IT零碎研发流程从需要提出到产品交付往往具备较长的研发周期,纵观银行当下面临的市场环境,集体信贷生产降级,资管需要旺盛,普惠金融成为国家策略,来自银行同业和互联网金融的压力扑面而来,谁先推出合乎市场需求的产品谁就霸占了先机,对银行IT研发的疾速交付能力提出了新的要求和挑战。 传统银行IT零碎研发过程中的弊病次要体现在研发流程不连贯难追溯、人工解决效率低时效差、不足无效的代码审查机制、人力资源节约等,针对上述问题,咱们基于继续集成、继续交付的理念,设计了针对某银行大型管理系统(下称C零碎)的CI/CD流水线,开发了一系列外围组件,基于TFS (现已改名为 Azure DevOps Server)实现了端到端、线上化、全自动的继续交付。 一、CI/CD流水线的设计与实现C零碎是某银行重要的大型管理系统,具备多团队合作、多我的项目并行、多技术体系并用、多产品/模块协同、多环境并存、多时点交付等特点,是一个典型的银行大型IT零碎。咱们以C零碎为试点,基于TFS,设计了从需要治理、任务分配、分支建设、代码提交、版本合并、自动化构建公布到自动化测试的笼罩研发全流程的继续集成和交付流水线。开发人员通过全线上操作发动版本公布申请,将代码收集、版本核查、构建公布等重复性工作自动化、线上化,进步了版本交付的效率与品质、开释了人力资源。 图1 继续集成和交付流水线模型 1.1 自动化代码动态扫描代码动态扫描是控制代码品质的重要伎俩。对于C零碎来说,原有的人工触发全量查看形式是一种被动的预先查看策略,在公布生产环境前查看,每次查看至多须要3个小时,且须要人工甄别增量违例,时效性差、工作效率低、批改老本低等问题突出。 为解决上述问题,咱们深入研究了TFS API和JTest、CChecker等动态查看工具,通过文件哈希值比对等技术手段,对代码合规查看组件和邮件告诉组件进行了深度定制,造成了一套按需增量查看+定时全量查看相结合的代码合规查看策略,并可能向相干负责人精准发送违例代码告诉。 表1 代码合规查看调用的TFS API列表 咱们将代码合规性查看集成到继续集成和交付流水线中,在开发人员申请将代码合并到测试版本库或准生产版本库时,主动触发代码合规性查看步骤,并主动解析检查报告,若存在新增违例,则禁止代码合并,并向代码提交人发送邮件告诉。 图2 分支策略中配置的代码合规性查看 图3 代码合规性查看存在新增违例的日志信息 1.2 代码强制评审代码评审次要包含两方面内容:一是C零碎由多个模块形成,每个模块由不同的开发人员负责,当呈现跨模块的代码批改时,须由该模块的负责人评审改变内容的准确性;二是零碎中存在一些公共配置文件,这些文件改变后可能会对整个零碎产生影响,须由资深的零碎研发人员进行评审。 咱们借助TFS拉取申请中的审阅者性能,设计了满足C零碎特点的代码强制评审策略,无效防止了误审、漏审、甚至不审等弊病。 咱们首先在TFS中创立了C零碎各模块的开发人员团队,并在分支策略中配置了各模块对应的代码门路。 图4 分支策略中配置的模块负责人 当开发人员提交代码时,TFS会主动判断是否存在跨模块的代码批改,并在拉取申请的审阅者中主动增加模块负责人作为必须的审核人员,只有通过审核能力进行后续的代码合并。 图5 代码合并时的强制代码审核 1.3 继续集成继续交付继续集成继续交付是进步研发效率、保障产品质量至关重要的一环,咱们编写了一系列构建组件,通过TFS进行组件编排,实现不同环境的继续集成和交付需要。 图6 TFS构建中的组件编排 C零碎前台应用java语言开发,以一个残缺程序包的模式进行公布。对于日常的研发,将构建公布配置为定时模式,每周一至周五12:00和18:00定时主动构建公布,满足日常测试须要。 图7 定时构建公布配置 对于时效性强的敏捷类我的项目,将构建公布配置为实时模式,每当有代码提交时便触发构建公布,测试人员可及时染指,缩短开发测试周期。 图8 实时构建公布配置 C零碎后盾性能应用c语言开发,运行在AIX平台,无奈间接应用TFS的构建性能,通过一系列的技术攻关,咱们借助Jenkins自主实现了一套c程序构建公布的办法,解决了TFS Agent不反对AIX平台的技术难题,对立了C零碎前后台的构建公布流程,为开发人员提供了简洁统一的应用体验。 图9 基于AIX平台的C程序构建流程 c程序具备绝对独立、依赖关系弱的特点,所以均采纳由开发人员自主触发的实时交易构建公布模式,每个开发人员可按需独立公布程序,在构建参数中填入待发布的程序名即可。 图10 C程序自主构建公布 1.4 自动化测试版本品质是研发的基本落脚点。咱们构建了基于Ant+Junit+Selenium的功能测试框架,将测试流程集成到继续集成和交付流水线,实现了业务测试版本和准生产版本的回归测试,每日定时执行业务外围流程案例,缩短了版本验证工夫,晋升了投产版本的可靠性,无效升高了投产危险。 二、端到端的版本交付流程设计与实现2.1 需要条目化和开发项目经理从我的项目的角度,以“我的项目->模块->性能->工作”构造对需要进行条目化拆分,录入TFS,由我的项目组成员实现工作认领。随后基于各自的工作发展需要剖析、设计、开发和测试等工作。 图11 TFS工作项治理档次 图12 TFS工作项示例 在TFS中配置开发分支主动编译,当TFS检测到新的提交后,获取代码并主动编译,若编译失败,则会主动向代码提交人发送邮件告诉。 ...

February 19, 2021 · 1 min · jiezi

关于持续集成:如何将-github-上的代码一键部署到服务器

在 Github 上看到一些不错的仓库,想要奉献代码怎么办?在 Github 上看到一些有用的网站,想部署到本人的服务器怎么办?。。。我想很多人都碰到过这个问题。 如果要奉献代码,之前我的做法通常是将代码克隆到本地,而后在本地的编辑器中批改并提交 pr。如果想部署到本人的服务器,之前我的做法通常是克隆到本地,而后本地批改一下部署的配置,最初部署到本人的服务器或者第三方的云服务器(比方 Github Pages)。而当初随着云技术的遍及,咱们没有必要将代码克隆到本地进行操作,而是间接在云端编辑器中实现批改,开发,并间接部署到云服务器。明天就给大家举荐一个工具,一键将代码部署到云服务器。 什么是一键部署?明天给大家介绍的就是一键部署。那什么是一键部署呢?顾名思义,就是有一个按钮,点击一下就能实现部署工作。 如下是一个领有一键部署按钮的我的项目: 点击之后进入如下页面,你能够对一些默认配置进行批改(也能够间接应用默认配置): 批改后点击Deploy app 即可。部署胜利之后就能够通过相似如下的地址拜访啦~ 图中演示地址是:https://leetcode-cheat.heroku...大家能够间接进我的仓库 https://github.com/leetcode-p...,点击部署按钮试试哦。 它是如何实现的呢?我是一个喜爱探索事物原理的人,当然对它们的原理一目了然才行。其实它的原理很容易,咱们从头开始说。 1. 如何在 Github 中显示公布按钮。下面的部署按钮就是如下的一个 Markdown 内容渲染的: [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)下面内容会被渲染成如下的 DOM: <a href="https://heroku.com/deploy" rel="nofollow" ><img src="https://camo.githubusercontent.com/6979881d5a96b7b18a057083bb8aeb87ba35fc279452e29034c1e1c49ade0636/68747470733a2f2f7777772e6865726f6b7563646e2e636f6d2f6465706c6f792f627574746f6e2e737667" alt="Deploy" data-canonical-src="https://www.herokucdn.com/deploy/button.svg" style="max-width:100%;"/></a>也就是说其实就是一个被 a 标签包裹的 svg 图片,点击之后会实现 url 跳转。 2. 云服务厂商如何获取默认配置?这里以 heroku 为例,其余厂商(比方腾讯)原理都差不多。 因为下面的起因,实际上咱们传递给第三方云厂商的形式只可能是 url。因而咱们能够间接将配置通过 ur 的形式传输。比方 https://heroku.com/deploy?a=1... 。 这种形式对于大量数据是足够的,那如何数据量很大呢?咱们晓得浏览器 url 的长度是无限的,而且不同的浏览器限度也不尽相同。 那怎么解决呢?当初比拟风行的思路是约定。以 heroku 来说,就约定根目录的 app.json 文件中存配置,这种约定的形式我集体强烈推荐。 比方我的仓库的 app.json 就是: { "name": "LeetCode Cheatsheet", "description": "力扣加加,或者是西湖区最好的算法题解", "repository": "https://github.com/leetcode-pp/leetcode-cheat", "logo": "https://tva1.sinaimg.cn/large/008eGmZEly1gnm68epc0kj30u00tsaav.jpg", "keywords": ["github", "leetcode", "cheatsheet", "91algo", "algorithm"], "env": { "REACT_APP_BUILD_TARGET": { "description": "枚举值:extension 和 web", "value": null }, "PUBLIC_URL": { "description": "动态资源寄存地位(可应用 cdn 减速)", "value": "https://cdn.jsdelivr.net/gh/leetcode-pp/leetcode-cheat@gh-pages/" } }, "buildpacks": [ { "url": "https://buildpack-registry.s3.amazonaws.com/buildpacks/mars/create-react-app.tgz" } ]}能够看出,除了配置仓库,logo,形容这些惯例信息,我还配置了环境变量和 buidpacks。buildpacks 简略来说就是构建利用的形式, 对于 buildpacks 的更多信息能够参考 heroku 官网文档 ...

February 18, 2021 · 1 min · jiezi

关于持续集成:CODING-X-CLife云端-DevOps-加速企业数智化

数联天下,智造生存数字化开始从抽象化、标准化走向智能化 2020 给全民遍及了什么是线上化、数字化、智能化,也减速了企业的数字化转型。“全数字化”时代,曾经不仅仅是简略粗放的数据采集、映射、形象。数字化开始迈入高级阶段——数据驱动的智能化:基于云管端 + AIoT 等为代表的新技术群落开始大量涌现,数智化企业思考的外围问题转向了如何以客户经营为外围,通过智能化伎俩进步客户全生命周期的体验。 作为物联网大数据行业的排头兵,深圳数联天下智能科技有限公司(以下简称数联天下)倾力打造的 C-Life 大数据综合计算服务平台,致力于为集体、行业、政府提供全周期、全链条、全维度、全方位的专业级经营参谋式服务。依靠着公司弱小的研发投入与技术实力,数联天下在智慧养老、智慧衰弱校园、智慧美业、智慧家庭、智慧酒店、智慧农业、智慧水生态等多个智慧畛域,打造了一批又一批的标杆示范我的项目。 DevOps 带动研发流程数字化企业的敏捷性、适应性、反脆弱性,决定其在这场数字化颠覆中的胜与负 在交付各个领域的智慧我的项目过程当中,数联天下的研发部门逐步发现问题:研发团队面对的是一个更加不确定、个性化、碎片化的市场需求。行业我的项目尽管存在着肯定的通用性,但也就地取材的存在大量定制化需要。如何让个性化与规模化齐头并进?多变的客户需要带动了研发组织发展与业务相适应的调整。通过研发流程数字化晋升研发流程的敏捷性、适应性、反脆弱性,数联天下开启了研发提效之路。 数联天下研发团队和咱们分享道:“客户我的项目周期缓和,需要变动比拟频繁,开发团队须要在短时间内实现软件开发并公布上线。而在之前的研发流程当中:公布流程长,审批环节多,公布节奏迟缓,开发运维之间没有良好合作来晋升公布效率。所以亟需突破跨部门之间的壁垒,缩小开发、测试、运维之间的沟通环节、沟通老本。DevOps 是咱们在较短开发周期内开发高质量软件的首选办法,心愿通过应用 DevOps 平台 —— CODING 来晋升客户满意度。” 区别于之前通过多个工具自建研发流程,数联天下团队首先基于 CODING 的继续集成、制品库、继续部署逐渐晋升交付带宽,再将项目管理、研发数据管理等流程对立至 CODING ,渐进式实现研发流程从需要提出到利用部署的价值交付,从而让研发团队各个角色基于对立平台通力协作,按期保质交付我的项目。 继续交付驱动业务减速 在应用 CODING 的过程中,数联天下研发团队遵循着循序渐进的路线。首先基于 CODING 继续集成、制品库、继续部署建设继续交付流水线。区别于自建 Jenkins 与 Nexus,CODING 的继续集成与制品库开箱即用,研发团队通过继续集成构建好的 Docker 镜像能够间接推送到 CODING 制品库中,再通过继续部署拉取指定版本镜像进行部署。 开箱即用的继续集成CODING 继续集成在构建脚本语法上全面兼容 Jenkins,反对数联天下无缝地迁徙 Jenkins 的构建到 CODING 中。并且反对 Docker 镜像的构建,在根底性能上满足了研发团队对构建制品的迁徙需要。 在应用上,CODING 比自建 Jenkins 要不便许多,关上浏览器就能够应用,不须要繁琐的机器配置、构建环境搭建、软件插件装置。而且 CODING 提供了多地区境内外构建节点,并优化国内拜访海内支流镜像链路,反对构建工作中开启缓存,大大晋升了构建速度。在构建资源的灵活性上,既反对数联天下应用 CODING 云主机进行构建,也反对数联天下将应用中的腾讯云机器设置为构建资源。 企业级的制品仓库在应用 CODING 制品库之前,数联天下团队基于开源我的项目自建制品库,在应用自建私服制品库经常遇到性能问题或易用性问题,比方一上传大容量的 Docker 镜像时,自建的制品库就经常服务不可用,导致后续一系列的版本公布碰壁,应用 CODING 后这类问题就迎刃而解了。CODING 制品库是专为生产环境打造的企业级制品库,无论是制品库的容量、散发效率都通过产品团队精心优化。数联天下团队将所有制品推送至 CODING 制品库,利用 CODING 制品库提供的版本策略、权限管制、平安扫描等能力对制品进行了标准治理。 ...

February 4, 2021 · 1 min · jiezi

关于持续集成:别当工具人了手摸手教会你-Jenkins

大家好,我是小菜,一个渴望在互联网行业做到蔡不菜的小菜。可柔可刚,点赞则柔,白嫖则刚! 死鬼~看完记得给我来个三连哦! 本文次要介绍 Jenkins如有须要,能够参考 如有帮忙,不忘 点赞 ❥ 微信公众号已开启,小菜良记,没关注的同学们记得关注哦! “唉,每天提交完代码都得本人打包再部署到测试环境和开发环境,好麻烦啊!都快变成运维了” “啊?哦!的确,每天打包部署的确都成为了工具人了” 一段简白的对话疾速的隐灭在办公室中,却引发了我的思考,“这么麻烦的过程必定曾经有了很好的解决方案,毕竟程序员是面向懈怠编程,本人对 Jenkins 这个工具有所耳闻曾经很久了,看来明天得对它下手了” 说干就干,明天咱们就来求索一下 JenKins,看完你无妨也给你们我的项目整一个,给本人多减少点划水的工夫! 读前须知: 本文较长,从装置到应用,一步步带你超神!微信公众号关注: [ 小菜良记 ] ,带你领略技术风骚! 一、Jenkins 是什么Jenkins是一个开源软件我的项目,是基于java开发的一种继续集成工具,用于监控继续反复的工作,旨在提供一个凋谢易用的软件平台,使软件的继续集成变成可能。简略来说,它就是一个 继续集成 的工具! 1. 继续集成继续集成(Continuous Integration),简称 CI。频繁地将代码集成到骨干之前,必须通过自动化测试,只有有一个测试用例失败,就不能集成。通过继续集成,团队能够疾速从一个性能到另外一个性能。 益处: 升高危险,因为继续集成一直去构建,编译和测试,能够很早发现问题缩小重复性的工作继续部署,提供可部署单元包继续交付可供使用的版本2. Jenkins 继续集成 咱们先通过这张图来看到 Jenkins 在其中起到的作用: 首先,开发人员将代码提交到 Git 仓库而后 Jenkins 应用 Git 插件来拉取 Git 仓库的代码,而后配合 JDK、Maven 等软件实现代码编译,测试、审查、、测试和打包等工作最初 Jenkins 将生成的 jar/war 推送到 测试/生产 服务器 ,供用户拜访整套步骤下来,作为开发人员咱们只须要提交下代码,剩下的工作都交给了 Jenkins ,真是美滋滋,怎么没有早点上这个工具的车! 二、Jenkins 装置磨刀不误砍柴工,没刀的状况下说再多都是虚的。咱们就先来看下 Jenkins 是如何装置的吧! 1. 装置JDK因为 Jenkins 是 java 写的,所以要运行起来必须要配置 java 运行环境。这里就不赘诉 JDK 的装置过程了 ...

December 13, 2020 · 5 min · jiezi

关于持续集成:如何用-CI-持续集成-保证研发质量

本文来自OPPO互联网根底技术团队,转载请注名作者。同时欢送关注咱们的公众号:OPPO_tech,与你分享OPPO前沿互联网技术及流动。1. 背景分布式技术的倒退粗浅地扭转了咱们编程的模式和思考软件的模式。分布式很好的解决性能扩大,可靠性,组件可用性等问题,然而单机转变成分布式却加大了零碎的复杂性,对于组件的开发,测试,部署,公布都提出更高的要求。那么,针对简单的分布式系统怎么保障软件品质和零碎的稳定性?首先看下,传统软件产品流动的大抵流程,简化流程大略是 3 大块: 开发 -> QA -> 灰度上线!个别如下图: 流程有个很大的问题,品质全靠 QA 测,对接全靠人力,沟通老本大,脱漏问题多,个别有几个常见的问题: QA 很难每次都测试全面,毕竟QA毕竟是人,人的主观因素太大,有时候人为判断感觉简略,不必测的中央很可能有漏了。或者感觉批改点太简略,感觉不至于出问题,就不再全面的测试。以至于可能会有基本功能问题;测试速度慢,效率太低,QA 资源节约,如果每次 QA 都须要全量的测试,那么反复工作太多,效率太低,成果也不好,对于这些反复工作,本能够更好,更快的解决,不至于 QA 就为了测试这么点货色,而没有精力去做更多的事件;甚至说编译不过的代码都有可能脱漏到 QA;闭环太慢,开发性能如果有问题,等到 QA 测进去,让后再反馈到开发这个闭环就太慢了。更不用说,问题漏到线上,再反馈到开发人员,那么戴江就更大了;多个开发人员并行开发的时候,工作可能相互影响,小问题越积越多,性能集成的时候可能十分耗时;咱们提出的改良点: 外围点之一:问题发现要早,发现越早,代价越小;外围点之一:问题闭环要快,闭环越快,效率越高;反复工作自动化,缩小人的有效劳作;多开发人员的时候,性能继续集成,问题拆小,提前发现;最外围的一点就是:”自动化闭环问题“。 以后的简单的软件系统对品质和效率提出了更高的要求,所以响应的软件流动必须要高度自动化能力达到要求。自动化触发、自动化测试、自动化闭环、自动化公布、自动化卡点等一系列的保障,所有可能当时预知且可固化的行为都应该自动化,把效率和品质晋升,而让人去做更聪慧的事件。 咱们的思考:近些年来,对于自动化有 Continuous Integration,Continuous Delivery,Continuous Deployment 的一些实践和实际。这三者来说,突出“继续”二字,“继续”是为了达到“快”的目标,“疾速迭代”,“疾速响应”,“疾速闭环”,“快”是外围竞争力。个别大家的共识流程分类如下: 对于开发者来说,接触到更多的是 Continuous Integration(继续集成),CI 把通过自动化,把流程固化下来,保障代码集成的有序、牢靠,确保版本可控,问题可追溯,代码的流动中通过自动化,升高了人为主观的出错率,进步速度,进步版本品质和效率。 2. CI 是什么?CI 即是继续集成(Continuous Integration),是当今软件流动中至关重要的一环。CI 个别由开发人员递交代码改变所触发,CI 在两头环境做自动化验证,CI 验证过后,即通过了根本质量保证,那么就能够容许下一步的软件流动。 继续集成说白了就是一种软件开发实际,即团队开发成员尽可能的快的集成,每次集成通过自动化的构建(包含编译,公布,自动化测试)来验证,从而尽早地发现集成谬误。因为问题发现的越早,那么问题解决的老本就越少。 一般来说,继续集成须要买通几个环节: 代码提交(git)工作构建(jenkins)部署测试(ansible,shell,puppet)划重点:CI 过程由代码流动触发。 代码流动关注两个工夫点: Pre-Merge :代码改变合入主干分支前夕触发。集成的对象是代码改变与骨干最新代码 Merge 之后的代码,目标是验证代码改变是否可能合入主干;Post-Merge :代码改变合入主干分支之后触发。集成对象就是最新的骨干分支代码,目标是验证合入改变代码之后骨干是否可能失常工作;Pre-Merge 和 Post-Merge 关注点不同,缺一不可。差别在哪里?如果只有一个开发者,那么 Pre-Merge 和 Post-Merge 的测试对象是雷同的。在多个开发者递交代码的时候,Pre-Merge 和 Post-Merge 就会出现差别,他们的 CI 测试对象不同。 ...

November 13, 2020 · 5 min · jiezi

关于持续集成:实践解读丨Python-面向对象三大特征之多态

摘要:多态从字面意思上看就是多种状态,在咱们python的面向对象里就是不同的对象在接管雷同办法或者函数时会产生不同的行为,也就是说,每个对象能够用本人的形式去响应独特的函数,不同的形式实现不同的后果。多态从字面意思上看就是多种状态,比方人有黑种人,黄种人,白种人等等,这就是一类事物的不同状态,在咱们python的面向对象里就是不同的对象在接管雷同办法或者函数时会产生不同的行为,也就是说,每个对象能够用本人的形式去响应独特的函数,不同的形式实现不同的后果。 多态1、多态多态指的是一类事物有多种状态 动物有多种状态:人,狗,猪 import abcclass Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): passclass People(Animal): #动物的状态之一:人 def talk(self): print('say hello')class Dog(Animal): #动物的状态之二:狗 def talk(self): print('say wangwang')class Pig(Animal): #动物的状态之三:猪 def talk(self): print('say aoao')文件有多种状态:文本文件,可执行文件 import abcclass File(metaclass=abc.ABCMeta): #同一类事物:文件 @abc.abstractmethod def click(self): passclass Text(File): #文件的状态之一:文本文件 def click(self): print('open file')class ExeFile(File): #文件的状态之二:可执行文件 def click(self): print('execute file')2、多态性一 什么是多态动静绑定(在继承的背景下应用时,有时也称为多态性) 多态性是指在不思考实例类型的状况下应用实例 在面向对象办法中个别是这样表述多态性: 向不同的对象发送同一条音讯(!!!obj.func():是调用了obj的办法func,又称为向obj发送了一条音讯func),不同的对象在接管时会产生不同的行为(即办法)。 也就是说,每个对象能够用本人的形式去响应独特的音讯。所谓音讯,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。 比方:老师.下课铃响了(),学生.下课铃响了(),老师执行的是上班操作,学生执行的是放学操作,尽管二者音讯一样,然而执行的成果不同peo=People()dog=Dog()pig=Pig()#peo、dog、pig都是动物,只有是动物必定有talk办法#于是咱们能够不必思考它们三者的具体是什么类型,而间接应用peo.talk()dog.talk()pig.talk()#更进一步,咱们能够定义一个对立的接口来应用def func(obj): obj.talk()鸭子类型逗比时刻: Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’ python程序员通常依据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,能够继承该对象 也能够创立一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保留程序组件的松耦合度。 例1:利用规范库中定义的各种‘与文件相似’的对象,只管这些对象的工作形式像文件,但他们没有继承内置文件对象的办法 例2:序列类型有多种状态:字符串,列表,元组,但他们间接没有间接的继承关系 #二者都像鸭子,二者看起来都像文件,因此就能够当文件一样去用class TxtFile: def read(self): pass def write(self): passclass DiskFile: def read(self): pass def write(self): pass点击关注,第一工夫理解华为云陈腐技术~ ...

September 21, 2020 · 1 min · jiezi

关于持续集成:90的开发都没搞懂的CI和CD

摘要:对于CI/CD你搞懂了吗?据IDC统计,2017年,DevOps的寰球软件市场已达到约39亿美元的程度,预计到2022年市场将达到80亿美元左右! 在麻利软件开发环境中,工作模型和操作须要对公司一直变动的需要具备超级灵便的能力。DevOps——一种工具和实际的联合,有助于软件开发与IT运维并携手共进。这种跨性能的工作模式旨在最小化零碎开发生命周期的持续时间,并提供继续的部署和交付。 施行CI和CD的形式你可能有很多想法,你的产品创意可能是最好的,但如果你不常常交付新版本,那么你将很难与周边的竞争对手匹敌。继续集成(CI)和继续交付与部署(CD)是对代码的所有次要和主要更改集成到一起并一起交付,或者增加新性能或产品,甚至能够是Bug修复。这些代码更改始终保持可部署状态,并主动公布到预生产环境中。通常状况下,这种状况会在一天内至多产生一次或屡次。这种实际将激励频繁地提交小的更改,而不是不频繁地提交大的更改。 CI/CD管道的渗透性CI/CD管道是将软件应用程序交付给客户或客户端的一种路径。这个过程要通过继续的集成,即增加代码更改或批改现有代码、自动测试阶段、交付更改,以及随后部署到登台环境中。它自动化了软件开发中波及的所有步骤。 CI/CD管道中的各个阶段源代码/提交阶段 这一阶段次要是减少新的性能,或者是对现有的工作模式进行一些小的批改,以便更无效地工作以满足客户的需要。管道在这里由源代码存储库触发。代码中的任何更改都会触发告诉。 构建阶段 编译源代码,零碎在构建阶段运行单元测试。一旦单元测试通过,集成测试就实现了。这个阶段呈现的所有问题都必须立刻解决。Docker工具用于创立服务器并将数据挪动到注册表中,以便为下一个测试阶段做好筹备。 测试阶段 自动测试在这个阶段进行,以确保整个软件中没有Bug,同时也查看软件是否满足预期性能。这些测试从最终用户的角度进行,以验证代码的品质。测试阶段的失败表明代码的不精确,这会导致开发人员返工,测试循环持续进行。 部署阶段 一旦软件通过测试阶段,可执行程序就能够部署到生产环境中了。在将它们间接推送到生产环境之前,最好有一个外部工作就像生产工具一样的登台环境。登台环境充当额定的测试和评审。一旦它通过测试和审查不存在Bug,程序被部署到生产中。 CI/CD管道长处一览表构建任何软件的次要目标都是为问题提供强壮的解决方案。软件必须是精确的,最小化所波及的危险,并且应该尽快交付给客户。CI/CD管道有助于构建这种强壮而精确的软件。如果一个公司适应了麻利办法中的CI/CD管道,那么它能够失去以下益处: ●通过单元测试和功能测试,在每次迭代中检测到不精确的代码和不统一的构造。 ●故障检测和修复率的进步导致新公布日的减少。这将有助于产品团队将更多精力集中在客户对产品工作的新需要上。对公布的性能进行疾速反馈是为了达到这个目标。 ●通过品质和压力测试来测试产品的耐用性。 ●CI/CD管道中的代码更改绝对较小,这是通过以更快的速度集成代码片段来实现的。 ●当代码谬误呈现时,通过拆散代码谬误,代码更改更小,均匀解决工夫越短。 CI/CD管道对开发和运维的重要性在软件反动的新时代,开发人员和运维人员一起工作。这种状况下,两者的指标往往是绝对独立且明确的,会导致环境中的凌乱。开发人员和运维人员通过一组正式称为“DevOps”的工具和实际进行联合。CI/CD管道是DevOps实际和工具的支柱。DevOps遵循继续集成、继续交付的准则,并通过自动化测试进行开发。 高速度 在其工作模型中蕴含CI/CD管道的软件应用程序通过一直的反馈流动对代码中的更改或新个性的增加做出更快的响应。 效率进步 随着响应变得更快,新的代码更改将无效地实现到应用程序中,从而进步了生产率。 开发周期较短的高质量软件 因为CI/CD流水线中的每个过程都可自动化,使得软件开发的生命周期缩短。尽管生命周期较短,但通过一直反馈和定期施行订正的程序,仍可对品质放弃亲密监督。 可靠性 CI/CD管道始终是牢靠的,在运行时不会反弹。当运行时因为多个失败而碰壁时,开发人员会感到丧气。因为在CI/CD管道中有恒定的反馈和故障拆散,使得软件更加牢靠和易于应用。 升高测试老本 因为测试是自动化的,管道能够在几秒钟内解决数百个测试,并提供牢靠的输入。在传统的软件开发模型中,成千盈百的测试破费了大量的老本。在DevOps中,测试老本不高,而且运行速度十分快。 华为云DevCloud 践行DevOps理念,从组织、流程、工具、环境等几个方面来承载DevOps的残缺实际过程。目前曾经提供13个服务,3个行业解决方案,笼罩软件交付的全生命周期,打造全云化研发场景,开发、测试、部署、运维、经营等一起研发流动都在云中实现,包含在云上编码调试,全面撑持落地DevOps。目前,曾经有30多万个软件我的项目运行在华为云DevCloud上,15万开发者抉择了华为云DevCloud作为工作平台,极大地晋升了开发者的工作效率。华为云DevCloud将逐渐汇聚百万开发者,构筑更加广大的软件生态。 点击关注,第一工夫理解华为云陈腐技术~

September 21, 2020 · 1 min · jiezi

关于持续集成:前端面试每日-31-第500天

明天的知识点 (2020.08.28) —— 第500天 (我也要出题)[html] 跨域通信有哪些形式?[css] 说说CSS对元素属性赋值的具体过程?[js] 在js中undefined和not defined的区别是什么?[软技能] 说说你对继续集成的了解,它解决什么问题以及如何在前端中使用?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!!欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨!心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

August 28, 2020 · 1 min · jiezi

一分钟开始持续集成之旅系列之微信公众号服务器端应用以-Java-后端为基础

作者:CODING - 朱增辉前言本文是 CODING 持续集成自定义构建节点功能 的使用教程,通过一个为微信公众号启用开发配置的 Demo 演示,讲解如何接入自定义构建节点,如何使用自定义构建节点进行构建、测试、部署服务器。 准备工作环境本文会使用到如下工具,请确认已安装,或者根据链接的文档进行安装。 gitJavaMaven开发微信公众号还需要提前准备好下面两项资源。 微信公众号微信公众号可以在微信公众平台官网申请,平台也提供了详细的开发帮助文档。 服务器这里的服务器指的是能够让微信服务器访问到的计算机,用来运行本文的服务端程序。很多公司都提供了云服务器租赁,还是很方便获取的。这里推荐腾讯云平台的 CVM,临时用的话,竞价实例真的很划算。 代码本文重点是介绍 CODING 平台持续集成自定义构建节点功能,具体的业务逻辑并不重要,这里已提前准备好了一份演示代码,可以结合下面的步骤实际操作。 代码本身比较简单,需要特别说明的是,为了能够重复部署,代码引入了 Spring Boot Actuator 支持调用 API 退出服务器进程。 步骤一 准备构建计划在左侧菜单栏选择构建计划,在打开的页面中点击新建构建计划配置。 为简化构建计划配置,CODING 提供了丰富的模板供选择,这里我们选择 Java 编译部署 jar 包模板。 该模板支持将构建出的 jar 包通过 ssh 的方式传输到远端服务器,并执行命令启动。本文使用自定义构建节点的方式,可以直接在服务器上进行构建、部署,不需要传输,因此这里远端服务器的配置信息留空即可。 调整后的构建脚本(即代码中 Jenkinsfile 文件的内容)如下,您可以在此基础上按自己的需要调整。 def VERSION = ""pipeline { agent any stages { stage('检出') { steps { checkout([$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[ url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID ]]]) script { def pom = readMavenPom() VERSION = pom.getVersion() println "current version ${VERSION}" } } } stage('单元测试') { steps { sh 'mvn clean test' } } stage('编译') { steps { sh 'mvn clean package -Dmaven.test.skip=true' } } stage('部署') { steps { sh "curl -X POST localhost/actuator/shutdown || true" sh "JENKINS_NODE_COOKIE=dontKillMe nohup java -Dserver.port=80 -jar ${env.WORKSPACE}/target/demo-${VERSION}.jar > log &" } } }}这里有两点需要特别说明: (1)为方便重复部署,构建脚本在部署前会调用 actuator/shutdown API 退出正在运行的服务进程。 (2)CODING CI 底层是基于 Jenkins 实现的,而 Jenkins 在构建任务结束后会停掉此次任务创建出来的所有进程,因此在部署时添加了环境变量 JENKINS_NODE_COOKIE=dontKillMe 以阻止 Jenkins 停掉部署的服务器进程。 ...

June 29, 2020 · 1 min · jiezi

弹性配置为构建提速-CODING-腾讯云-CVM-最佳实践

CODING 中提供了内置云主机用来执行持续集成(CI)中的构建计划,能够胜任大部分构建任务。但如果碰上了大型项目的构建,或者需要在本地服务器生成构建成果,单个计算资源就显得有点捉急了。针对这一部分需求,CODING 现已支持接入第三方计算资源作为构建节点,甚至可以接入多个服务器共同作为构建节点池,打造专属的计算集群。 下面将会以腾讯云 CVM 为例,演示如何在 CODING 持续集成中接入自己的计算资源。 开通安全组在购买了腾讯云 CVM 后,第一件要做的事情就是开放相应的安全组策略,入站和出站规则都需要设置。 登录服务器在【操作】中点击登录,按照提示输入 root 密码。如果忘记密码可以在【更多】>【密码/密钥】中点击【重置密码】后再次输入即可。 做完上述操作并成功登录服务器后,可以选择 Docker 或 cci-agent 两种方式将服务器接入至构建节点池。如果想使用与 CODING 官方提供的运行节点一致的环境,请选择使用 Docker 运行构建节点。如果想使用节点上自带的环境,譬如需要使用 MacOS 上的 Xcode 编译 iOS 应用,请选择 cci-agent 方式进行接入。 接入构建节点池使用 Docker(推荐)使用 Docker 的前提是服务器上已经安装了 Docker。需要注意的是,部分 openVZ 虚拟化的服务器因内核较低,无法成功安装 Docker,当然我们的腾讯云 CVM 是没有这个问题的。下面使用 curl 命令安装 Docker。 curl -fsSL https://get.docker.com/ | sh待 Docker 安装完成后,前往 CODING 进入【项目】>【持续集成】>【构建节点】,在构建节点页复制配置命令。 等待一小会,等镜像构建完成后便会提示构建成功。 在 CODING 构建节点页也可以看到新注册上线的服务器。 手动接入 cci-agent在 CODING 的构建节点页一键生成初始化命令,并在服务器中运行该命令。 ...

June 24, 2020 · 1 min · jiezi

一分钟开始持续集成之旅系列之C-语言-Makefile

作者:CODING - 朱增辉前言make 工具非常强大,配合 makefile 文件可以实现软件的自动化构建,但是执行 make 命令依然需要经历手动输入执行、等待编译完成、将目标文件转移到合适位置等过程,我们真正关心的是最终的输出,却在这些中间过程上浪费了很多时间。利用 CODING 持续集成功能可以实现自动触发构建,构建全程自动化,无须分心看护,节省时间。 本文通过一个 C 语言 + Makefile Demo 项目讲解如何使用 CODING 持续集成功能创建构建计划,自动触发构建,以及如何将生成的目标文件发布到 CODING generic 制品库。 准备工作环境本文涉及到以下工具,请确认已存在,或者根据链接的文档进行安装。 gitmakegcc另外,您还需准备一个 CODING 项目。 代码我已经准备了一份简单的示例代码,使用 make 工具构建 Hello-world 程序。 // hello.c#include <stdio.h>int main() { printf("Hello, World!\n"); return 0;}您可以通过下面的命令克隆到本地。 git clone https://e.coding.net/coding-public/demo-c-make.git仓库中还包含了一个 makefile 文件,定义了简单的规则来完成软件构建。 all: hellohello: hello.o gcc -o hello hello.ohello.o: hello.c gcc -c hello.cclean: rm -rf hello.o hello您可以在本地执行 make 命令以验证构建正常。 下面我们正式开始通过一个 Demo 演示 CODING 平台持续集成功能的使用。 ...

June 23, 2020 · 1 min · jiezi

避开这2个误区测试目标-KPI-不再难设

阿里妹导读:好的开始是成功的一半!工作中,目标的设置是最不能马虎的事情。今天,我们请来孙阳(阿里巴巴测试开发专家),他从11年入职至今已有8年。在测试技术目标的KPI设置上,他有一些想法要与你分享。常见误区误区一:我能做什么,就做什么? 我们在讲测试能力建设的时候,往往会说我们有什么样的问题,所以要建什么样的测试能力,要做到什么样之类。这里经常能看到大家在设置目标的时候,思考路径往往是“我能做什么,我要怎么做”。 比如,海外没有真机环境,所以我们需要建设海外真机环境。接下去就会想到我们在海外有办公室,所以上半年的目标就是在海外办公室部署真机环境,技术方案上可以采用某个方案。 看上去没有什么问题,但是如果你仔细想一想,就会发现这个目标其实禁不起推敲。上半年建了海外环境,那下半年要建什么?这当中对国家选择的标准是什么?对真机环境建设的成本、稳定性、速度、可移植性等要怎么衡量?如果只是觉得业务上需要海外环境,我也能做海外环境,就去做了,那在方案选择上可能就会存在局限性,比如当前的方案就很依赖办公网的建设,其实不利于在世界范围内复制。 这种定目标的方式,很容易变成:今年没有能力,我建了某个能力,明年我发现这个能力不完善,然后我又做了优化一二三。这样做规划, 没有体系,缺乏前瞻性,也看不到终局。 误区二:拿手段当目标 有的同学说,我要做自动化调度中心,整合各种自动化平台,解决自动化调度问题,统一所有自动化测试件的执行。上半年的目标就是把平台重构,接入测试件类型一二三四。 这就是典型的拿手段当目标了,我们做自动化调度中心,这是一个手段,而不是目标。 目标是要结合业务测试的痛点问题来的,比如,目前自动化能力分散,在持续集成能力落地时,自动化能力集成成本高。那这时候我建立调动中心的目的就变成了降低持续集成自动化集成成本,然后就可以对这个成本进行度量,以描述我达到的阶段。同时,对平台集成能力也可以进行度量,建立你的子目标:比如可扩展性、稳定性等等。 技术目标设置的思考路径在说思考路径之前,我想先分析一下,一般的技术目标有哪几种类型。 在质量团队来说,一般我们的技术目标会有两种,一种是做原子能力,解决某一类问题,比如UI自动化、接口自动化、doom等等;二是建一个整合平台,做原子能力的调度,打整体效果。 那么接下来我就以活动质量中心的目标设置来谈一下我的思考路径。 平台整合型 我们在说到平台整合的时候,往往给自己找的价值点都是:降低工具使用成本、沉淀保障策略之类,要降低工具使用成本,其实一个门户网站做个导航可能就能解决问题;而沉淀保障策略,一个文档也能解决问题。所以如果你把价值定位在这两个方面,最多就是量变,很难做出质变。其核心问题是: 没有对业务的测试工作产生改变 ,也就是目标和价值没有想清楚。 定义目标我认为,做平台能力整合,想要做出质变, 一定是要对工作模式发生一些变化的 。你把一堆能力整合到一起,肯定是希望这些能力能够在某一件事情上产生合力,而这个合力所产生的效果,我认为就是能够对这件事情的模式,产生一些变化。 比如,aone(研发工具平台)整合了一堆能力,改变了研发的工作模式。 那么要怎么去思考这样的变化呢?我觉得有以下几个步骤: 1)先从问题出发,聚焦到一个域,定义出当前工作模式的一个状态,即:当下的阶段。 2)把目光放长远,从三年后往回看,你期望的工作模式是什么?即:愿景的阶段。 3)一年内我期望给工作带来的变化是什么?即:短期目标。 按照这个三个步骤去拆解问题,把终局和阶段想清楚,就能把平台的工作的价值整明白了。 能力建设在定义清楚当前阶段、愿景和目标之后,我们就需要来看Action是什么了,也即是说,为了实现我的目标和愿景,我需要做的事情有哪些。 这时候我就可以根据目标进行拆解,明确哪些是平台架构需要完成的,哪些是原子能力需要提升的,然后看当前的短板在哪里,重点投入兵力建设。 举个例子以活动质量中心为例,我们先来灵魂拷问: 当下我们对会场的质量保障模式是:S级(重大项目)大促半自动化、日常活动全裸奔; 如果往后做三年,我希望给这件带来的变化是:以场景化的方式、针对不同活动,提供个性化的全自动化保障策略; 一年内我能达到的台阶:所有营销类活动全自动化保障。 在定义清楚目标之后,就要来看达成目标我需要建设的能力了。 比如,我要在今年实现所有营销类活动全自动化保障,我就需要做这几件事情: 1)建立活动质量中心,和研发活动一体化系统对接,实现关键节点(选品、搭建)环境的自动化检测和流程卡口。 2)针对会场特色,把核心原子能力做厚。 而往三年目标走的话,我还需要:沉淀保障能力模板,针对不同类型活动提供场景化解决方案(比如3C和大工业);活动覆盖面拓展,系统对接导购系统等。那这些的优先级在本财年就会被降低。 平台能力整合型的,我认为大概就是这个思路了,下面再来看看原子能力型的。 原子能力型 所谓原子能力,一定是解决某一类型问题的,比如会场UI自动化,解决的就是会场UI层质量问题。 针对原子能力的KPI,我认为其思考路径应该是这样的:先定义问题,再定义目标,然后思考需要能力项,再根据指标思考方案和实施路径。 定义问题明确当前的问题是什么,这里对问题的分析需要更加全面,要有抽象能力。比如当你遇到了一个单点的问题,可以思考这个问题是否具备通用性,可能一个个例问题背后,是一个普遍的现象。而越是抽象的问题,解决的难度越大,而价值也越大。 以活动会场UI自动化为例,开始我想解决的是S级(重大项目)大促会场质量保障的问题,后来想想这东西一年用两次,不划算,而日常几百次的营销活动会场都是裸奔,为什么我不能把S级(重大项目)大促保障的思路复用到日常会场呢?然后再往外延展,导购活动的页面质量,能不能用同样的思路解决呢?最终,我定义的会场UI自动化能力要解决的问题就是:所有活动类型的会场UI质量保障。 定义目标和能力项所谓的价值,就是要把问题解决到什么程度。问题解决得越彻底,价值越大,所以我们在解决问题的时候,姿势一定帅,不能是一个临时方案,而要有长效机制。 在明确了目标之后,就可以分析要实现这个目标,我们所需要的能力项有哪些了。 还是以活动会场UI自动化为例,作为测试能力,我认为必须能够替代手工测试。比如破图、死链、样式错乱、空楼层、空白品、重复品、无价格品等等影响用户体验的问题。所以,对于问题的覆盖面肯定有要求。 然后,运行速度要快,要给运营及时的反馈,否则做为发布卡点,体验很差。再者,对稳定性和误报率肯定有要求,假摔会导致排查成本增加,也会给运营发布的体验造成负面影响。 这样分析下来,我相信,能力项也就出来了:覆盖率、执行速度、稳定性。 定义指标定义了目标和能力项,之后就需要对每一个能力项做到什么程度进行定义,这就是我们说的指标了。 比如覆盖率上,我希望脚本能发现所有问题,而所有问题又很难定义,所以,我至少希望脚本能替代手工,那我的KPI就可以定义为:脚本覆盖所有手工测试的case,实现会场内容全自动化检查。 在执行速度上,我们希望做到2分钟内执行完成。 在稳定性上,我们希望成功率达到三个9,误报率小于1‰。 当然,有时候由于缺乏历史数据积累,很多数字只能靠拍,但是拍也不是乱拍。我们可以从业务上的效果来思考,比如执行速度,我们如果希望一次S级大促所有会场在15分钟之内完成测试,那么根据会场数量、执行机的数量,就可以反推出单个case的运行时长,而这个就是我们能力项的指标了。 方案和实施路径选择好了,根据以上的分析,我们已经得到了能力建设的目标和指标,那在方案的选择和实施路径上也就会相对清晰了,这里本文就不再赘述了。 小结在很多时候,能力整合和原子能力往往是相辅相成的,能力整合打应用场景,原子能力打解决问题的深度,只有结合起来很才能最大化价值。但是在定义KPI的时候,两者其实可以分开考虑,这样在团队资源投入上也更容易分工和形成合力。 另外,思考价值、目标的过程是很折磨人的,但是我认为这是一个锻炼“思考力”的方式,一旦习惯了以后,就会按照这个思考路径来想问题了。 本文作者:孙阳阅读原文 本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

October 14, 2019 · 1 min · jiezi

利用Travis-CIGitHub实现持续集成和自动部署

前言如果你手动部署过项目,一定会深感持续集成的必要性,因为手动部署实在又繁琐又耗时,虽然部署流程基本固定,依然容易出错。 如果你很熟悉持续集成,一定会同意这样的观点:“使用它已经成为一种标配”。 什么是持续集成Continuous Integration(CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.———ThoughtWorks 翻译过来就是:持续集成是一个开发行为,它要求开发者每天多次将代码集成到一个共享的仓库,每次提交都会被自动构建所检查,团队可因此提前检测出问题。持续集成的工具非常多,例如用java语言开发的Jenkins,由于其可以在多台机器上进行分布式地构建和负载测试的特性,很多大公司都在使用它。 但是Jenkins的不加修饰的界面界面让我有些嫌弃... 随着GitHub的发展,出现了越来越多支持GitHub的CI/CD产品。在GitHub市场上,可以看到,已经支持的持续集成服务提供商已超过300多家(详情)。 选择Travis CI,是因为身边很多朋友的推荐。 下面分享一下我是如何利用Travis CI+GitHub实现持续集成和自动部署的,通过我的一些研究和实战经验,希望可以帮到有需要的朋友。 什么是Travis CITravis CI是用Ruby语言开发的一个开源的分布式持续集成服务,用于自动构建和测试在GitHub托管的项目。支持包括Javascript、Node.js、Ruby等20多种程序语言。对于开源项目免费提供CI服务。你也可以买他的收费版,享受更多的服务。 Travis CI目前有两个官网,分别是 https://travis-ci.org 和 https://travis-ci.com 。https://travis-ci.org 是旧平台,已经逐渐往新平台 https://travis-ci.com 上迁移了。对于私有仓库的免费自动构建,Travis CI在新平台上给予了支持。 一、获取GitHub Access TokenTravis CI在自动部署的时候,需要push内容到仓库的某个分支,而访问GitHub仓库需要用户授权,授权方式就是用户提供 Access Token 给Travis CI。 ...

October 4, 2019 · 1 min · jiezi

Github-travisci-CI-CD-026

Github travis-ci CI CDCICD 是 持续集成Continuous Integration和持续部署Continuous Deployment简称。指在开发过程中自动执行一系列脚本来减低开发引入 bug 的概率,在新代码从开发到部署的过程中,尽量减少人工的介入。 本文主要介绍一下 travis-ci 持续集成和给 github Actions Travis-cihttps://www.travis-ci.org/1.登录travis-ci通过 github账号登录,会自动同步你的仓库 选择需设置的仓库 先勾选一个测试仓库 3 设置一些解释说明可以看具体的文档,主要包括这几方面 添加.travis.ymlTravis-ci 构建的生命周期 具体一些步骤可以查看文档. 这个文件主要是告诉 Travis CI 应该做什么,以前端node.js为例: language: node_js # 语言设置node_js: # node 版本 - "8"# npm现在默认缓存,如果您要禁用它,请将以下内容添加到您的.travis.yml:cache: npm: false before_install: # 安装前 - npm installscript: - npm run build如果当前目录存在yarn.lock可以使用 Yarn; 如果当前目录中都存在package.json和yarn.lock,则运行以下命令而不是 npm install 具体的一些配置,通过查看文档即可; 现在已经构建成功; 发布部署如果每次构建完都自动部署,或者手动部署可以再下一步; language: node_jsnode_js: - "8"before_install: - yarn installscript: - yarn build after_script: - cd ./dist - git init - git config user.name "${U_NAME}" - git config user.email "${U_EMAIL}" - git add . - git commit -m "Update tools" - git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:${P_BRANCH}#指定分支,只有指定的分支提交时才会运行脚本branches: only: - master发布的是 github page 博客. ...

September 19, 2019 · 1 min · jiezi

从0到1了解CICD初学者入门必备

本文先介绍了系统构建的先决技术与实践,自动化构建、版本控制,并给出了Java环境下一些构建工具,然后分别介绍了持续集成(CI)、持续交付和持续部署(CD)的概念及其优势,并在最后给出了一些最佳实践,如确保部署一致、保证良好的测试覆盖率等。 现代软件开发的需求加上部署到不同基础设施的复杂性使得创建应用程序成为一个繁琐的过程。当应用程序出现规模性增长,开发团队人员变得更分散时,快速且不断地生产和发布软件的流程将会变得更加困难。 为了解决这些问题,开发团队开始探索新的策略来使他们的构建、测试和发布流程自动化,以帮助其更快地部署新的生产。这就是持续交付和持续集成发展的由来。 本文将介绍什么是CI/CD并且它是如何帮助团队迅速开发部署经过充分测试、可靠的软件。在了解CI/CD及其优势之前,我们应该讨论这些系统构建的一些先决技术和实践。 自动构建流程 在软件开发过程中,构建流程会将开发人员生成的代码转换为可执行的可用软件。对于Go或者C语言等编译语言,此阶段需要通过编译器运行源代码以生成独立的二进制文件。对于Python或PHP等解释性语言,没有编译的步骤,但是代码依旧需要在特定的时间内冻结、绑定依赖项、打包以便于分发。这些过程通常称为“构建”或“发布”的工件。 虽然开发人员可以手动构建,但这样操作有诸多不利。首先,从主动开发到创建构建的转变中引入了上下文转换,使得开发人员不得不停止生产效率更高的工作来专注于构建过程。其次,每个开发人员都在制作自己的工件,这可能导致构建过程不一致。 为了解决这些顾虑,许多开发团队配置了自动构建流水线。这些系统监视源代码存储库,并在检测到更改时自动启动预配置的构建过程。这一配置无需牵涉过多的人力在其中并且确保了每个构建过程一致。 市场上有许多帮助用户自动化这些步骤的构建工具,以下列出了在Java生态下比较受欢迎的构建工具: Ant:Apache Ant是一个开源Java库,创建于2000年。它是Java领域的原始构建工具,至今仍然被频繁使用。Maven:Apache Maven是一个自动化构建工具,主要是为Java项目编写的。不同于Apache Ant,Maven遵循约定优于配置的原则,仅需要针对偏离合理默认值的构建过程的方面进行配置。Gradle:在2012年推出的1.0版本中,Gradle尝试通过结合Maven的现代功能来融合Ant和Maven的优势,同时又不失Ant提供的灵活性。构建指令是用一种名为Groovy的动态语言编写的。尽管在这个领域,这是一个相对比较新的工具,但它已被广泛采用。版本控制 大部分现代软件开发需要在共享的代码库中进行频繁协作。版本控制系统(VCS)用于帮助维护项目历史记录,并行处理离散特征,以及解决存在冲突的更改。VCS允许项目轻松采用更改并在出现问题时回滚。开发人员可以在本地计算机上处理项目,并使用VCS来管理不同的开发分支。 记录在VCS中的每个更改都称为提交。每个提交都对代码库的更改进行编目分类,元数据也包含在其中,例如关于查看提交历史记录或合并更新的描述。 图1 分布式版本控制 虽然版本控制是一个十分有价值的工具,它能帮助管理在单一代码库中许多不同的更改。但分布式开发通常会为其带来挑战。在没有定期合并到共享集成分支的情况下在代码库的独立分支中进行开发可能会使以后合并更改变得困难。为了避免这一情况,开发人员开始采纳持续集成实践。 持续集成(CI) 持续集成(CI)是一个让开发人员将工作集成到共享分支中的过程,从而增强了协作开发。频繁的集成有助于解决隔离,减少每次提交的大小,以降低合并冲突的可能性。 为了鼓励CI实践,一个强大的工具生态已经构建起来。这些系统集成了VCS库,当检测到更改时,可以自动运行构建脚本并且测试套件。集成测试确保不同组件功能可以在一个组内兼容,使得团队可以尽早发现兼容性的bug。因此,持续集成所生产的构建是经过充分测试的,并且是完全可靠的。 图2 持续集成的过程 持续交付和持续部署(CD) 持续交付和持续部署是在构建持续集成的基础之上的两种策略。持续交付是持续集成的扩展,它将构建从集成测试套件部署到预生产环境。这使得它可以直接在类生产环境中评估每个构建,因此开发人员可以在无需增加任何工作量的情况下,验证bug修复或者测试新特性。一旦部署到staging环境中,就可能需要进行额外的手动和自动测试。 持续部署则更进一步。一旦构建在staging环境中通过了自动测试,持续部署系统将会自动将它部署到生产服务器上。换言之,每个通过测试的构建都是实时的,可供用户及早反馈。这使得团队可以不断发布新特性和修复bug,并以其测试流程提供的保证为后盾。 图3 CI / CD流程路线图 CI/CD的优势 持续集成、交付和部署对软件开发过程有显著的改进。下文将简单介绍一些CI/CD的主要优势: 快速反馈回路 对于一个快速的开发周期,快速反馈回路显得尤为重要。为了能够实时接收反馈,软件必须迅速触达终端用户。而CI / CD可以通过简化更新生产部署来提供实现此目标的平台。通过要求每个更改都经过严格的测试,CI可以帮助降低每个构建的相关风险并因此使得团队可以便捷地向用户发布有价值的特性。 增加可见度 CI/CD通常是指将IT流程的各个步骤按序列组成一条流水线,且该流水线对整个IT团队(包括开发、测试、运维等团队)均可见。因此,每个团队成员可以跟踪系统中的构建状态并且可以确定任何导致测试失败的构建。团队成员通过深入了解代码库的当前状态,可以更轻松地规划最佳行动方案。这样的可见度为这一问题提供了一个明确的答案——“我提交的更改是否破坏了构建?” 简化故障排除 尽管CI的目标是集成并测试每个发生在代码库中的更改,但是更安全的方式是每次提交都是小型的并尽早将它们合并到共享代码存储库中。如此,当找到bug时,确定和问题相关的更改会更加容易。毕竟,根据问题的严重程度,团队可以选择回滚或编写并提交修复,从而减少生产中解决问题的时间。 软件质量更高 自动化构建和部署流程不仅缩短了开发周期,而且帮助团队开发出品质更好的软件。因为每个更改都会经过充分的测试并且至少会部署在一个预生产环境中,因此团队可以毫无顾虑地将更改部署到生产中。不过,只有当代码库的所有级别,从单元测试到更复杂的系统测试,都有良好的测试覆盖率时,才能实现这一点。 集成问题更少 因为自动化测试套件在每次提交时自动生成的构建上运行,所以可以尽早检测并修复集成问题。这使开发人员能够及早了解当前正在进行的工作是否可能影响其代码。它会在一开始就测试由不同贡献者编写的代码是否兼容,而不是在之后可能出现其他问题的时候才开始测试。 有更多的时间专注于开发 CI/CD系统依赖自动化来生产构建并且通过流水线来迁移新的更改。由于不需要手动干预,因此构建和测试不再占用开发团队大块的时间。进而开发人员可以心无旁骛地对代码库进行有效的更改,因为如果构建过程中出现任何问题,自动化系统会通知他们。 持续集成和交付的最佳实践 既然我们已经了解了使用CI/CD的一些优势,那么接下来,我们将讨论一些指导原则来帮助您成功实现这些流程。 对CI / CD流水线负责 开发者直到更改被部署到预生产环境中,才无需对其提交的代码负责。这意味着开发者必须确保他们的代码集成正确并且随时可以部署。如果提交的更改违反了这些要求,则开发人员有责任快速提交修复以避免影响其他人的工作。构建失败应该暂停流水线并阻止不参与修复故障的提交,这使得快速解决构建问题变得至关重要。 确保部署一致 部署过程不需要手动操作,反而流水线需要自动部署流程以确保一致性和可重复性。这减少了将破坏性构建推向生产的可能性,并有助于避免出现一些难以重现的、未经测试的配置。 将代码库提交到版本控制 将每次更改提交到版本控制是十分重要的。这会帮助团队审核所有提交的变更并且让团队可以简单地还原出现问题的提交。同时,也可以保持配置、脚本、数据库和文档的完整性。如果没有版本控制,特别是当多人使用同一个代码库时,会非常容易丢失配置和代码更改或对其处理不当。 提交小的、渐进的更改 开发人员一定要牢记:更改必须是小的。因为等待引入更大批量的更改会延迟测试反馈,会更难以确定问题的根本原因。 良好的测试覆盖率 由于CI / CD的目的是减少手动测试,因此整个代码库应该有一个良好的自动化测试覆盖率,以确保软件按预期运行。此外,还应该定期清理冗余或过时的测试以避免影响流水线。 ...

August 7, 2019 · 1 min · jiezi

十分钟-CODING-DevOps-全链路体验

近期 CODING 团队在 2019 KubeCon 大会上发布 DevOps 一站式解决方案:CODING 2.0。此次 CODING 全新上线了持续集成与制品库模块,通过自动化与标准化的方式来帮助开发者摆脱编译、构建、集成、制品管理等重复劳动,旨在打造沉浸式开发体验。在 KubeCon 大会现场,我们以一个基于 Spring 的模版项目为例,展示了开发者如何基于 CODING 轻松完成编码到构建制品的过程。 新项目创建首先新建一个项目,选择一个您熟悉的开发语言预置模版。预置代码模版提供了从代码生成、持续集成、制品库的自动配置,并已预置了 Dockerfile ,实现 Docker 容器化的打包方式。目前代码模版已内置了包括 Java、Ruby、Android、Node.js、Python 等主流语言开发框架的网页或移动端应用。 只需几分钟,项目即可创建完毕。CODING 为您创建了一个代码仓库,并将一个简单 Java 网页应用的代码推送到仓库 master 分支,还为您创建一条可直接运行的构建流水线,产物为 Docker 镜像。基于创建好的代码仓库和构建流水线您可以立即进行代码开发,并且快速集成代码。 接下来我们基于创建好的模版项目 spring-demo ,通过三个环节:代码托管、持续集成、制品管理,来看看 CODING 的 DevOps 配置具体是什么样的。 代码托管CODING 提供代码托管能力,并支持 Git 与 SVN 的代码提交方式。在自动生成的代码仓库中我们看到了 Maven 编译脚本、Jenkins 构建脚本、Docker 镜像打包脚本、网页应用的源码。在 README 文件中详细介绍了各个源码文件的作用以及如何运行该网页应用,对于开发新手来说可以说是手把手程度的详细介绍。您可以通过本地 Git/SVN 客户端来提交代码。 持续集成修改后的代码如何集成到软件当中来?我们来看看预置模版下生成好的构建任务,并学习如何修改持续集成配置以满足更多的场景需求。 在下图中可以看到系统已自动运行过第一次的构建,在持续集成首页您可以清晰地看到每次构建结果的状态、触发原因、持续时长等基本信息。CODING 的持续集成支持多 Job 并发运行,如果您的研发团队有这方面的需求,在持续集成页面按需创建多个构建任务即可。 在构建记录中您可以看到每次构建结果的详细信息。比如构建过程的运行状态,如果遇到构建失败的情况,您就可以在该页面查看失败环节的日志信息以便快速修复构建流水线。您还可以看到改动记录、测试报告、还有生成的构建产物(比如 Jar/War/脚本/配置文件等构建半成品)。最终的构建产物(比如 Docker 镜像)通过简单配置即可自动推入制品库中,稍后我们会详细介绍制品库。 接下来我们来看看构建任务的具体配置是怎样的。在触发方式中您可以按需设置触发方式、邮件通知人员。在持续集成过程中您可以选择通过图形化编辑器或者文本编辑器(如果您对 Jenkinsfile 脚本熟悉)的方式来详细配置构建的每个环节。针对一些持续集成过程中无法明文展示或者易变的信息,您可以通过环境变量或者凭据注入的方式来进行设置。如果想要加快构建速度,您可以打开缓存配置,同时还支持清空重置。 ...

July 4, 2019 · 1 min · jiezi

拥抱自动化CODING-20-持续集成全新上线

在文章开始前,做一个小调查,在您的软件项目中集成一行新代码平均需要花多长时间? 15 分钟一小时半天一天及以上注意这里的集成是指将源码放在一起,并验证源码可以作为一个一致、运行可靠的软件的过程,而不只是完成编译。 如果在软件集成阶段耗费的时间经常让您的研发团队加班加点,那么是时候考虑落地持续集成了。我们都知道软件只有从代码生成制品,最终部署到生产环境中可靠运行才会给公司带来收入。持续集成是一种以“反馈”为核心的实践,为了达到短周期、高质量的交付目标,研发团队需要频繁且自动化地发布软件。每次修改代码都进行集成可以让上线的时间尽可能短,开发人员也可尽早发现缺陷以便快速修复。 拥抱自动化,打造沉浸式开发体验CODING 持续集成(CCI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、Node.js 等所有主流语言编译环境,并且支持 Docker 镜像的构建。只要几步配置,就可以开启 Git 代码仓库的持续集成,包括 CODING 代码托管、GitHub、GitLab 等等。帮助您控制每一次从引入代码变更到发布的整个过程,从而更好地优化软件交付的速度和质量。 人力资源是非常有价值的,所以研发团队应该把人力放在开发新功能上,而不是那些枯燥且易出错的重复劳动上,比如像编译、打包、质量检查这类工作可以考虑都由 CODING 的持续集成来完成。 即使项目规模不大,我们也相信研发组织能从 CODING 的持续集成中受益。因为小项目会逐步成长为大项目,一开始就使用规范、自动化的方式进行软件集成,可以减少团队更替或者新人加入带来的沟通成本;尽早卸掉流程债务与管理债务,可以避免项目庞大失控后陷入交付沼泽中无法上岸。 深度优化,助力企业加速落地持续集成CODING 的持续集成在构建效率、使用门槛、构建物管理等方面都进行了深度优化。包括支持图形化编排以提高开箱即用的体验;高配集群多 Job 并行构建提速您的构建任务;统一的构建产物管理真正打通持续集成与持续交付的枢纽;凭据注入让持续集成更加安全易用。接下来我们来具体看看这些优化: 更友好的新手体验:图形化编排可视化的图形编排对于用户快速直观地理解、编排工作流水线是非常必要的。CODING 在基于编辑 Jenkinsfile 的核心功能之上设计了可视化视图,针对构建的每一个步骤提供丰富的构建脚本模板供用户选择。同时也兼容绝大部分自定义操作,实现了边写边看、所见即所得的直观编辑体验,降低了 Jenkinsfile 新手的使用门槛。 更快速的构建效率:多 Job 并行与缓存加速CODING 支持在一个项目当中并行构建多个 Job,以满足重度持续集成用户的需求。后端的服务器集群可以根据用户的需求实施调度响应的计算资源,保证用户的构建任务快速开始,减少排队时间;同时支持在不同的构建任务之间开启缓存,以提高反复构建的速度。开启缓存功能可以平均提高 300% 的构建速度。 更完整的构建流程:制品库管理CODING 制品库支持 Docker Image、Maven/Jar、Kubernetes Helm、Node.js NPM 包等常见软件包类型。制品库可以跟源代码协同进行版本化控制,可以与本地各构建工具和云上的持续集成、持续部署无缝结合,帮助您以标准化的方式管理构建产物。 更安全的鉴权机制:凭据注入在持续集成之后需要将构建产物自动存入制品库当中。不放心将制品库的账号密码配置在脚本或者是环境变量当中?CODING 提供了更为安全便捷的凭据注入方式,开发者通过服务连接的方式新建连接,配置好连接 ID 即可将持续集成产物推送到制品库中。 持续集成让开发者甩掉软件集成过程中的重复劳动并提高了代码质量。在这样的安全环境中,开发者更敢于创新,尝试新的想法。对于专业的软件研发组织来讲,版本控制、敏捷开发、持续集成等等都是非常重要的研发实践。CODING 通过日益完善的 DevOps 工具链,将前沿研发理念注入其中,帮助企业研发组织提高研发效率,让开发更简单。 点击下方,了解更多 CODING 2.0 升级资讯: 《CODING 2.0 企业级持续交付解决方案》 《CODING 2.0:为什么我们需要 DevOps》 《CODING 2.0 服务升级:一站式服务体系助力企业研发上云》 《CODING 2.0:如何通过设计给品牌创造价值?》 《打通 DevOps 任督二脉 ,CODING 2.0 制品库全新上线》 ...

July 3, 2019 · 1 min · jiezi

基于-CODING-轻松搞定持续集成

点击观看视频教程带你一步一步搞定 CODING 持续集成 持续集成加速软件交付持续集成这个概念是由 Grady Booch 在 1991 年首次提出,随后成为了 DevOps 的核心实践之一。持续集成使得开发人员不断地将各自分支的源代码集成到共享的主干中,同时对代码进行验证(执行静态测试用例)、编译和测试(执行动态测试用例),以避免集成出现问题。 持续集成为研发组织带来了多重好处: 自动化构建流水线将开发人员从重复劳动中解放出来,比人工集成更加高效。花费更少的时间调试,告别长时间和紧张的集成。提高集成效率的可视性,让每个人都能看到集成结果和获取最新构建的可交付成果,减少沟通成本。及早发现问题并将其扼杀在萌芽状态,更加快速地交付软件。基于 CODING 轻松搞定持续集成业界推荐的持续集成最佳实践要点包括:研发组织按照项目情况共同维护一个代码库,支持代码自动化构建,并且在构建过程当中可以进行自检;每次提交必须进行一次构建、保持构建的高效;确保研发团队易于取得最新构建的可交付成果,并且支持自动化部署。 落地持续集成最佳实践的方式有多种,可以选择基于开源工具自建,例如 Jenkins,或者使用 CODING 这类 SaaS 化的解决方案。这两种方式究竟哪种更适合你呢?接下来我们通过视频看看两种方式搭建流水线的效率—— 线上视频地址:https://v.qq.com/x/page/f0877pg1r9w.html 除了视频中展示的开箱即用体验之外,CODING 的持续集成还提供了: 全面的构建类型CODING 支持包括 Docker 镜像、Jar、APK 等软件包的构建,预置了主流开发语言的构建环境:Java、PHP、Go、Python、NodeJS 等。 缓存加速与构建依赖拉取优化CODING 持续集成支持在不同的构建任务之间开启缓存,开启缓存功能可以平均提高 300% 的构建速度。在构建依赖拉取方面,对于包括 Maven,NPM 在内的主流镜像源有专用网络优化,保证拉取速度,进一步提升构建的速度。 多 Job 并行构建CODING 支持单项目并行构建,以满足重度持续集成用户的需求。后端的服务器集群可以根据用户的需求实施调度响应的计算资源,保证用户的构建任务快速开始,减少排队时间。 图形化编排完善的图形化编排能力,以降低使用门槛。针对构建的每一个步骤提供丰富的构建脚本模板供用户选择。 全面兼容 JenkinsCODING 持续集成的构建脚本在语法上全面兼容 Jenkins。Jenkins 用户可以无缝迁移 Jenkins File 到 CODING。 近期 CODING 的制品库功能已上线,开发者可以在制品库中统一管理持续构建产物。目前制品库已支持 Docker 镜像的制品管理,后续会逐步支持多种主流的软件包类型来进一步完善 DevOps 工作流,敬请期待。 点击此处立即体验开箱即用的 CODING 持续集成

June 6, 2019 · 1 min · jiezi

如何实现持续集成闲鱼把研发效率翻了个翻

阿里妹导读:业务的快速发展,需要我们更快速地响应,和更高质量产品的交付。如何从原来大(xiao)迭(pu)代(bu)的开发模式切换为精益开发模式?以 2-1-1(2周需求交付周期,1周需求开发周期,1小时集成时长)为愿景驱动改进,达到持续交付价值,响应业务要求成为我们的目标。今天,闲鱼工程师琪钰为我们分享:闲鱼是怎样朝着这一目标前进的?切换为精益开发模式后,又面临了哪些问题和挑战?名词解释:精益开发模式,团队基于看板组织协作,以持续地交付需求为目标,需求按优先级,逐步进入开发、提测。由于在项目协作中,采用看板泳道来管理需求,因此在闲鱼,同学们习惯称之为泳道模式。 1、我们面临的要求和挑战业务对交付响应时间要求越来越快。闲鱼业务正处于高速发展中,反摩尔定律告诉我们,交付越迟,商品价值打折得就越厉害。速度为王,为了满足业务快速迭代和试错对技术团队能否快速交付需求提出了更大的挑战。团队规模变大,项目沟通成本越来越高。随着闲鱼业务和技术的快速发展,交付的环境也越来越复杂,协作的角色越来越多。整个研发过程包含需求管理、开发、测试、发布、回归等关键活动,涉及aone(研发协作平台,主要是需求、bug管理等)、代码库、打包平台、自动化测试平台等多个系统,沟通协同的成本越来越高。多分支并行开发增加额外成本。项目开发切换为精益开发模式最核心的改变就是各需求是独立的互不影响,可以分别独立进行测试和集成,保持主干的稳定,随时拉发布分支进行灰度发布。但多分支并行开发,也带来了新的问题,原来打包配置、手动打包、安装测试包等人工成本,都成倍的增加。随时来的提测都能够测。之前客户端发布版本时间固定,批量开发、批量提测,测试介入比较晚。项目开发切换为精益开发模式对技术质量团队提出了更高的要求,面对多需求同时提测的情况,如何更快地响应测试。所以,构建一个贯穿从需求到代码开发,再到测试整个过程的流程,并将其工具化、自动化就显得十分必要和紧迫,而持续集成就是这一流程的重要形式体现,构建一个高效的持续集成系统摆在我们面前。这将一定程度降低开发过程中的沟通成本,流程工具化,加速自动化。 现在针对服务端的集成发布有很多可以参考的实践,但对客户端的集成发布来说,我们依然面对如下难点。 2、客户端持续集成的难点如何将研发过程中各环节关联起来,一个需求从创建到发布的关键活动如下:创建需求->创建代码分支->创建打包项目->提交代码->打包->提交测试->修复->提交集成->发布如何做到需求和代码分支关联,确保代码可追溯; 如何做到代码分支和打包项目关联,代码变更可自动触发打包; 如何做到代码范围和测试范围关联,确保测试回归范围。 多分支并行,如何有条不紊的进行集成。并行需求分支越多,意味着提交集成时,可能的冲突的概率就会越大。如何降低集成的冲突,以及集成后主干的稳定性,确保集成质量;如何做到一提交代码就触发测试,测试进一步左移;如何降低自动化测试的成本,提高测试效率;而要解决上面的这些难点,缺少一站式的工具平台支撑(集团内平台对服务端的发布有很好的支持,但对于客户端的集成发布来说,涉及平台工具比较多)。 3、怎么做客户端持续集成为了解决从需求创建到发布整个项目研发过程中协同、构建、集成和测试等遇到的问题,提高团队的持续交付能力。针对客户端集成发布,我们的整体方案的目标是首先是拉通整个需求交付流程中各个环节,简化持续交付工作,提供及时的质量反馈机制,让开发同学关注在业务的开发;有效提高集成成功率及缩短集成发布周期,让版本能够按时上线大家能够按时下班;建设可视化、自动化、智能化的持续集成流水线,让业务需求真正的可持续交付。 空谈误国,实干兴邦。在谈论更多的改进之前,我们先把基础本的流程通过工具先串起来,只有先看到整体,然后再发现问题逐步改进。 流程化 我们的核心流程是这样的,一旦创建需求分支,交付通道就已建立,直到需求发布。 首先开发按照规范创建需求分支后,自动将分支和需求进行绑定,同时创建打包项目后,自动将需求和打包地址进行绑定,这样开发同学一旦提交代码,就可以根据需求、代码提交内容等,给出影响范围,同时自动触发打包,开发和测试同学不用再担心最新的包中是否有刚提交的内容,每次变更都会触发打包;打包成功后,根据 merge request、push 定时等不同的触发方式,及分支类型,自动触发相应的测试件,进行一系列的自动化测试;测试件执行完后,执行结果将被及时反馈出来,确保每次代码变更都是经过测试验证的,测试进一步左移,并将问题在团队项目协作看板上将问题标示出来,帮助团队在项目协作中能够持续的发现问题从而提高集成质量,降低发布风险,保证业务更快更顺畅的交付。当完成了第一步,将整个流程打通之后,我们发现,在整个流程中,依然有很多是依赖人工操作的地方,这是最容易出错,并且极低地影响效率的地方,对我们来说,这是改进的机会,所以,第二步我们的重点就是做好无人化和自动化。 无人化 为了支撑持续集成流水线的运行,以无人化、自动化、可扩展为目标,及基于最小研发成本原则,我们做得事情主要分为精益开发流程协同支撑无人化及测试验证自动化两部分。 fish CI 主要是研发流程支撑,如需求绑定、监听变更、触发打包、触发测试等,fish guard 主要测试件调度、执行,结果通知,及后续测试件接入扩展部分。目前已接入的测试件主要有 UI 遍历、UI 识别、monkey、单元测试等。后续计划按照分层测试的原则,接入更多的测试件,如代码静态扫描、weex 自动化测试、服务端测试件等,增强测试件覆盖度,拓展自动化测试边界。关于这一部分,我们将在后面的文章中做更深入的分享。 数据度量 管理学之父彼得德鲁克说:“如果你不能度量它,你就无法改进它”,其实也是我们整个持续集成流水线的自检,我们到底做得怎么样,持续交付的能力如何,我们定义了如下指标用于后续统计。 指标主要分为响应能力、效率、质量三个维度,通过响应能力的这些指标,可以反应出打包变快了,质量反馈变快了,集成变快了,集成频率变高了;有效率的指标,反应出流水线工作的有效性,成功率越高说明流水线越稳定;最后质量,主要从代码质量和项目测试质量来度量,通过修改的文件数,模块分布可以反映出代码的拆分、依赖等情况;通过项目测试中 bug 的分布和库存,可以反映出项目质量情况,是否及时发现及时修复,是否达到发布标准等。 4、效果闲鱼从3月中旬开始试运行精益开发模式(持续交付模式)到现在,闲鱼所有的业务需求全部走精益开发模式,我们交付的速度,由一个月一个版本到两周一个版本。这离不开我们在流水线各个环节中的改进,如打包变快了,需求分支构建次数越来越多,集成频率越来越高,以及自动化测试验证及时反馈集成质量情况。此外,闲鱼在精益开发模式下质量获得了明显提升,如下图所示: 绿色分割线左半部分,是之前未切换到泳道模式前的一个版本,bug 趋势看,前面编码阶段,测试基本未介入,大量的代码批量集成后集中测试,在缺陷充分被移除后,才能交付,无法持续交付。绿色分割线右半部分,是某个业务线的缺陷趋势图,小批量的持续集成、及时测试和发现问题、及时修复,可以快速持续交付。 5、总结与规划简单总结下,我们做的事情,第一步是拉通整个交付过程,有一个稳定的交付过程,第二步保证交付的效率,即响应变快了,集成变快了,质量反馈变快了,第三步持续交付,关键词是“持续地”,频次上提出了更高的要求,集成的频率变高了,以前一个月集成一次,现在每天都能集成,从一个月一次,到 nightly build,再到随时集成。即相比以前,让开发同学“更”有信心集成一次变更并发布。 因此,我们的终极目标就是7*24随时发布,没有发布窗口限制,真正做到交付流水线自动化无人化和全自动化测试,降低持续构建成本,拓展自动化测试边界。 本文作者:琪钰阅读原文 本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

May 28, 2019 · 1 min · jiezi

后端好书阅读与推荐续七

后端好书阅读与推荐系列文章: 后端好书阅读与推荐后端好书阅读与推荐(续)后端好书阅读与推荐(续二)后端好书阅读与推荐(续三)后端好书阅读与推荐(续四)后端好书阅读与推荐(续五)后端好书阅读与推荐(续六)后端好书阅读与推荐(续七) Spring微服务实战Spring微服务实战 (豆瓣): https://book.douban.com/subje... Spring体系用来做微服务在当下可谓是风头正劲,这本书就用一个实例来手把手教我们实现微服务。实战系列的口碑一直不错,这本也不例外,看完就可以对微服务的概念有一个完整的理解,并且想上手也有路可寻。 亮点: 编码就像艺术,是一种创造性活动。构建分布式应用就像指挥一个管弦乐队演奏音乐,是一件令人惊奇的事情微服务是一个小的、松耦合的分布式服务,分解和分离大型复杂应用程序的功能,使它们独立,这样负责每个功能的团队都拥有自己的代码库和基础设施,技术不限,能灵活地独立开发部署,职责分离,降低团队协作成本。随着云的普及,微服务单元的增减(每个服务单元都是完整的)变得非常容易,使得整个应用更具弹性伸缩能力。Spring勇于自我革新,当初出场取代了沉重的J2EE,后面的Spring Boot使用简单注解去掉了自己原本繁重的配置,后来的Spring Cloud更是为分布式服务提供了一套完整的解决方案,所以Spring体系是我们构建微服务的绝佳选择微服务构建的一个关键是划分,而划分的一个关键是粒度,这个没有绝对标准,但是有几个原则:开始可以让服务设计范围大一些,后续可以重构至更小的服务;重点关注服务之间如何交互;随着对问题域的理解变化,服务的职责也要变化(演化思维)。需要注意微服务的几个坏味道(太粗;太细):职责过多,跨表超过5个,URL太长,测试用例太多;数量巨大、彼此依赖严重、成为简单的curd、只在一个表操作等微服务没有标准,但是作者提出了12种最佳实践:独立代码库、显式依赖、配置存储、后端可切换、构建发布运行必须完整、进程无状态、端口命令行制定、横向扩展并发、可down可up、环境一致、日志流式处理、管理脚本化。微服务的生命周期:装配、引导、发现、服务和监控、关闭少量程序可以使用低层级文件(YAML、json、XML)来存储配置,将其与代码分开,但是到了数百单元(每个单元可能有多个实例)时就不行了。手动管理既慢又复杂还可能配置漂移,这时应该引入配置管理工具(etcd、eureka、consul、zookeeper、spring cloud config等),服务启动时通过环境变量注入配置或者从集中式存储中获取服务发现提供了快速水平伸缩的能力,且当服务不健康时可以快速删除,还能取代传统的手动管理负载均衡。主要涉及服务注册、客户端服务地址查找、信息共享、健康监测4个方面一般大家关注高可用都是某个组件彻底不可用(容易检测)的情况,但是一个性能不佳而没有完全垮掉(不易检测)的服务也可以彻底拖垮整个应用,因此也需要保护这些不佳服务,避免连锁效应,导致彻底不可用。一般有客户端负载均衡(Ribbon)、断路器、后备、舱壁(Hystrix)等四个弹性模式来实现保护缓冲区AOP的思想帮我们分离关注点,那么要在微服务中实现靠啥?答案就是网关(比如Zuul,核心就是反向代理)了,我们可以在网关中实现验证授权、数据搜集与日志等关注点,但是要注意,避免网关成为单点要注意使其轻量且无状态(无状态就可以很容易扩展,而服务发现必须有状态,所以要扩展还要用Gossip等协议来同步状态数据,保障一致性和可用性)安全注意事项:都要使用HTTPSSSL、所有服务都要经过网关、将服务划分为公共API和私有API、封锁不必要的端口来限制微服务的攻击面微服务不是单体,其好处是灵活,代价就是解决问题时难以定位,所以需要追踪并聚合日志,最终定位问题。spring cloud 给每一个事务开启之前注入关联ID(一般由网关完成),每个服务都可以传播关联ID并将其添加进日志中,这些日志被统一发送到日志聚合点中,就可以供我们统一检索了,常见实现有ELK、Splunk等。光能检索还不够,一张直观的事务流图抵过1万条日志,Sleuth和ZipKin一起可以实现该功能微服务强调灵活迅速,所以一个成熟的构建与部署管道(引入CI/CD)必不可少:提交代码、自动构建(钩子实现)、构建期间进行单元测试与集成测试后获得一个jar(自包含tomcat)、用jar构建并提交机器镜像、在新环境中拉取机器镜像并进行平台测试后启动镜像、每个新环境都要重复前面一个步骤书很厚,所以很多具体工具可以跳过,尝试几个即可,将来使用的时候知道这本书里有就行了。 持续交付持续交付 (豆瓣): https://book.douban.com/subje... 微服务离不开CI/CD,而CI/CD核心就是几点:自动化、连续、小范围、快速、可靠。我们通过这本书来了解CI/CD,也看看持续交付是如何解决“Last Mile”问题,让软件交付不再令人紧张,成为一件简单平常的事情。 亮点: 从决定修改到结果上线的时间为周期时间,CI/CD技术能让周期从传统手段的周月单位变成小时甚至分钟级别(产品快速落地,降低机会成本),发布过程可靠可重复(减少错误与人力资源),核心技术就是部署流水线(一个应用从构建、部署、测试到发布这整个过程的自动化实现,过程中需要的所有东西包括需求、源码、配置、脚本、文档、运行环境等都要纳入VCS的管理,但是结果性的东西比如二进制镜像就不用,因为它可以随时构建得到,作者罗列了一些相应的工具)提出了一些反模式,让我们避免:手工部署软件(复杂 不可重复和审计 易出错)、开发完成之后才向类生产环境部署(不确定性很大 发布有风险)、生产环境手工配置管理(不能完全掌握 不可重复)。同时也提出了一些应该遵循的正面原则持续集成的前提是版本控制、自动化构建、团队共识,需要做到频繁提交、自动化测试、保持构建和测试过程较短、管理开发工作区、构建失败之后修复成功之前不能提交新代码、提交之前自己运行测试、提交测试通过之后再继续工作、时刻准备回滚(回滚之前要有一个修复时间)、为自己的问题负责、测试驱动等等持续集成能提高团队对复杂系统的自信心与控制力,其主要关注是开发团队,并不能解决软件部署、交付过程的低效,所以需要一个端到端的自动化构建、部署、测试和发布流程,也就是部署流水线(关注的是软件从CVS到用户手中这个过程),它有一些相关实践:只生成一次二进制包、不同环境统一部署、对部署进行冒烟测试、向生产环境的副本部署、每次变更都要立即在流水线中传递、只要有环节失败停止整个流水线。CI/CD的关键都是记录变更,为尽早发现问题提供信息,消除低效环节部署流水线的几个要点:构建与部署脚本化(配置初始化数据、基础设施、中间件等)、提交阶段快速反馈与及时修复、自动化验收测试(验收测试是验证客户的期待,单元测试是验证开发人员的期待)、注意非功能测试(主要指性能)、部署与发布要有策略并且可重复执行(文本化)且可回滚(不同版本文件不删除,用符号链接到当前版本)作者说无论项目大小都应使用CI/CD,这个我感觉有点偏激了,所谓磨刀不误砍柴工,前提是这个柴要么很多,要么很大,如果只是几根细柴,有那个磨刀的功夫柴都砍完了。但是实际工作中这么小的项目应该很少,所以大多数项目我们还是都还是应该搭建部署流水线,用上CI/CD。书很厚,其实好多地方可以跳过,你只需要看标题就能抓住主旨而无需多看。PS:可以先看看这本持续集成。 敏捷革命敏捷革命:提升个人创造力与企业效率的全新协作模式 (豆瓣): https://book.douban.com/subje... CI/CD 实际上正是敏捷开发的最佳实践,有了前面的铺垫,我们可以通过这本书我们来真正了解敏捷开发的全貌。 亮点: 2005年之前,大多数软件开发项目都是采用“瀑布法”:整个项目被划分为多个阶段,每个阶段都要经过严格的评审,以期为客户或软件使用者提供完美的产品(甘特图表现),每一阶段的工作做得足够好时才允许进入下一阶段。这种工作方式看似完美,实际全凭想象和猜测、华而不实,往往导致开发进度缓慢,常常超出预算,且现实和规划差异巨大,Scrum(敏捷开发流程)的出现就是解决这个问题的(不凭猜测,而是PDCA:计划、执行、检查、行动)任何项目的管理都需要实现两个目标:可控性与可预测性管理层的职责在于制定战略目标,团队的工作则是决定如何完成目标。无论任何人,只要不在现场,都不可能及时跟上事态变化的步调,所以团队要有自主决策权,此外一个团队需要包含完成一个项目的所有技能,同时要小而精(7人左右)。团队成员之间不要互相指责,而是尽量改善制度“冲刺”(一般以星期为周期)可以让团队成员集中精力快速做出成果并得到反馈,“每日立会”(15分钟以内)能让成员清楚地知道冲刺进度如何。Scrum的核心就是节奏确定懂项目、懂市场、懂顾客的产品负责人,拟定待办事项清单并检测两遍,重要的事情优先做这本书细看的话真的很洗脑,看完感觉自己迫不及待地想要冲进一家公司试试Scrum了。 DevOps实践指南DevOps实践指南 (豆瓣): https://book.douban.com/subje... DevOps是软件开发、运维和质量保证三个部门之间的沟通、协作和集成所采用的流程、方法和体系的一个集合(所以也要基于CI/CD,前4本书可以看做一个连续的专题,核心都是敏捷)。它取代了传统开发、测试、运维职责大分离的思想,填平了部门之间的鸿沟,让大家更有效的工作。我们可以通过这本书来对DevOps有一个全面的了解。 亮点: 开发部通常负责对市场变化做出响应,以最快的速度将新功能或者变更上线。而运维部则要以提供稳定、可靠和安全的服务为已任,让任何人都很难甚至无法引入可能会危害生产环境的变更。这种配置方式让开发部门和IT运维部门的目标和动因之间存在“根本的、长期的冲突”——公司对不同部门的考核和激励不同,这种冲突造成了一种恶性循环,阻碍了公司全局目标的实现。DevOps能够提高公司业绩,实现开发、QA、IT运维、信息安全等各职能技术角色的目标,同时改善人们的境遇DevOps是精益、约束理论、丰田生产系统、柔性工程、学习型组织、康威定律等知识体系的集大成者DevOps“三步工作法”:流动、反馈、持续学习与实验,并阐述了DevOps实施需遵守的原则与最佳实践(流动:它加速了从开发、运维到交付给客户的正向流程;反馈:它使组织构建安全可靠的工作体系,并获得反馈;持续学习与实验:它打造出一种高度信任的文化,并将改进和创新融入日常工作中)为了能识别工作在哪里流动、排队或停滞,需要将工作尽可能地可视化,如在看板或Sprint计划板上,使用纸质或电子卡片将各项工作展示出来,通过这种方式,不仅能将工作内容可视化,还能有效地管理工作,加速其从左至右的流动,还可以通过卡片从在看板上创建到移动至“完成”这一列,度量出工作的前置时间。此外,看板还能控制在制品数量(队列长度)文中关于小批量和大批量的差异,我以前在博客中也提到过。如此看来,两种方式各有优劣,关键看能分配的资源是什么?更追求总体效率还是效果出现的等待时间?对返工的要求是什么?再来决定使用方法第一步描述的原则,使得工作能够在价值流中从左向右快速地流动。第二步描述的原则,使得在从右向左的每个阶段中能够快速、持续地获得工作反馈。快速发现问题、群策群力解决问题,可以避免把问题带入下游环节,避免修复成本指数增加。根据精益原则,我们最重要的客户是我们的下游(不一定是最终付费用户),为他们而优化我们的工作,在源头保障质量。第三步描述的原则可以持续提升个人技能,进而转化为团队的财富......感觉历史的天平总是左右摇摆,一开始职责混乱、一个人干所有的事,后来职责分离、分工明确,现在又提倡填平鸿沟、部门融合。随着时代的发展,适用于时代的技术也总是不停变更,要想不被淘汰就得终身学习呀。 Web容量规划的艺术Web容量规划的艺术 (豆瓣): https://book.douban.com/subje... 容量规划(很早就有了,如道路规划、电力运营)是一门省钱的艺术,保证用合理的资源来实现最大化需求,通过这本书我们来敲开容量规划在互联网世界中实际运用的大门。 亮点: 容量规划整个过程:首先要明确定义响应时间、可供消耗容量以及峰值驱动处理等明确指标来定义总体负载和容量需求,然后了解当前基础设施的负荷特征,预测需要的资源来达到这种性能,然后如何管理资源,最后不断迭代,最终目标介于“没有买足够资源”和“浪费太多资源”之间有几个方法:预测系统何时失败、用统计图表(比数字更直观)呈现问题、性能调优与容量规划要同步进行、搜集数据驱动未来的规划测量是规划的前提,要有坚实的数据支撑而不是猜测,有许多工具可以测量,他们应该可以随着时间记录和保存数据、自定义度量、比较指标、导入和导出指标,当然测量工具本身要轻量,尽量对资源本身影响较小。如果说测量是对已有情况的了解,那么估计就是根据数据趋势预测未来。预测部分靠直觉,部分靠数学。我们可以做曲线拟合,注意到趋势和变更,并进行迭代和校准(看来基于机器学习或者说AI的运维是未来啊)文章除了基于传统模式的容量规划,还涉及到了基于虚拟化和云计算的模式,所以我们学习也要注意趋势和变化。 领域驱动设计领域驱动设计 (豆瓣): https://book.douban.com/subje... 构建程序之前,我们都要对业务进行梳理和理解,然后是领域划分与建模等一系列重要步骤,最后才是编码实现,这就是一本讲解这些步骤的好书。而且本书会告诉你,设计和实现可以交错进行和演化,来达到最优。还提出了专业术语,你在和别人交流时可以使用。我在读到假同源这个词语时真是犹如醍醐灌顶,因为之前开发项目就有过:同一个对象,这个模块改吧改吧,那个模块改吧改吧,最后导致对两个模块而言,这个对象都不完全属于它,要修改都得小心翼翼怕影响对方,本书告诉我,遇上假同源,要么重新理解和建模,统一该对象表示,要么果断分开这两个模块,用两个对象分别服务这两个模块。 亮点: 模型是一种简化,是对现实的解释,把与解决问题密切相关的方面抽象出来,而忽略无关的细节(所以需要我们消化和提炼已有知识,包括深层次探索)。用户应用软件的问题区域就是软件的领域(有形的如机票系统,无形的如会计系统)。成功的项目有一个共同特征:都有一个丰富的领域模型,这个模型在迭代设计过程中不断演变(我们要持续学习),与实现绑定,成为项目不可分割的一部分很多因素可能会导致项目偏离轨道,但真正决定软件复杂性的是设计方法。当复杂性失去控制时,开发人员就无法很好地理解软件,因此无法轻易、安全地更改和扩展它,而好的设计则可以为开发复杂特性创造更多机会。一些设计因素是技术上的,很多技术人员都能轻易注意到并改进,但是很多程序主要的复杂性并不在技术上,而是来自领域本身、用户的活动或业务,这部分往往被许多人忽略要避免不设计和过度设计(极限编程)模型、设计的核心、实现互相影响和关联;模型是团队所有人员沟通的中枢,使得开发人员和领域专家无需翻译就能沟通,高效简洁;模型是浓缩的知识技术人才更愿意从事精细的框架工作,试图用技术来解决领域问题,把学习领域知识和领域建模的工作留给别人去做。软件核心的复杂性需要我们直接去面对和解决,如果不这样做,则可能导致工作重点的偏离——软件的初衷以及核心就是为了解决领域问题对于比较重要的业务规则(这个知识点需要我们自己去理解)比如货船超订110%,应该单独抽象成1个实体(具体就可以是1个方法),而不是简单的用一个guard clause来实现,这样既能明确这个知识点本身,又利于代码的扩展性。当然,把不重要的细节也单独抽象就是典型的过度设计了以文本为主,简洁的小图为辅(大而全的图反而失去了解释能力)来阐释模型最好。文档是代码和口头交流的补充,为团队提供稳定和共享的交流。只用代码做文档容易使人陷入细节,不能把控全局,所以应该文档和代码互补,文档不再重复阐述代码能表现的内容而是着重核心元素,阐明设计意图,文档还要注意和代码保持同步不脱节(不再适用的文档要进行历史归档),不然就失去了意义。模型与实现也要同步,通过模型驱动设计MDD实现,保证模型既利于实现,也利于前期的分析要想创建出能处理复杂任务的程序,需要做到关注点分离,使设计中的每个部分都得到单独的关注,行业普遍采用分层架构,分层的价值在于每一层都只代表程序中的某一特定方面,每个方面的设计都更具内聚性,更容易解释。分层设计大都是“用户层界面-应用层-领域层-基础设施层”这种四层架构的变体,其中领域层是软件的核心,将其分离才是MDD的关键,也是领域驱动设计DDD的前提。领域层与应用层的区分关键在于领域层包含实际业务规则(如转账操作),而应用层是为了实现业务的辅助功能(如导入转账文本记录)DDD适用于大型项目,小项目用“Smart UI”更合适,还有其他的架构模式都有自己的使用场景和局限领域中用来表示某种具有连续性和标识(比如银行账户)的事物是ENTITY,用于描述某种状态的属性是VALUE OBJECT(不可变,无标识,比如数字3,尽量设计为不可变,便于复制和共享),动作或操作最好用SERVICE来表示(在大型系统中,中等粒度、无状态的SERVICE更容易被复用),对象之间的关联可以通过限定条件进行简化,MODULE是一种更粗粒度的建模和设计单元(提供了两种观察模型的方式,一是可以在MODULE中查看细节,而不会被整个模型淹没,二是观察MODULE之间的关系,而不考虑其内部细节)。领域模型中的每个概念都应该在实现元素中反映出来由于汽车的装配和驾驶永远不会同时发生,因此将这两种功能合并到同一个机制中是毫无价值的。同理,装配复杂的复合对象的工作也最好与对象要执行的工作分开。应该将创建复杂对象(比如依赖其他对象B的对象A就是复杂对象,不要直接在A构造函数中调用B的构造函数)的实例和AGGREGATE(一组相关对象的集合,比如车辆与发动机)的职责转移给单独的对象:FACTORY初始模型通常都是基于对领域的浅显认知而构建的,不够成熟也不够深入,通过重构(不仅是一般的代码细节的重构,还有领域的重构,后者通常风险很高,但是回报也很高,需要在前者的不断积累下寻找突破)最终开发出能够捕捉到领域深层含义的模型,这也是管理项目的规模和复杂性的要素,加上柔性设计(软件易于修改)就能让项目稳步发展。持续重构渐渐被认为是一种“最佳实践”,但大部分项目团队仍然对它抱有很大的戒心。人们虽然看到了修改代码会有风险,还要花费开发时间,但却不容易看到维持一个拙劣设计也有风险,而且迁就这种设计也要付出代价代码除了要能准确得到结果外,还要能显式的表达出领域的规则,易于理解和预测修改代码的影响。所以有一些原则:揭示意图的接口,能避免用户去研究它的实现(失去了封装的价值);无副作用的函数,安全地预见函数的作用,避免组合爆炸;断言可以帮助展示和理解副作用技术角度的设计模式中的一些也适用于领域设计,比如Strategy和Composite模式,把设计模式用作领域模式的唯一要求是这些模式能够描述关于概念领域的一些事情,而不仅是作为解决技术问题的技术解决方案大型系统的模型很复杂,需要注意三个要素:上下文(不要强制在大型系统中统一模型,可以在不同的上下文使用不同的模型(注意重复概念和假同源),划定好边界即可)、精炼和大型结构,才能操纵和理解这个模型......DDD我们可能都用过,但是很可能没把它当成一项正经学问,都是大概过一下需求,稍微捋一捋逻辑然后就开始编码了,实际上,在我们这个过程我们已经经历了ddd,看完本书以后希望能把这个过程正规化,流程化,高效化。 Go语言实战Go语言实战 (豆瓣): https://book.douban.com/subje... 上本书给我们讲了go的基础知识和原理,这本书就带领我们用go的各种库和工具进行实战。 亮点: 计算机一直在演化,但是编程语言并没有以同样的速度演化。现在的高性能服务器拥有 64 核、128 核,甚至更多核。但是我们依旧在使用为单核设计的技术在编程。Go语言对传统的面向对象开发进行了重新思考,并且提供了更高效的复用代码的手段。Go语言还让用户能更高效地利用昂贵服务器上的所有核心,而且它编译大型项目的速度也很快经验,如果需要声明初始为零值的变量,应该使用 var 关键字声明变量;如果提供确切的非零值初始化变量或者使用函数返回值创建变量,应该使用简化变量声明运算符 :=go vet工具不能让开发者避免严重的逻辑错误,或者避免编写充满小错的代码。不过可以很好地捕获一部分常见错误。每次对代码先执行 go vet 再将其签入源代码库是一个很好的习惯;在保存文件或者提交到代码库前执行 go fmt可以统一代码风格go在函数之间传递变量时,总是以值的方式传递的。函数间传递数组可能涉及大量数据拷贝,最好传递数组的指针,就只用拷贝8字节的指针而非拷贝数组本身。相反,与切片关联的数据包含在底层数组里,不属于切片本身,所函数间直接传递切片没有性能影响,映射也是;在创建切片时设置切片的容量和长度一样,就可以强制让新切片的第一个 append 操作创建新的底层数组,与原有的底层数组分离,可以安全地进行修改而不影响原切片,同时也保持了为切片申请新的底层数组的代码简洁性关键字 func 和函数名之间的参数被称作接收者,将函数与接收者的类型绑在一起。如果一个函数有接收者,这个函数就被称为方法。值接收者使用值的拷贝副本来调用方法,而指针接受者使用实际值来调用方法。Go语言会调整传入的参数,无论是指针接受者还是值接受者都可以接受指针或者值两种类型,说是方便开发,但我觉得这反而是一个不必要的歧义,比如到了接口的方法集中,如果使用指针接收者来实现一个接口,那么只有指向那个类型的指针才能够实现对应的接口。如果使用值接收者来实现一个接口,那么那个类型的值和指针都能够实现对应的接口,主要原因是编译器并不是总能自动获得一个值的地址通过嵌入类型,与内部类型相关的标识符会提升到外部类型上。这些被提升的标识符就像直接声明在外部类型里的标识符一样,也是外部类型的一部分,可以无缝实现对象组合,需要注意嵌入类型不需要声明字段。如 ...

May 7, 2019 · 1 min · jiezi

如何在京东云上简单实践CI流程

在如今的互联网时代,随着软件开发复杂度的不断提高,软件开发和发布管理也越来越重要。目前已经形成一套标准的流程,最重要的组成部分就是持续集成及持续交付、部署。在此,我们在京东云上以一个案例简单实践下 CI 流程。在初探前,我们有几个概念和工具需要了解下:1)、CI/CD:持续集成(Continuous Integration,CI),它属于开发人员的自动化流程。成功的 CI 意味着应用代码的新更改会定期构建、测试并合并到共享存储库中。该解决方案可以解决在一次开发中有太多应用分支,从而导致相互冲突的问题。持续交付(Continuous Delivery,CD),通常是指开发人员对应用的更改会自动进行错误测试并上传到存储库(如 GitHub 或容器注册表),然后由运维团队将其部署到实时生产环境中。这旨在解决开发和运维团队之间可见性及沟通较差的问题。因此,持续交付的目的就是确保尽可能减少部署新代码时所需的工作量。持续部署(Continuous Deployment,CD),这是另一种“CD”,指的是自动将开发人员的更改从存储库发布到生产环境,以供客户使用。它主要为了解决因手动流程降低应用交付速度,从而使运维团队超负荷的问题。2)、Jenkins:Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。3)、Docker:Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。4)、Git:Git(读音为/gt/),是一个开源的分布式版本控制系统,提供代码仓库,可以有效、高速地处理从很小到非常大的项目版本管理。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。CI流程设计图:工作流程:开发人员提交代码到Git版本仓库;Jenkins人工/定时触发项目构建;Jenkins拉取代码、代码编码、打包镜像、推送到镜像仓库;Jenkins在Docker主机创建容器并发布主机环境规划:docker-jenkins:构建;拉取代码、代码编码、打包镜像、推送镜像到镜像仓库 116.196.85.174(公) 10.0.0.20 (内)docker-git:代码仓库 116.196.86.207(公) 10.0.0.22 (内)docker-harbor:私有镜像仓库 116.196.88.91(公) 10.0.0.21 (内)buildimage:build docker镜像 116.196.89.139(公) 10.0.0.4 (内)一、主机创建在京东云控制台创建4台云主机,地址:https://console.jdcloud.com/配置如下,购买时数量直接选择4,购买完成后再修改名称,分别为:docker-jenkins、docker-git、docker-harbor、buildimage创建修改名称后如下:二、环境配置1、云主机docker-git1.1. 修改主机名为:docker-git[root@112 ~]# hostnamectl set-hostname docker-git[root@112 ~]# hostname docker-git[root@112 ~]# logout[root@docker-git ~]#Ctrl+D退出后重新登陆生效1.2. 部署Git代码版本仓库安装:[root@docker-git ~]# yum install git -y配置git用户:[root@docker-git ~]# useradd git[root@docker-git ~]# passwd git创建库:[root@docker-git ~]# su git[git@docker-git root]$ cd[git@docker-git ~]$ mkdir tomcat-java-demo.git[git@docker-git ~]$ cd tomcat-java-demo.git/[git@docker-git tomcat-java-demo.git]$ git –bare initInitialized empty Git repository in /home/git/tomcat-java-demo.git/[git@docker-git tomcat-java-demo.git]$ lsbranches config description HEAD hooks info objects refs[git@docker-git tomcat-java-demo.git]$ 2、云主机docker-jenkins2.1. 修改主机名为:docker-jenkins[root@113 ~]# hostnamectl set-hostname docker-jenkins[root@113 ~]# hostname docker-jenkins[root@113 ~]# logout[root@docker-jenkins ~]#Ctrl+D退出后重新登陆生效2.2. jenkins环境部署部署jdk环境及maven[root@docker-jenkins tomcat-java-demo]# cd[root@docker-jenkins ]# mkdir tools[root@docker-jenkins ]# cd tools[root@docker-jenkins tools]# wget https://pocenv-hcc.oss.cn-north-1.jcloudcs.com/jdk-8u191-linux-x64.tar.gz;tar zxf jdk-8u191-linux-x64.tar.gz;mv jdk1.8.0_191/ /usr/local/;ln -s /usr/local/jdk1.8.0_191/ /usr/local/jdk;[root@docker-jenkins tools]# vim /etc/profile######## JDK #######JAVA_HOME=/usr/local/jdk1.8.0_191JAVA_BIN=/usr/local/jdk1.8.0_191/binPATH=$PATH:$JAVA_BINCLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarexport JAVA_HOME JAVA_BIN PATH CLASSPATH[root@docker-jenkins tools]# source /etc/profile[root@docker-jenkins tools]# java -versionjava version “1.8.0_191"Java(TM) SE Runtime Environment (build 1.8.0_191-b12)Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode) [root@docker-jenkins tools]# wget https://pocenv-hcc.oss.cn-north-1.jcloudcs.com/apache-maven-3.5.0-bin.tar.gz;tar zxf apache-maven-3.5.0-bin.tar.gz;mv apache-maven-3.5.0 /usr/local/maven[root@docker-jenkins tools]# 安装Jenkins,下载Tomcat二进制包将war包到webapps下即可:[root@docker-jenkins tools]# wget https://pocenv-hcc.oss.cn-north-1.jcloudcs.com/jenkins.war[root@docker-jenkins tools]# wget https://pocenv-hcc.oss.cn-north-1.jcloudcs.com/apache-tomcat-8.5.38.tar.gz[root@docker-jenkins tools]# tar zxf apache-tomcat-8.5.38.tar.gz[root@docker-jenkins tools]# lsapache-maven-3.5.0-bin.tar.gz apache-tomcat-8.5.38 apache-tomcat-8.5.38.tar.gz jdk-8u191-linux-x64.tar.gz jenkins.war[root@docker-jenkins tools]# mv apache-tomcat-8.5.38 /usr/local/tomcat-jenkins[root@docker-jenkins tools]# ls /usr/local/tomcat-jenkins/webapps/docs examples host-manager manager ROOT[root@docker-jenkins tools]# rm -rf /usr/local/tomcat-jenkins/webapps/*[root@docker-jenkins tools]# mv jenkins.war /usr/local/tomcat-jenkins/webapps/ROOT.war[root@docker-jenkins tools]# ll /usr/local/tomcat-jenkins/webapps/total 75520-rw-r–r–. 1 root root 77330344 Mar 15 00:55 ROOT.war[root@docker-jenkins tools]# cd /usr/local/tomcat-jenkins/bin/[root@docker-jenkins bin]# ./startup.shUsing CATALINA_BASE: /usr/local/tomcat-jenkinsUsing CATALINA_HOME: /usr/local/tomcat-jenkinsUsing CATALINA_TMPDIR: /usr/local/tomcat-jenkins/tempUsing JRE_HOME: /usr/local/jdk1.8Using CLASSPATH: /usr/local/tomcat-jenkins/bin/bootstrap.jar:/usr/local/tomcat-jenkins/bin/tomcat-juli.jarTomcat started.[root@docker-jenkins bin]#启动后,浏览器访问(docker-jenkins):http://Jenkins主机公网IP:8080/,按提示输入密码,登录即可。在/root/.jenkins/secrets/initialAdminPassword文件里,查看密码后填入即可按照你自己的需求安装插件设置管理员开始使用Jenkins2.3. 安装DOCKER CE安装所需包yum install -y yum-utils device-mapper-persistent-data lvm2 -y设置稳定存储库yum-config-manager –add-repo https://download.docker.com/linux/centos/docker-ce.repo -y安装DOCKER CE(这一步比较慢,耐心等会儿)yum install docker-ce docker-ce-cli containerd.io -y启动Dockersystemctl start docker3、云主机docker-harbor3.1. 修改主机名为:docker-harbor[root@c-dfjgjesgqe ~]# hostnamectl set-hostname docker-harbor[root@c-dfjgjesgqe ~]# hostname docker-harborCtrl+D退出后重新登陆生效3.2. 企业级harbor镜像仓库部署Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的 企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访 问控制,AD/LDAP集成以及审计日志等,足以满足基本企业需求。harbor各组件介绍:| 组件 | 功能 | | :——– | :——–| | harbor-adminserver | 配置管理中心 | | harbor-db | MySQL数据库 | | harbor-jobservice | 负责镜像复制 | | harbor-log | 记录操作日志 | | harbor-ui | Web管理页面和API | | nginx | 前端代理,负责前端页面和镜像上传/下载转发 | | redis | 会话 | | registry | 镜像存储 | Harbor安装有3种方式1)在线安装:从Docker Hub下载Harbor相关镜像,因此安装软件包非常小2)离线安装:安装包包含部署的相关镜像,因此安装包比较大3)OVA安装程序:当用户具有vCenter环境时,使用此安装程序,在部署OVA后启动Harb在此我们使用第二种离线安装方式来搭建基于 https 访问的 harbor 镜像仓库。3.2.1. 下载并解压离线安装包harbor离线包下载地址:https://github.com/goharbor/h…为方便下载,我在京东云对象存储上也存了一份,可直接wget:https://pocenv-hcc.oss.cn-nor…[root@docker-harbor ~]# yum install vim wget openssl -y[root@docker-harbor ~]# wget https://pocenv-hcc.oss.cn-north-1.jcloudcs.com/harbor-offline-installer-v1.7.4.tgz[root@docker-harbor ]# tar zxf harbor-offline-installer-v1.7.4.tgz[root@docker-harbor ]# cd harbor[root@docker-harbor harbor]# lltotal 570744drwxr-xr-x 3 root root 23 Apr 1 15:05 common-rw-r–r– 1 root root 939 Mar 4 15:33 docker-compose.chartmuseum.yml-rw-r–r– 1 root root 975 Mar 4 15:33 docker-compose.clair.yml-rw-r–r– 1 root root 1434 Mar 4 15:33 docker-compose.notary.yml-rw-r–r– 1 root root 5608 Mar 4 15:33 docker-compose.yml-rw-r–r– 1 root root 8033 Mar 4 15:33 harbor.cfg-rw-r–r– 1 root root 583086399 Mar 4 15:33 harbor.v1.7.4.tar.gz-rwxr-xr-x 1 root root 5739 Mar 4 15:33 install.sh-rw-r–r– 1 root root 11347 Mar 4 15:33 LICENSE-rw-r–r– 1 root root 1263409 Mar 4 15:33 open_source_license-rwxr-xr-x 1 root root 36337 Mar 4 15:33 prepare3.2.2. 自签http证书1)获取权威认证证书[root@docker-harbor harbor]# mkdir ssl[root@docker-harbor harbor]# cd ssl[root@docker-harbor ssl]# openssl genrsa -out ca.key 4096Generating RSA private key, 4096 bit long modulus……………………………..++…………………………………………………………………………………………………………………….++e is 65537 (0x10001)[root@docker-harbor ssl]# openssl req -x509 -new -nodes -sha512 -days 3650 -subj “/C=ZH/ST=ShangHai/L=ShangHai/O=example/OU=Personal/CN=reg.marin.com” -key ca.key -out ca.crt[root@docker-harbor ssl]# lltotal 8-rw-r–r– 1 root root 2037 Apr 4 18:41 ca.crt-rw-r–r– 1 root root 3243 Apr 4 18:41 ca.key2)获取服务端证书1.Create your own Private Key:[root@docker-harbor ssl]# openssl genrsa -out reg.marin.com.key 4096Generating RSA private key, 4096 bit long modulus………………………………………++………………………………………………………………………………………………………………………………………………………………………………………………….++e is 65537 (0x10001)[root@docker-harbor ssl]# openssl req -sha512 -new -subj “/C=ZH/ST=ShangHai/L=ShangHai/O=example/OU=Personal/CN=reg.marin.com” -key reg.marin.com.key -out reg.marin.com.csr[root@docker-harbor ssl]# lltotal 16-rw-r–r– 1 root root 2037 Apr 4 18:41 ca.crt-rw-r–r– 1 root root 3243 Apr 4 18:41 ca.key-rw-r–r– 1 root root 1708 Apr 4 18:42 reg.marin.com.csr-rw-r–r– 1 root root 3243 Apr 4 18:42 reg.marin.com.key[root@docker-harbor ssl]# cat > v3.ext <<-EOF> authorityKeyIdentifier=keyid,issuer> basicConstraints=CA:FALSE> keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment> extendedKeyUsage = serverAuth> subjectAltName = @alt_names> > [alt_names]> DNS.1=reg.marin.com> DNS.2=reg.marin> DNS.3=marin> EOF[root@docker-harbor ssl]# openssl x509 -req -sha512 -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in reg.marin.com.csr -out reg.marin.com.crtSignature oksubject=/C=ZH/ST=ShangHai/L=ShangHai/O=example/OU=Personal/CN=reg.marin.comGetting CA Private Key[root@docker-harbor ssl]# lltotal 28-rw-r–r– 1 root root 2037 Apr 4 18:41 ca.crt-rw-r–r– 1 root root 3243 Apr 4 18:41 ca.key-rw-r–r– 1 root root 17 Apr 4 18:44 ca.srl-rw-r–r– 1 root root 2098 Apr 4 18:44 reg.marin.com.crt-rw-r–r– 1 root root 1708 Apr 4 18:42 reg.marin.com.csr-rw-r–r– 1 root root 3243 Apr 4 18:42 reg.marin.com.key-rw-r–r– 1 root root 260 Apr 4 18:43 v3.ext3)修改harbor配置,以及为Docker配置服务端证书,key和CA。[root@docker-harbor ssl]# cd ..[root@docker-harbor harbor]# vim harbor.cfg……hostname = reg.marin.comui_url_protocol = httpsssl_cert = ./ssl/reg.marin.com.crtssl_cert_key = ./ssl/reg.marin.com.keyharbor_admin_password = 123456……密码也可以不修改,默认登录用户admin,密码Harbor12345Docker守护进程会将.crt文件解释为CA证书,将.cert文件解释为客户机证书,先将.crt文件转换一份.cert文件。[root@docker-harbor harbor]# cd ssl/[root@docker-harbor ssl]# mkdir -p /etc/docker/certs.d/reg.marin.com[root@docker-harbor ssl]# openssl x509 -inform PEM -in reg.marin.com.crt -out reg.marin.com.cert[root@docker-harbor ssl]# cp reg.marin.com.cert reg.marin.com.key ca.crt /etc/docker/certs.d/reg.marin.com/到此自签成功!3.2.3. 安装DOCKER CE安装所需包yum install -y yum-utils device-mapper-persistent-data lvm2 -y设置稳定存储库yum-config-manager –add-repo https://download.docker.com/linux/centos/docker-ce.repo -y安装DOCKER CE(这一步比较慢,耐心等会儿)yum install docker-ce docker-ce-cli containerd.io -y启动Dockersystemctl start docker通过运行hello-world 映像验证是否正确安装了Docker CE 。docker run hello-world3.2.4. 初始化及安装验证初始化安装:[root@docker-harbor ssl]# [root@docker-harbor ssl]# cd ..[root@docker-harbor harbor]# ./prepareGenerated and saved secret to file: /data/secretkeyGenerated configuration file: ./common/config/nginx/nginx.confGenerated configuration file: ./common/config/adminserver/envGenerated configuration file: ./common/config/core/envGenerated configuration file: ./common/config/registry/config.ymlGenerated configuration file: ./common/config/db/envGenerated configuration file: ./common/config/jobservice/envGenerated configuration file: ./common/config/jobservice/config.ymlGenerated configuration file: ./common/config/log/logrotate.confGenerated configuration file: ./common/config/registryctl/envGenerated configuration file: ./common/config/core/app.confGenerated certificate, key file: ./common/config/core/private_key.pem, cert file: ./common/config/registry/root.crtThe configuration files are ready, please use docker-compose to start the service.执行install.sh脚本,安装harbor仓库注意:在执行install.sh脚本之前,先检查两个问题:1)docker-compose是否安装,否则在运行install.sh时会失败,报错“✖ Need to install docker-compose(1.7.1+) by yourself first and run this script again.”2)docker服务是否正常运行,否则在运行install.sh会失败,报错“Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?”安装Compose运行此命令以下载Docker Compose的当前稳定版本:curl -L “https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)” -o /usr/local/bin/docker-compose对二进制文件应用可执行权限:chmod +x /usr/local/bin/docker-compose执行install.sh脚本,安装harbor仓库[root@docker-harbor harbor]# ./install.sh[Step 0]: checking installation environment …Note: docker version: 18.09.4Note: docker-compose version: 1.24.0[Step 1]: loading Harbor images …bffe2a0fec66: Loading layer [==================================================>] 33.22MB/33.22MB38e174bed467: Loading layer [==================================================>] 8.964MB/8.964MB427e4936ae66: Loading layer [==================================================>] 35.77MB/35.77MB3bfd5214250a: Loading layer [==================================================>] 2.048kB/2.048kBf30df776629d: Loading layer [==================================================>] 3.072kB/3.072kBf87afad43f43: Loading layer [==================================================>] 22.8MB/22.8MB……953717aa0afc: Loading layer [==================================================>] 22.8MB/22.8MBLoaded image: goharbor/registry-photon:v2.6.2-v1.7.4[Step 2]: preparing environment …Clearing the configuration file: ./common/config/adminserver/envClearing the configuration file: ./common/config/core/envClearing the configuration file: ./common/config/core/app.confClearing the configuration file: ./common/config/core/private_key.pemClearing the configuration file: ./common/config/db/env……Generated certificate, key file: ./common/config/core/private_key.pem, cert file: ./common/config/registry/root.crtThe configuration files are ready, please use docker-compose to start the service.[Step 3]: checking existing instance of Harbor …[Step 4]: starting Harbor …Creating network “harbor_harbor” with the default driverCreating harbor-log … doneCreating redis … doneCreating registryctl … doneCreating harbor-db … doneCreating harbor-adminserver … doneCreating registry … doneCreating harbor-core … doneCreating harbor-jobservice … doneCreating harbor-portal … doneCreating nginx … done✔ —-Harbor has been installed and started successfully.—-Now you should be able to visit the admin portal at https://reg.marin.com. For more details, please visit https://github.com/goharbor/harbor .浏览器访问验证:浏览器访问要做域名解析,在本地hosts(C:WindowsSystem32driversetchosts)文件中加入:116.196.88.91 reg.marin.com访问:https://reg.marin.com,并登陆。登录后界面基本操作:新建项目test新建用户marin将用户marin设置为test项目管理员三、环境测试1、远程clone代码测试clone 云主机docker-git上的仓库tomcat-java-demo.git:[root@docker-jenkins ~]# yum install git vim wget -y[root@docker-jenkins ~]# git config –global user.email “hcc@c.com”[root@docker-jenkins ~]# git config –global user.name “hcc”[root@docker-jenkins ~]# git clone git@10.0.0.22:/home/git/tomcat-java-demo.gitCloning into ‘solo’…The authenticity of host ‘10.0.0.22 (10.0.0.22)’ can’t be established.ECDSA key fingerprint is SHA256:XNWQhGsAsqd84k/6OYV3xl1+mPGjtASsxeV1YVLZVas.ECDSA key fingerprint is MD5:b4:bd:16:2b🇩🇪e7:7c:fd:c5:dd:91:75:20:ff:3e:0a.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added ‘10.0.0.22’ (ECDSA) to the list of known hosts.git@10.0.0.22’s password⚠️ You appear to have cloned an empty repository.[root@docker-jenkins ~]# lstomcat-java-demo[root@docker-jenkins ~]# ls tomcat-java-demo/doc Dockerfile LICENSE pom.xml README.md src[root@docker-jenkins ~]# 2、拉取Github demo代码模拟生产项目,拉取github上的一个demo,并上传至本地git库[root@docker-jenkins ~]# mv tomcat-java-demo tomcat-java-demo.bak[root@docker-jenkins ~]# git clone https://github.com/dingkai163/tomcat-java-demo.gitCloning into ’tomcat-java-demo’…remote: Enumerating objects: 185, done.remote: Counting objects: 100% (185/185), done.remote: Compressing objects: 100% (165/165), done.remote: Total 185 (delta 5), reused 178 (delta 4), pack-reused 0Receiving objects: 100% (185/185), 4.50 MiB | 870.00 KiB/s, done.Resolving deltas: 100% (5/5), done.[root@docker-jenkins ~]# cd tomcat-java-demo[root@docker-jenkins tomcat-java-demo]# vim .git/config[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true[remote “origin”] url = git@10.0.0.22:/home/git/tomcat-java-demo.git # 修改为本地的git库地址 fetch = +refs/heads/:refs/remotes/origin/[branch “master”] remote = origin merge = refs/heads/master[root@docker-jenkins tomcat-java-demo]# git add .[root@docker-jenkins tomcat-java-demo]# git status# On branch masternothing to commit, working directory clean[root@docker-jenkins tomcat-java-demo]# git commit -m “all”# On branch masternothing to commit, working directory clean[root@docker-jenkins tomcat-java-demo]# git push origin mastergit@10.0.0.22’s password:Counting objects: 229, done.Compressing objects: 100% (185/185), done.Writing objects: 100% (229/229), 4.52 MiB | 0 bytes/s, done.Total 229 (delta 25), reused 229 (delta 25)To git@10.0.0.22:/home/git/tomcat-java-demo.git * [new branch] master -> master[root@docker-jenkins tomcat-java-demo]#3、自建镜像仓库上传下载用云主机buildimage上传及下载镜像修改主机名为:buildimage[root@c-dfjgjesgqe ]# hostnamectl set-hostname buildimage[root@c-dfjgjesgqe ]# hostname buildimageCtrl+D退出后重新登陆生效安装DOCKER CE安装所需包yum install -y yum-utils device-mapper-persistent-data lvm2 -y设置稳定存储库yum-config-manager –add-repo https://download.docker.com/linux/centos/docker-ce.repo -y安装DOCKER CE(这一步比较慢,耐心等会儿)yum install docker-ce docker-ce-cli containerd.io -y启动Dockersystemctl start docker首先在云主机buildimage上做本地hosts解析[root@buildimage ~]# echo “10.0.0.21 reg.marin.com” >> /etc/hosts其次编辑/etc/docker/daemon.json文件,保存退出[root@buildimage ~]# vim /etc/docker/daemon.json{“insecure-registries”:[“reg.marin.com”] }最后重启下docker,让配置生效[root@buildimage ~]# systemctl restart docker如果没有此步docker login将会报错:[root@buildimage ~]# docker login reg.marin.comUsername (admin): adminPassword: Error response from daemon: Get https://reg.marin.com/v1/users/: x509: certificate signed by unknown authority此时可以通过docker login reg.marin.com 登录harbor,输入用户名及密码:[root@buildimage ~]# docker login reg.marin.comUsername (admin): adminPassword: Login Succeeded在buildimage云主机上构建Tomcat基础镜像,并推送到harbor镜像库:[root@buildimage ~]# mkdir tomcat[root@buildimage ~]# cd tomcat[root@buildimage tomcat]# vim Dockerfile-tomcatFROM centos:7MAINTAINER hanchaochao www.jdcloud.com ENV VERSION=8.5.39 RUN yum install java-1.8.0-openjdk wget curl unzip iproute net-tools -y && \ yum clean all && \ rm -rf /var/cache/yum/RUN wget http://mirrors.shu.edu.cn/apache/tomcat/tomcat-8/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz && \ tar zxf apache-tomcat-${VERSION}.tar.gz && \ mv apache-tomcat-${VERSION} /usr/local/tomcat && \ rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/ && \ mkdir /usr/local/tomcat/webapps/test && \ echo “ok” > /usr/local/tomcat/webapps/test/status.html && \ sed -i ‘1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom”’ /usr/local/tomcat/bin/catalina.sh && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ENV PATH $PATH:/usr/local/tomcat/bin EXPOSE 8080CMD [“catalina.sh”, “run”][root@harbor tomcat]# docker build -t tomcat:v1 -f Dockerfile-tomcat .[root@harbor tomcat]# docker tag tomcat:v1 reg.marin.com/test/tomcat:v1[root@docker-git-harbor tomcat]# docker login reg.marin.com[root@docker-git-harbor tomcat]# docker push reg.marin.com/test/tomcat:v1打开harbor的test仓库,查看镜像已经push成功四、CI流程测试1、Jenkins安装必要插件由于jenkins是离线安装,所有在此需要配置一下插件下载地址:系统管理–>插件管理–>Advanced(高级)修改下方地址,将https修改为http 再点提交若出现问题无法获取插件,请尝试更换地址,如:https://mirrors.tuna.tsinghua…提交后点击可选插件,此时我们可以看到很多可获得插件首先搜索并安装Pipeline插件(如果搜索不到,在已安装中查看是否已经安装完毕)pipeline 是一套运行于jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。再安装SCM to job 插件,同上步骤(搜索,安装)。2、Jenkins项目创建创建jobs选择流水线类型到这里我们就开始配置Pipeline script,点击流水线语法,来自动生成我们需要的配置。如下图,我们Git方式,配置Git仓库地址,再添加认证相关。在示例步骤中下拉选择如图选项,在Repository URL中填写docker-git上的git仓库地址,因为没有添加jenkins到docker-git容器的免密码登陆,所以截图中我们可以看到连接被拒绝的一大串红色提示,我们点击添加按钮这里我们使用的是秘钥认证方式,需要在容器docker-jenkins上生成密钥,然后将jenkins上生成的公钥发送到(docker-git)git服务器上,然后将jenkins上的生成的私钥内容粘贴到下图Key中,这样jenkins就可以免交互的拉取git仓库中的代码了。[root@docker-jenkins ~]# ssh-keygenGenerating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:SHA256:RQZ78bcVhLRQi8fWFPYmyvcnOqlxy980QwLsYFT/iz8 root@docker-jenkinsThe key’s randomart image is:+—[RSA 2048]—-+| .o=oooo*.|| .+.o=.* o|| .oo+.Bo.+|| .oo.+o.= || S .o.oo || .+..|| . .o.++|| +oo.E+|| ..+o..o|+—-[SHA256]—–+[root@docker-jenkins ~]# cd[root@docker-jenkins ~]# ls .ssh/id_rsa id_rsa.pub known_hosts[root@docker-jenkins ~]# ssh-copy-id git@10.0.0.22/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: “/root/.ssh/id_rsa.pub”/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed – if you are prompted now it is to install the new keysgit@10.0.0.22’s password: Number of key(s) added: 1Now try logging into the machine, with: “ssh ‘git@10.0.0.22’“and check to make sure that only the key(s) you wanted were added.[root@docker-jenkins ~]# cat .ssh/id_rsa—–BEGIN RSA PRIVATE KEY—–MIIEogIBAAKCAQEAvrI8lBov+W8v+zSGdu2EP4BPP7Ml+T5KUwc2MKX1RNMMNQxctPUf7PjhbJJvuTpPPbS1+9PAlrPhikDrug3K4+sF/Fiy+/YgoVMlEFrXiSJK1xHiErDLA39WGq+E4ssth3JfrQHV+AINGAh1/NR+Uk+YmPDAuQgA1l7jSH1PN6qTdrYt95HbklAA+Q3omAJJ4Uc80lk7ZdMcdCc0OAtHjCfbRv287qrH4U2OKSlOLljiBHBN……—–END RSA PRIVATE KEY—–[root@docker-jenkins ~]# 配置完成后,我们就可以生成Pipeline脚本了。点击下方生成流水线脚本,然后复制方框内的内容。将生成的流水线脚本复制出来,我生成的流水线脚本如下:checkout([$class: ‘GitSCM’, branches: [[name: ‘/master’]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: ‘9baf7156-9ac6-435d-b0db-86cae51c8fe6’, url: ‘git@10.0.0.22:/home/git/tomcat-java-demo.git’]]])将生成的流水线脚本记录完成后,我们点击左上角返回继续点击配置,完成流水线项目tomcat-java-demo的配置点击流水线,我们所需要的Pipeline脚本如下,将其粘贴到script的拉取代码模块中,并修改分支/master为${branch},其他模块内容自行编写,具体需要修改的地方和脚本如下:node { // 拉取代码 stage(‘Git Checkout’) { checkout([$class: ‘GitSCM’, branches: [[name: ‘${branch}’]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: ‘9baf7156-9ac6-435d-b0db-86cae51c8fe6’, url: ‘git@10.0.0.22:/home/git/tomcat-java-demo.git’]]]) } // 代码编译 stage(‘Maven Build’) { sh ’’’ export JAVA_HOME=/usr/local/jdk /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true ’’’ } // 项目打包到镜像并推送到镜像仓库 stage(‘Build and Push Image’) {sh ‘‘‘REPOSITORY=reg.marin.com/test/tomcat-java-demo:${branch}cat > Dockerfile << EOFFROM reg.marin.com/test/tomcat:v1 MAINTAINER marinRUN rm -rf /usr/local/tomcat/webapps/ADD target/.war /usr/local/tomcat/webapps/ROOT.warEOFdocker build -t $REPOSITORY .docker login reg.marin.com -u admin -p 123456docker push $REPOSITORY’’’ } // 部署到Docker主机 stage(‘Deploy to Docker’) { sh ’’’ REPOSITORY=reg.marin.com/test/tomcat-java-demo:${branch} docker rm -f tomcat-java-demo |true docker pull $REPOSITORY docker container run -d –name tomcat-java-demo -p 88:8080 $REPOSITORY ’’’ }}在Pipeline脚本里面我们指定了一个branch参数,所以我们需要传递一个参数变量,这里我们选择参数化构建,默认值为master分支。然后保存配置。3、Jenkins构建任务构建前我们还需要做两个操作:添加reg.marin.com的hosts解析[root@docker-jenkins ~]# echo “10.0.0.21 reg.marin.com” >> /etc/hosts编辑/etc/docker/daemon.json文件,输入如下信息,保存退出[root@docker-jenkins ~]# vim /etc/docker/daemon.json{“insecure-registries”:[“reg.marin.com”] }最后重启下docker,让配置生效[root@docker-jenkins ~]# systemctl restart docker返回到工作台,我们开始构建任务构建开始构建完成可以通过Console Output输出查看jenkins构建流程成功构建会提示: SUCCESS通过浏览器来访问tomcat-java-demo项目:http://Jenkins主机公网IP:88/![图片上传中…]可以看到正常访问,至此在京东云上基ker+Git 的简单CI流程实践已经成功部署了。原参考地址:https://www.toutiao.com/a6中…] ...

April 16, 2019 · 8 min · jiezi

Docker|持续集成

基本概念敏捷开发什么是敏捷开发?敏捷开发(Agile)是一种以人为核心、迭代、循序渐进的开发方法。在敏捷开发中,软件项目的构建被切分成多个子项目,各个子项目的成果都经过测试,具备集成和可运行的特征。简单地来说,敏捷开发并不追求前期完美的设计、完美编码,而是力求在很短的周期内开发出产品的核心功能,尽早发布出可用的版本。然后在后续的生产周期内,按照新需求不断迭代升级,完善产品。参考文章:http://blog.jobbole.com/110231/持续集成持续集成指的是,频繁地(一天多次)将代码集成到主干。它的好处主要有两个:快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。Martin Fowler 说过,“持续集成并不能消除 Bug,而是让它们非常容易发现和改正。“持续交付持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。持续部署持续部署(continuous deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。持续部署的前提是能自动化完成测试、构建、部署等步骤。基本操作流程总体流程:1.配置好GitRunner脚本和docker相关文件提交到 GitLab2.提交就会触发GitRunner程序,自动下载代码,然后根据脚本进行编译构建,运行。总的目标:实现提交代码就可以集成到测试环境中,无需我们再像以前那样,需要自己安装什么环境,下载代码,编译构建等操作,完全自动处理。大概就是流程如下图:实战操作此类实战文字无法描述,推荐以下教程视频或者你可以找一下相关资源:https://www.bilibili.com/vide…或者文末公众号有相关docker视频教程。总结docker 一次构建,到处运行。隔离机制,与运行环境无关。因为这些特点,就不会出现我们平时说的:“在我的电脑上运行没问题的呀”由于隔离机制,所以不用担心CPU多少核,系统是Linux或者windows,你只要有docker其他的都没有影响。最后如果对 Java、大数据感兴趣请长按二维码关注一波,我会努力带给你们价值。觉得对你哪怕有一丁点帮助的请帮忙点个赞或者转发哦。关注公众号【n平方】,回复2019有相关视频教程哦。

April 15, 2019 · 1 min · jiezi

容器环境下的持续集成最佳实践:构建基于 Drone + GitFlow + K8s 的云原生语义化 CI 工作流

云原生 (Cloud Native) 是伴随的容器技术发展出现的的一个词,最早出自 Pivotal 公司(即开发了 Spring 的公司)的一本技术小册子 Migrating to Cloud-Native Application Architectures, 其中定义了云原生应用应当具备的一些特质,如无状态、可持续交付、微服务化等。随后云原生概念被广为引用,并围绕这一概念由数家大厂牵头,成立了 CNCF 基金会来推进云原生相关技术的发展,主要投资并孵化云原生生态内的若干项目,包括了如 Kubernetes / etcd / CoreDNS 等耳熟能详的重要项目。而这张大大的云原生版图仍然在不断的扩展和完善。从个人理解来说,传统的应用由于年代久远,更多会考虑单机部署、进程间通信等典型的“单机问题”,虽然也能工作在容器下,但由于历史包袱等原因,架构上已经很难做出大的调整。而“云原生”的应用大都是从一开始就为容器而准备,很少考虑在单机环境下使用,有些甚至无法脱离容器环境工作;考虑的场景少,从而更轻量,迭代更快。比如 etcd 之于 zookeeper , traefik 之于 nginx 等,相信只要在容器环境下实现一次同样的功能,就能强烈的体会到云原生应用所特有的便捷之处。在 CNCF 的版图下,持续集成与持续交付(Continuous Integration & Delivery)板块一直缺少一个钦定的主角,虽然也不乏 Travis CI、GitLab、Jenkins 这样的知名项目,但最能给人云原生应用感觉的,应该还是 Drone 这个项目,本文将围绕 Drone 结合 GitFlow 及 Kubernetes 介绍一些容器环境下持续集成、持续发布 (CI/CD) 方面的实践经验。主流 CI/CD 应用对比之前我也介绍过基于 Travis CI 的一些持续集成实践。后来经过一些比较和调研,最终选择了 Drone 作为主力 CI 工具。截止本文,团队已经使用 Drone 有 2 年多的时间,从 v0.6 一路用到现在即将发布的 v1.0,虽然也踩了不少坑,但总的来说 Drone 还是可以满足大部分需求,并以不错的势头在完善和发展的。下面这张表总结了主流的几个 CI/CD 应用的特点项目名称开发语言配置语言公有云服务私有部署备注Travis CIRubyYAML有不支持公共项目免费,私有项目 $69/单进程, $129/2 进程CircleCIClojureYAML有不支持单进程免费,$50/加 1 进程Gitlab CIRubyYAML有支持绑定 Gitlab 代码管理JenkinsJavaGroovy无支持 DroneGoYAML有支持Cloud 版本不支持私有项目,自建版本无此限制Travis CI 和 CircleCI 是目前占有率最高的两个公有云 CI,易用性上相差无几,只是收费方式有差异。由于不支持私有部署,如果并行的任务量一大,按进程收费其实并不划算;而且由于服务器位置的原因,如果推送镜像到国内,速度很不理想。Gitlab CI 虽然好用,但和 Gitlab 是深度绑定的,我们的代码托管在 Github,整体迁移代码库的成本太大,放弃。Jenkins 作为老牌劲旅,也是目前市场占有率最高的 CI,几乎可以覆盖所有 CI 的使用场景,由于使用 Java 编写,配置文件使用 Groovy 语法,非常适合 Java 为主语言的团队。Jenkins 显然是可以满足我们需要的,只是团队并非 Java 为主,又已经习惯了使用 YAML 书写 CI 配置,抱着尝鲜的心态,将 Jenkins 作为了保底的选择。综上,最终选择 Drone 的结论也就不难得出了,Drone 即开源,又可以私有化部署,同时作为云原生应用,官方提供了针对 Docker、Docker Swarm、K8s 等多种容器场景下的部署方案,针对不同容器场景还有特别优化,比如在 Docker Swarm 下 Drone 是以 agent 方式运行 CI 任务的,而在 K8s 下则通过创建 K8s Job 来实现,显然充分利用了容器的优势所在,这也是 Drone 优于其他 CI 应用之处。个人还觉得 Drone 的语法是所有 CI 中最容易理解和掌握的,由于 Drone 每一个步骤都是运行一个 Docker 容器,本地模拟或调试也非常容易。一句话概况 Drone,可以将其看做是可以支持私有化部署的开源版 CircleCI,并且目前仍然没有看到有其他主打这个定位的 CI 工具,因此个人认为 Drone 是 CI/CD 方面云原生应用头把交椅的有力竞争者。容器环境下一次规范的发布应该包含哪些内容技术选型完成后,我想首先演示一下最终的成果,希望能直观的体现出 CI 对自动化效率起到的提升,不过这就涉及到一个问题:在容器环境下,一次发布应该包含哪些内容,其中有哪些部分是可以被 CI 自动化完成的。这个问题虽然每家公司各不相同,不过按经验来说,容器环境下一次版本发布通常包含这样一个 Checklist:[ ] 代码的下载构建及编译[ ] 运行单元测试,生成单元测试报告及覆盖率报告等[ ] 在测试环境对当前版本进行测试[ ] 为待发布的代码打上版本号[ ] 编写 ChangeLog 说明当前版本所涉及的修改[ ] 构建 Docker 镜像[ ] 将 Docker 镜像推送到镜像仓库[ ] 在预发布环境测试当前版本[ ] 正式发布到生产环境看上去很繁琐对吗,如果每次发布都需要人工去处理上述的所有内容,不仅容易出错,而且也无法应对 DevOps 时代一天至少数次的发布频率,那么下面就来使用 CI 来解决所有问题吧。CI 流程演示为了对 CI 流程有最直观的认识,我创建了一个精简版的 Github 项目 AlloVince/drone-ci-demo 来演示完整的流程,同时项目对应的 CI 地址是 cloud.drone.io/AlloVince/drone-ci-demo ,项目自动构建的 Docker 镜像会推送到 docker registry 的 allovince/drone-ci-demo,。为了方便说明,假设这个项目的核心文件只有 index.html 一个静态页面。单人开发模式目前这个项目背后的 CI 都已经配置部署好,假设我是这个项目的唯一开发人员,如何开发一个新功能并发布新版本呢?Clone 项目到本地, 修改项目代码, 如将 Hello World 改为 Hello World V2。git add .,然后书写符合约定的 Commit 并提交代码, git commit -m “feature: hello world v2”推送代码到代码库git push,等待数分钟后,开发人员会看到单元测试结果,Github 仓库会产生一次新版本的 release,release 内容为当前版本的 ChangeLog, 同时线上已经完成了新功能的发布。虽然在开发者看来,一次发布简单到只需 3 个指令,但背后经过了如下的若干次交互,这是一次发布实际产生交互的时序图,具体每个环节如何工作将在后文中详细说明。多人开发模式一个项目一般不止一个开发人员,比如我是新加入这个项目的成员,在这个 Demo 中应该如何上线新功能呢?同样非常简单:Clone 项目到本地,创建一个分支来完成新功能的开发, git checkout -b feature/hello-world-v3。在这个分支修改一些代码,比如将Hello World V2修改为Hello World V3git add .,书写符合规范的 Commit 并提交代码, git commit -m “feature: hello world v3”将代码推送到代码库的对应分支, git push origin feature/hello-world如果功能已经开发完毕,可以向 Master 分支发起一个 Pull Request,并让项目的负责人 Code ReviewReview 通过后,项目负责人将分支合并入主干,Github 仓库会产生一次新版本的 release,同时线上已经完成了新功能的发布。这个流程相比单人开发来多了 2 个环节,很适用于小团队合作,不仅强制加入了 Code Review 把控代码质量,同时也避免新人的不规范行为对发布带来影响。实际项目中,可以在 Github 的设置界面对 master 分支设置写入保护,这样就从根本上杜绝了误操作的可能。当然如果团队中都是熟手,就无需如此谨慎,每个人都可以负责 PR 的合并,从而进一步提升效率。GitFlow 开发模式在更大的项目中,参与的角色更多,一般会有开发、测试、运维几种角色的划分;还会划分出开发环境、测试环境、预发布环境、生产环境等用于代码的验证和测试;同时还会有多个功能会在同一时间并行开发。可想而知 CI 的流程也会进一步复杂。能比较好应对这种复杂性的,首选 GitFlow 工作流, 即通过并行两个长期分支的方式规范代码的提交。而如果使用了 Github,由于有非常好用的 Pull Request 功能,可以将 GitFlow 进行一定程度的简化,最终有这样的工作流:以 dev 为主开发分支,master 为发布分支开发人员始终从 dev 创建自己的分支,如 feature-afeature-a 开发完毕后创建 PR 到 dev 分支,并进行 code reviewreview 后 feature-a 的新功能被合并入 dev,如有多个并行功能亦然待当前开发周期内所有功能都合并入 dev 后,从 dev 创建 PR 到 masterdev 合并入 master,并创建一个新的 release上述是从 Git 分支角度看代码仓库发生的变化,实际在开发人员视角里,工作流程是怎样的呢。假设我是项目的一名开发人员,今天开始一期新功能的开发:Clone 项目到本地,git checkout dev。从 dev 创建一个分支来完成新功能的开发, git checkout -b feature/feature-a。在这个分支修改一些代码,比如将Hello World V3修改为Hello World Feature Agit add .,书写符合规范的 Commit 并提交代码, git commit -m “feature: hello world feature A"将代码推送到代码库的对应分支, git push origin feature/feature-a:feature/feature-a由于分支是以feature/命名的,因此 CI 会运行单元测试,并自动构建一个当前分支的镜像,发布到测试环境,并自动配置一个当前分支的域名如 test-featue-a.avnpc.com联系产品及测试同学在测试环境验证并完善新功能功能通过验收后发起 PR 到 dev 分支,由 Leader 进行 code reviewCode Review 通过后,Leader 合并当前 PR,此时 CI 会运行单元测试,构建镜像,并发布到测试环境此时 dev 分支有可能已经积累了若干个功能,可以访问测试环境对应 dev 分支的域名,如 test.avnpc.com,进行集成测试。集成测试完成后,由运维同学从 Dev 发起一个 PR 到 Master 分支,此时会 CI 会运行单元测试,构建镜像,并发布到预发布环境测试人员在预发布环境下再次验证功能,团队做上线前的其他准备工作运维同学合并 PR,CI 将为本次发布的代码及镜像自动打上版本号并书写 ChangeLog,同时发布到生产环境。由此就完成了上文中 Checklist 所需的所有工作。虽然描述起来看似冗长,但不难发现实际作为开发人员,并没有任何复杂的操作,流程化的部分全部由 CI 完成,开发人员只需要关注自己的核心任务:按照工作流规范,写好代码,写好 Commit,提交代码即可。接下来将介绍这个以 CI 为核心的工作流,是如何一步步搭建的。Step by Step 构建 CI 工作流Step.0: 基于 K8s 部署 Drone v1.0.0以 Github 为例,截止本文完成时间(2019 年 3 月 28 日), Drone 刚刚发布了第一个正式版本 v1.0.0。官方文档已经提供了分别基于 Docker、K8s 的 Drone 部署说明,不过比较简略,因此这里给出一个相对完整的配置文件。首先需要在 Github 创建一个 Auth App,用于 repo 的访问授权。应用创建好之后,会得到 Client ID 和 Client Secret 。同时 Authorization callback URL 应填写 Drone 服务对应域名下的 /login,如https://ci.avnpc.com/loginDrone 支持 SQLite、MySQL、Postgres、S3 等多种后端存储,主要用于记录 build logs 等文本信息,这些信息并不是特别重要,且我们的 CI 有可能做迁移,因此个人更推荐使用 SQLite。而在 K8s 环境下,SQLite 更适合用挂载 NAS 的方式供节点使用,因此首先将存储的部分独立为文件drone-pvc.yml,可以根据实际情况配置 nfs.path 和 nfs.serverkubectl apply -f drone-pvc.yamlDrone 的配置主要涉及两个镜像:drone/kubernetes-secrets 加密数据服务,用于读取 K8s 的 secretsdrone/drone:1.0.0-rc.6 就是 Drone 的 server 端,由于在 K8s 下 Drone 利用了 Job 机制,因此不需要部署 agent。这部分配置较长,可以直接参考示例 drone.yaml主要涉及到的配置项包括:drone/kubernetes-secrets 镜像中SECRET_KEY: 数据加密传输所用的 key,可以使用 openssl rand -hex 16 生成一个drone/drone镜像中DRONE_KUBERNETES_ENABLED: 开启 K8s 模式DRONE_KUBERNETES_NAMESPACE: Drone 所使用的 Namespace, 这里使用 defaultDRONE_GITHUB_SERVER: Github 服务器地址,一般为 https://github.comDRONE_GITHUB_CLIENT_ID: 上文创建 Github Auth App 得到的 Client IDDRONE_GITHUB_CLIENT_SECRET: 上文创建 Github Auth App 得到的 Client SecretDRONE_SERVER_HOST: Drone 服务所使用的域名DRONE_SERVER_PROTO: http 或 httpsDRONE_DATABASE_DRIVER: Drone 使用的数据库类型,这里为 sqlite3DRONE_DATABASE_DATASOURCE: 这里为 SQLite 数据库的存放路径DRONE_SECRET_SECRET: 对应上文的 SECRET_KEYDRONE_SECRET_ENDPOINT: 加密数据服务的地址,这里通过 k8s service 暴露,无需修改最后部署即可kubectl apply -f drone.yaml部署后首次登录 Drone 就会跳转到 Github Auth App 进行授权,授权完毕后可以看到所有能读写的 Repo,选择需要开启 CI 的 Repo,点击 ACTIVATE 即可。 如果开启成功,在 Github Repo 的 Settings > Webhooks 下可以看到 Drone 的回调地址。Step.1: Hello World for Drone在正式开始搭建工作流之前,首先可以测试一下 Drone 是否可用。Drone 默认的配置文件是 .drone.yml, 在需要 CI 的 repo 根目录下创建.drone.yml, 内容如下,提交并git push到代码仓库即可触发 Drone 执行 CI。kind: pipeline name: deploy steps: - name: hello-world image: docker commands: - echo “hello world"Drone v1 的语法主要参考的 K8s 的语法,非常直观,无需阅读文档也可以知道,我们首先定义了一个管道 (pipeline),管道由若干步骤 (step) 组成,Drone 的每个步骤是都基于容器实现的,因此 Step 的语法就回到了我们熟悉的 Docker,一个 Step 会拉取 image 定义的镜像,然后运行该镜像,并顺序执行 commands 定义的指令。 在上例中,Drone 首先 clone git repo 代码到本地,然后根据 .drone.yml 所定义的,拉取 Docker 的官方镜像,然后运行该进行并挂载 git repo 的代码到 /drone/src 目录。在 Drone 的界面中,也可以清楚的看到这一过程。本阶段对应代码部分: https://github.com/AlloVince/...Drone 构建记录: https://cloud.drone.io/AlloVi...Docker 镜像: 无Step.2: 单人工作流,自动化单元测试与 Docker 镜像构建有了 Hello World 的基础,接下来我们尝试将这个工作流进行扩充。为了方便说明,这里假设项目语言为 js,项目内新增了test/index.js文件用于模拟单元测试,一般在 CI 中,只要程序的返回值为 0,即代表运行成功。这个文件中我们仅仅输出一行 Log Unit test passed用于模拟单元测试通过。 我们希望将代码打包成 Docker 镜像,根目录下增加了 Dockerfile 文件,这里直接使用 Nginx 的官方镜像,构建过程只有 1 行COPY index.html /usr/share/nginx/html/, 这样镜像运行后可以通过 http 请求看到index.html的内容。至此我们可以将工作流改进为:当 master 分支接收到 push 后,运行单元测试当 github 发布一次 release, 构建 Docker 镜像,并推送到镜像仓库对应的 Drone 配置文件如下kind: pipeline name: deploy steps: - name: unit-test image: node:10 commands: - node test/index.js when: branch: master event: push - name: build-image image: plugins/docker settings: repo: allovince/drone-ci-demo username: allovince password: from_secret: DOCKER_PASSWORD auto_tag: true when: event: tag虽然比 Hello World 复杂了一些,但是可读性仍然很好,配置文件中出现了几个新概念:Step 运行条件, 即 when 部分,上例中展示了当代码分支为 master,且收到一个 push;以及当代码被标记 tag 这两种情况。Drone 还支持 repo、运行结果等很多其他条件,可以参考 Drone Conditions 文档。Plugin 插件,上例中用于构建和推送镜像的是 plugins/docker 这个 Plugin, 一个 Plugin 本质上仍然是一个 Docker 镜像,只是按照 Drone 的规范接受特定的输入,并完成特定的操作。所以完全可以将 Plugin 看做一个无法更改 command 的 Docker 镜像。Docker 这个 Plugin 由 Drone 官方提供,用于 Docker 镜像的构建和推送,具体的用法可以查看Docker 插件的文档 。例子中演示的是将镜像推送到私有仓库,如果不做特殊配置,镜像将被推送到 Docker 的官方仓库。 此外 Docker 插件还有一个很方便的功能,如果设置 auto_tag: true,将根据代码的版本号自动规划 Docker 镜像的标签,如代码版本为1.0.0,将为 Docker 镜像打三个标签 1, 1.0, 1.0.0。如果代码版本号不能被解析,则镜像标签为 latest。目前 Drone 的插件已经有很多,可以覆盖主流的云服务商和常见的工作流,并且自己制作插件的成本也不高。Secret 加密数据,镜像仓库的用户名和密码都属于敏感信息,因此可以使用 from_secret 获取加密数据。一条加密数据就是一个 key / value 对,如上例中的 DOCKER_PASSWORD 就是我们自己定义的加密数据 key。即便加密数据在 log 中被打印,UI 也只能看到 。加密数据的 value 需要提前保存好,保存的方式有 3 种:通过 Drone UI 界面中, repo -> Settings -> Secrets 添加,所添加的加密数据将保存在 Drone 的数据库中,仅能在当前 repo 中使用。通过Drone cli 加密后保存在 .drone.yml文件中, 使用范围仅限 yaml 文件内通过 K8s 保存为K8s Secret,称为 External Secrets,所有的 repo 都可以共享。如果是团队使用的话,这种保存方式显然是最方便的,但也要注意安全问题,因此 External Secrets 还支持 repo 级别的权限管理, 可以只让有当前 repo 写入权限的人才能使用对应 secret。这个阶段对应代码仓库: https://github.com/AlloVince/...push 时触发的 Drone CI: https://cloud.drone.io/AlloVi...release 时触发的 Drone CI: https://cloud.drone.io/AlloVi...release 后 CI 构建的 Docker 镜像: allovince/drone-ci-demo:latestStep.3: GitFlow 多分支团队工作流上面的工作流已经基本可以应付单人的开发了,而在团队开发时,这个工作流还需要一些扩展。不需要引入 Drone 的新功能,只需要在上文基础上根据分支做一点调整即可。首先保证单元测试位于 steps 的第一位,并且限定团队工作的分支,在 push 和 pull_request 时,都能触发单元测试。- name: unit-test image: node:10 commands: - node test/index.js when: branch: include: - feature/ - master - dev event: include: - push - pull_request然后根据 Gitflow 的流程对于不同的分支构建 Docker 镜像并打上特定标签,以 feature 分支为例,下面的配置约定了当分支名满足 feature/,并收到 push 时,会构建 Docker 镜像并打标签,标签名称为当前分支名去掉 feature/。如分支 feature/readme, 对应 docker 镜像为 allovince/drone-ci-demo:readme,考虑到 feature 分支一般都出于开发阶段,因此新的镜像会覆盖旧的。配置如下- name: build-branch-image image: plugins/docker settings: repo: allovince/drone-ci-demo username: allovince password: from_secret: DOCKER_PASSWORD tag: - ${DRONE_BRANCH##feature/} when: branch: feature/ event: push镜像的 Tag 处不再使用自动方式,其中DRONE_BRANCH是 Drone 的内置环境变量 (Environment),对应当前的分支名。##feature/是执行了一个字符串的替换操作 (Substitution)。更多的环境变量和字符串操作都可以在文档中找到。以此类推,可以查看这个阶段的完整 .drone.yml ,此时我们的工作流示例如下:团队成员从 dev 分支 checkout 自己的分支 feature/readme向feature/readme提交代码并 push, CI 运行单元测试,构建镜像allovince/drone-ci-demo:readme功能开发完成后,团队成员向 dev 分支 发起 pull request , CI 运行单元测试团队其他成员 merge pull request, CI 运行单元测试,构建镜像allovince/drone-ci-demo:test运维人员从 dev 向 master 发起 pull request,CI 运行单元测试,并构建镜像allovince/drone-ci-demo:latest运维人员 merge pull request, 并 release 新版本 pre-0.0.2, CI 构建镜像allovince/drone-ci-demo:pre-0.0.2可能细心的同学会发现 dev -> master 的 pull request 时,构建镜像失败了,这是由于 Drone 出于安全考虑限制了在 pull request 时默认无法读取加密数据,因此无法得到 Docker Registry 密码。如果是私有部署的话,可以在 Repo Settings 中勾选Allow Pull Requests,此处就可以构建成功。Step.4: 语义化发布上面基本完成了一个支持团队协作的半自动 CI 工作流,如果不是特别苛刻的话,完全可以用上面的工作流开始干活了。不过基于这个工作流工作一段时间,会发现仍然存在痛点,那就是每次发布都要想一个版本号,写 ChangeLog,并且人工去 release。标记版本号涉及到上线后的回滚,追溯等一系列问题,应该是一项严肃的工作,其实如何标记早已有比较好的方案,即语义化版本。在这个方案中,版本号一共有 3 位,形如 1.0.0,分别代表:主版本号:当你做了不兼容的 API 修改,次版本号:当你做了向下兼容的功能性新增,修订号:当你做了向下兼容的问题修正。虽然有了这个指导意见,但并没有很方便的解决实际问题,每次发布要搞清楚代码的修改到底是不是向下兼容的,有哪些新的功能等,仍然要花费很多时间。而语义化发布 (Semantic Release) 就能很好的解决这些问题。语义化发布的原理很简单,就是让每一次 Commit 所附带的 Message 格式遵守一定规范,保证每次提交格式一致且都是可以被解析的,那么进行 Release 时,只要统计一下距离上次 Release 所有的提交,就分析出本次提交做了何种程度的改动,并可以自动生成版本号、自动生成 ChangeLog 等。语义化发布中,Commit 所遵守的规范称为约定式提交 (Conventional Commits)。比如 node.js、 Angular、Electron 等知名项目都在使用这套规范。语义化发布首先将 Commit 进行分类,常用的分类 (Type) 有:feat: 新功能fix: BUG 修复docs: 文档变更style: 文字格式修改refactor: 代码重构perf: 性能改进test: 测试代码chore: 工具自动生成每个 Commit 可以对应一个作用域(Scope),在一个项目中作用域一般可以指不同的模块。当 Commit 内容较多时,可以追加正文和脚注,如果正文起始为BREAKING CHANGE,代表这是一个破坏性变更。以下都是符合规范的 Commit:feat: 增加重置密码功能fix(邮件模块): 修复邮件发送延迟BUGfeat(API): API重构BREAKING CHANGE: API v3上线,API v1停止支持有了这些规范的 Commit,版本号如何变化就很容易确定了,目前语义化发布默认的规则如下Commit版本号变更BREAKING CHANGE主版本号feat次版本号fix / perf修订号因此在 CI 部署 semantic-release 之后,作为开发人员只需要按照规范书写 Commit 即可,其他的都由 CI 完成。具体如何将语义化发布加入 CI 流程中呢, semantic-release 是 js 实现的,如果是 js 的项目,可以直接在package.json中增加配置项,而对于任意语言的项目,推荐像 Demo 中一样,在根目录下增加 配置文件release.config.js。这个配置目的是为了禁用默认开启的 npm 发布机制,可以直接套用。semantic-release 要执行 Github release,因此我们需要在 CI 中配置自己的 Personal access tokens 让 CI 有 Github repo 的读写权限, 可以通过 Github 点击自己头像 -> Settings -> Developer settings -> Personal access tokens -> Generate new token 生成一个 Token。 然后在 Drone 的 repo 设置界面新增一个 Secret, key 为 GITHUB_TOKEN, value 填入刚生成的 Token。最后在 .drone.yml 中增加这样一段就可以了。- name: semantic-release image: gtramontina/semantic-release:15.13.3 environment: GITHUB_TOKEN: from_secret: GITHUB_TOKEN entrypoint: - semantic-release when: branch: master event: push来再次模拟一下流程,feature 分支部分与上文相同从 dev 向 master 发起 pull request,CI 运行单元测试,并构建镜像allovince/drone-ci-demo:latestmerge pull request,CI 会执行单元测试并运行 semantic-release , 运行成功的话能看到 Github 新增 release v1.0.0Github release 再次触发CI 构建生产环境用 Docker 镜像allovince/drone-ci-demo:1.0.0最终我们能得到这样一个赏心悦目的 releaseStep.5: Kubernetes 自动发布Docker 镜像推送到仓库后,我们还剩最后一步就可以完成全自动发布的闭环,即通知 Kubernetes 将镜像发布到生产环境。这一步实现比较灵活,因为很多云服务商在容器服务都会提供 Trigger 机制,一般是提供一个 URL,只要请求这个 URL 就可以触发容器服务的发布。Demo 中我们使用更为通用的方法,就是将 kubectl 打包为容器,以客户端调用 K8s 集群 Master 节点 API ( kube-apiserver ) 的形式完成发布。假设我们在生产环境下 drone-ci-demo 项目的 K8s 发布文件如下— apiVersion: extensions/v1beta1 kind: Deployment metadata: name: ci-demo-deployment namespace: default spec: replicas: 1 template: spec: containers: - image: allovince/drone-ci-demo name: ci-demo restartPolicy: Always对应 .drone.yml 中增加 step 如下。这里使用的插件是honestbee/drone-kubernetes, 插件中kubectl 连接 API 使用的是证书+ Token 的方式鉴权,因此需要先获得证书及 Token, 已经授权的 Token 保存于 k8s secret,可以通过kubectl get secret [ your default secret name ] -o yaml | egrep ‘ca.crt:|token:‘获得并配置到 drone 中,注意插件要求 token 是明文的,需要 base64 解码一下:echo [ your token ] | base64 -d && echo ‘’- name: k8s-deploy image: quay.io/honestbee/drone-kubernetes settings: kubernetes_server: from_secret: KUBERNETES_SERVER kubernetes_cert: from_secret: KUBERNETES_CERT kubernetes_token: from_secret: KUBERNETES_TOKEN namespace: default deployment: ci-demo-deployment repo: allovince/drone-ci-demo container: ci-demo tag: - ${DRONE_TAG} when: event: tag在示例)中,可以看到在语义化发布之后 CI 会将新版本的 Docker 镜像自动发布到 K8s),这里为了演示仅打印了指令并未实际运行。相当于运行了如下的指令:kubectl -n default set image deployment/ci-demo-deployment ci-demo=allovince/drone-ci-demo:v1.0.2由于自动发布的环节势必要接触到生产服务器,需要格外注意安全问题,首推的方式当然是将 CI 和 K8s 集群放于同一内网中,同时可以使用 K8s 的 RBAC 权限控制,为自动发布单独创建一个用户),并删除不必要的权限。后话总结一下,本文展示了从 Hello World 到 单人单分支手动发布 到 团队多分支 GitFlow 工作流 到 团队多分支 semantic-release 语义化发布 到 通知 K8s 全自动发布,如何从零开始一步一步搭建 CI 将团队开发、测试、发布的流程全部自动化的过程,最终能让开发人员只需要认真提交代码就可以完成日常的所有 DevOps 工作。最终 Step 的完成品可以适配之前的所有 Step,如果不太在意实现细节的话,可以在此基础上稍作修改,直接使用。然而写好每一个 Commit 这个看似简单的要求,其实对于大多数团队来说并不容易做到,在实施过程中,经常会遇到团队成员不理解为什么要重视 Commit 规范,每个 Commit 都要深思熟虑是否过于吹毛求疵等等疑问。以 Commit 作为 CI 的核心,个人认为主要会带来以下几方面的影响:一个好的 Commit,代表着开发人员对当前改动之于整个系统的影响,有非常清楚的认识,代码的修改到底算 feat 还是 fix ,什么时候用 BREAKING CHANGE 等都是要仔细斟酌的,每个 Commit 都会在 ChangeLog 里“留底”,从而约束团队不随意提交未经思考的代码,提高代码质量一个好的 Commit 也代表开发人员有能力对所实现功能进行精细的划分,一个分支做的事情不宜过多,一个提交也应该专注于只解决一个问题,每次提交(至少是每次 push )都应该保持系统可构建、可运行、可测试,如果能坚持做到这些,对于合并代码时的冲突解决,以及集成测试都有很大帮助。由于每次发布能清楚的看到所有关联的 Commit 以及 Commit 的重要程度,那么线上事故的回滚也会非常轻松,回滚到哪个版本,回滚后哪些功能会受到影响,只要看 CI 自动生成的 Release 记录就一目了然。如果没有这些,回滚误伤到预期外的功能从而引发连锁反应的惨痛教训,可能很多运维都有过类似经历吧。因此 CI 自动化其实是锦上添花而非雪中送炭,如果团队原本就无视规范,Commit 全是空白或者没有任何意义的单词,分支管理混乱,发布困难,奢望引入一套自动化 CI 来能解决所有这些问题,无疑是不现实的。而只有原本就重视代码质量,有一定规范意识,再通过自动化 CI 来监督约束,团队在 CI 的帮助下代码质量提高,从而有机会进一步改进 CI 的效率,才能形成良性循环。愿天下不再有难发布的版本。References:云原生应用之路相关讨论可以在我的 Telegram Group 给我留言。 ...

April 8, 2019 · 7 min · jiezi

手摸手教你搭建 Travis CI 持续集成和自动化部署

很早之前我就在用 Travis CI 做持续集成了,虽然只是停留在 zhuang bi 的阶段,但或多或少也保证了代码的提交质量。最近在写一个 《JavaScript API 全解析》系列的 Book,需要经常把文章部署到服务器上,手动部署实在是烦,索性花了一天时间研究了一下自动化部署。这篇文章是对 Travis CI 持续集成和自动化部署的总结,以飨社区。前戏Travis CI 目前有两个网站,一个是 travis-ci.com,另一个是 travis-ci.org. 前者用于企业级和私有仓库,后者用于开源的公有仓库。实际上 free plan 也可以使用 travis-ci.com,但优先级很低,跑个自动化动辄两个小时,因此我们使用 travis-ci.org.首先打开 Travis CI 官网,并用 GitHub 账号登录,授权后 Travis CI 会同步你的仓库信息。接下来把需要做自动化的工程授权给 Travis CI.最好有一台 Linux 的服务器,我的是 Cent OS 7.6.x 64bit.我们点开一个工程,再切到设置,可以看到在 push 代码和 PR 时都会触发持续集成,当然可以根据需求手动配置。持续集成为了让持续集成像那么回事儿,我们先在 master 上切一个 develop 分支,再在 develop 上切一个 featur/ci 分支。接着我们再用 Jest 写几个测试用例,注意如果项目中没有测试脚本而 .travis.yml 文件里面包含 yarn test,自动化 一定 报错。关于 Jest 这里不详细说,只贴出几个示例代码。import * as utils from ‘../utils/util’;test(‘should get right date’, () => { expect(utils.formatJSONDate(‘2019-03-10T04:15:40.629Z’)).toBe( ‘2019-03-10 12:15:40’, );});test(‘should get right string’, () => { expect(utils.upperFirstLetter(‘AFTERNOON’)).toBe(‘Afternoon’); expect(utils.upperFirstLetter(‘YANCEY_LEO’)).toBe(‘Yancey Leo’);});然后我们在工程的根目录下新建一个文件 .travis.yml,并复制下面的代码。language: node_jsnode_js: - 8branchs: only: - mastercache: directories: - node_modulesinstall: - yarn installscripts: - yarn test - yarn build简单解释一下,工程使用 Node.js 8.x,并且只在 master 分支有变动时触发 自动化部署(正常的提交、PR 都会正常走持续集成),接着将 node_modules 缓存起来(你懂的),最后安装依赖、跑测试脚本、在沙箱部署。因此,理论上只要跑通这套流程,我们就可以放心的部署到真实环境了。提交一下代码,并 pull request 到 develop 分支。在此过程中我们触发了 push 和 PR,所以会跑两个 CI。待到两个都成功跑完后,我们就可以放心的合到 develop 分支了。(这里我还做了代码质量检测,有兴趣可以戳 Codacy)最后我们回到 Travis CI 的官网,可以看到一套完整的构建流程:安装依赖 -> 测试 -> 沙箱部署持续部署创建 rsa 对,并给予权限首先登录你的服务器,一般来讲我们不会直接在 root 上操作,所以这里新增一个 caddy 的用户 。具体怎样在 Linux 新建用户请自行谷歌。接下来 cd 到 ~/.ssh,看看有没有一对 id_rsa 和 id_rsa.pub,如果没有就用 ssh-keygen 生成。给予 .ssh 文件夹 700 权限,给予 .ssh 里的文件 600 权限。(看下面这张图,你的文件夹里可能暂时没有 authorized_keys、 known_host、config 这三个文件,后面会说到。)$ sudo chmod 700 ~/.ssh/$ sudo chmod 600 ~/.ssh/将生成的公钥添加到受信列表进入到 .ssh 文件夹里,执行下面的命令,可以看到公钥被添加到受信列表。$ cat id_rsa.pub >> authorized_keys$ cat authorized_keys测试登录在 .ssh 目录下创建一个文件 config,输入如下代码并保存。Host testHostName 当前服务器的IPUser 当前用户名IdentitiesOnly yesIdentityFile ~/.ssh/id_rsa因为 authorized_keys 和 config 文件都是新增的,它们还没被赋予 600 权限,所以重新执行一遍 sudo chmod 600 ~/.ssh/.然后我们输入 ssh test,不出意外会重新登录 ssh。如果你的公钥从来没有被使用过,会提示 Are you sure you want to continue connecting (yes/no)? ,输入 yes 后也会正常重新登录,并且在.ssh 文件夹下还会生成一个 known_hosts 文件.安装 Ruby因为 Travis 客户端是用 Ruby 写的,所以我们得先安装 Ruby.首先安装需要的依赖包:$ yum install gcc-c++ patch readline readline-devel zlib zlib-devel \ libyaml-devel libffi-devel openssl-devel make \ bzip2 autoconf automake libtool bison iconv-devel sqlite-devel接下来安装 RVM,并载入 RVM 环境。RVM 是 Ruby 的版本管理工具,类似于 Node 的 NVM.$ gpg –keyserver hkp://keys.gnupg.net –recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3$ \curl -sSL https://get.rvm.io | bash -s stable# 载入 rvm 环境$ source ~/.rvm/scripts/rvm安装完之后输入 rvm -v 做下检查,如果有 rvm 1.29.1 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io/] 的字样证明安装成功。最后安装 Ruby,这里选择 v2.4.1 版本,安装需要一段时间,完成后记得将此版本设为默认。$ rvm install 2.4.1$ rvm 2.4.1 –default执行一下 ruby -v 和 gem -v,如果和下图差不多证明安装成功。安装 Travis 客户端执行下面的命令以安装 Travis 客户端。$ gem install travis安装完成后执行 travis,它会让你安装相应的 Shell, 输入 yes 即可。配置免密登录将你的工程克隆下来,并进入到工程目录,然后登录你的 GitHub 账号。$ travis login –auto执行下面这句,它会利用服务器的私钥加密成一个叫做 id_rsa.enc 的文件,这个文件被用于 travis 登录你服务器的凭证,从而达到免密的目的。$ travis encrypt-file ~/.ssh/id_rsa –add我们执行一下 ll,可以看到根目录下多出一个 id_rsa.enc 文件来,并且 cat .travis.yml,发现多出了 before_install.为了更好地组织代码,我们在项目的根目录新建一个文件夹 .travis,然后将 id_rsa.enc 放到里面。配置 after_success 钩子在写这一小节之前,我们先看一看 Travis 的生命周期:before_install 安装依赖前install 安装依赖时before_script 执行脚本前script 执行脚本时after_success 或 after_failure 执行脚本成功(失败)后before_deploy 部署前deploy 部署时after_deploy 部署后after_script 执行脚本后因此 after_success 可用在成功通过测试脚本之后执行部署相关的脚本。当然细一点可以使用 deploy 相关的钩子,这里不做太复杂。打开 .travis.yml文件,直接上全部代码。language: node_jssudo: truenode_js: - 8branchs: only: - master# 这里填写服务器的ip,若端口号不是22,后面要注明端口号addons: ssh_known_hosts: - 你的服务器IPcache: directories: - node_modulesbefore_install: # 因为我们把 id_rsa.enc 移到了.travis 文件夹下,所以 -in 后面要改成 .travis/id_rsa.enc # 其次,-out 后面自动生成的是 ~/.ssh/id_rsa,要把 \ 去掉,否则会编译失败 - openssl aes-256-cbc -K $encrypted_XXXXXXXXXXXX_key -iv $encrypted_XXXXXXXXXXXX_iv -in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d # 开启 ssh-agent,即允许使用 ssh 命令 - eval “$(ssh-agent -s)” # 给予 id_rsa 文件权限,避免警告 - chmod 600 ~/.ssh/id_rsa # 将私钥添加到 ssh - ssh-add ~/.ssh/id_rsainstall: - yarn installscripts: - yarn test - yarn buildafter_success: # 登录服务器,执行部署脚本,其实最好把后面一串写成 shell 文件 - ssh caddy@你的服务器IP -o StrictHostKeyChecking=no ‘cd /var/www/jsapi/JavaScript-APIs-Set && git pull && yarn install && yarn build’走一遍正式的流程至此,搭建 Travis CI 持续集成和自动化部署就算完成了,可能不太严谨,但基本是这么一个思路。下面我们梳理一遍流程。我们先在 feature/ci 分支修改一段代码,提交分支,并 PR 到 develop,此时会运行两个 CI。当两个 CI 都跑通了,我们可以放心的 merge request 到 develop 分支。接下来让 develop PR 到 master,此时会运行两个 CI(一个是 develop 分支,一个是测试合并到 master 的 CI)。当两个 CI 都跑通了,我们可以放心的 merge request 到 master 分支。merge request 之后会跑最后一个流程, 也就是自动部署,部署成功后线上代码就会更新了。加入徽章别忘了把 build passing 徽章添加到你的 README.md 文件中。最后不知道你有没有发现,Travis CI 支持 LGBT…以上、よろしく。参考How to Encrypt/Decrypt SSH Keys for DeploymentTravis-CI 自动化测试并部署至自己的 CentOS 服务器CentOS 7 使用 rvm 安装 ruby 搭建 jekyll 环境 ...

March 28, 2019 · 3 min · jiezi

持续集成实操视频演示

点击观看持续集成实操视频演示持续集成在现代软件研发流程中,扮演了十分重要的角色。通过对每次提交的代码不断进行自动化的单元测试、代码检查、编译构建,甚至自动部署,持续集成大大降低了开发人员的工作负担,减少了重复劳动,提升代码质量和开发效率。CODING 企业版正式推出持续集成功能后,已经有近 200 家企业进行了超过 30000 次的构建。在这个过程中我们也收到了很多宝贵的意见与建议,在综合考虑了用户反馈后,我们对持续集成功能进行了一次大更新,增加了 Docker 支持、持久化缓存、多任务并行等重要功能。什么是持续集成集成指的是工程师个人研发的部分向软件整体进行合并交付的过程。持续指工程师把任务分成很多部分,每完成一个部分就进行一次交付,这样能尽早发现问题,马上进行调整。简单的说,持续集成(Continuous Integration)强调的是工程师提交了新代码之后,立刻进行自动化的构建、(单元)测试。根据实时测试结果确定新代码和原有代码能否正确地集成在一起放大,及时的反馈也能有效减少发现问题时的回溯时间,提高研发效能。用好持续集成,提高研发效能持续集成可以帮助你的企业:最及时的发现问题:持续集成的及时反馈机制能帮助工程师在第一时间发现问题并修复。解放了重复性劳动:自动化的流程可以解放集成、测试、部署等重复性劳动,提高研发效能。更高的产品质量:集成服务器往往提供代码质量检测等功能,对不规范或有错误的地方会进行标记,提高产品质量。CODING 持续集成新功能上线对 Docker 的支持CODING 持续集成现支持 CVM 模式下对 Docker 镜像的支持,免去安装、配置烦恼,让部署更加方便。支持通过 Dockerfile 创建自定义镜像,同时可以使用 hub.docker.com 上的镜像资源。支持持久化缓存,加速构建速度。持久化缓存进行持续集成构建过程中,每次会用大量的时间重复下载依赖文件,致使构建过程时间过长。CODING 持续集成在 CVM 模式下支持持久化缓存的功能,开启后,首次构建时会下载所需依赖文件,并存储到缓存区,后续的构建将使用缓存中的依赖文件,大幅降低构建的时间。多任务并行CODING 持续集成现已实现以不同服务器并行构建过程,降低等待时间。同时支持针对不同的分支进行独立构建。镜像优化为了帮助构建更快,maven、gradle、npm、python、ruby 默认使用了腾讯云的源(https://mirrors.cloud.tencent…)。php 目前支持了其他国内的源(https://packagist.phpcomposer…)。CODING 持续集成的优势一站式服务:CODING 持续集成是 CODING 研发管理系统的一部分,统一的账号体系能帮助开发者在单一平台完成从设计到部署的全流程,免去在工具间切换带来的效能浪费。完美兼容 Jenkins :CODING 持续集成完美兼容 Jenkinsfile 配置。简单容易上手:提供完整的帮助文档和示例,帮助您快速上手。无缝协作:在 CODING 研发管理系统中,持续集成的触发和结果都可以直接在其他模块中调用,方便任务的分配和验收。完整的构建报告:每次构建都会自动生成完整的报告。极速反馈:支持复数构建并行集成测试,能在最短的时间内反馈结果。点击立即体验 CODING 企业版一站式提供需求管理、代码管理、持续集成、开发环境管理、测试管理、缺陷管理等功能适用于传统模式和敏捷模式的软件研发项目和产品运营助力企业实现 DevOps!

March 26, 2019 · 1 min · jiezi

持续集成之 Spring Boot 实战篇

本文作者: CODING 用户 - 何健这次实战篇,我们借助「CODING 持续集成」,实现一个简单的 Spring Boot 项目从编码到最后部署的完整过程。本教程还有 B 站视频版,帮助读者更好地学习理解。思路在线上环境构建、测试、部署这种情况,通常会将 jenkins 安装在服务器上,确保构建测试等操作环境和线上环境一致。此时通常会在 jenkins 中配置好需要持续集成的仓库,以及具体流程。这种方式非常简单粗暴,也非常有效,但是缺点也很明显。可能 jenkins 会成为线上环境的旁站漏洞,这是非常不安全的。那么,我们就需要更高级的方式,可以线上环境之外的构建测试,最终部署到线上环境。「CODING 持续集成」正是提供这类持续集成模式的平台。不在实际部署服务器上构建、测试为了避免占用线上服务器的资源,也为了避免安全问题,我们可以使用单独的 jenkins (或者其它此类软件)完成构建、测试、分发,实际部署通过单独的 webhook 实现。这样就可以避免在线上环境安装 Jenkins,还可以避免更复杂的系统安全维护。这样做的优点:不会影响在线服务;缺点:部署地机器最好是可以公网访问的,否则会无法完成后续分发步骤。终极解决方案:使用 SaaS 化的 JenkinsSoftware as a Service,软件即服务。「CODING 持续集成」集成了 SaaS 化的 Jenkins 等主流企业开发流程工具,实现了 DevOps 流程全自动化。开箱即用,直接用它就好!捋一下思路我们这次实战针对后一种思路检出代码构建测试分发触发部署实战实际体验,还是很不错的。视频地址:CODING 持续集成 - Spring Boot 项目第一步:初始化一个持续集成1、首先,我们需要进入准备持续集成的项目。这里我用 start.spring.io 初始化一个 demo 示例项目,并推送到仓库。为了方便大家,亲自体验,我准备了一个现成的仓库,可以直接 git clone 下来再 git push 到自己账户下使用。仓库地址:demoForCI2、解压 demo 项目,进入 demo 目录,初始化仓库。 cd g:\demo\ git init git set remote giturl git add ./ git commit -m ‘init repo’ git push -u origin master别忘了 git config user.name yourname 和 git config user.email youremail3、开始体验仓库准备好后,就可以开始体验「CODING 持续集成」。第一次的使用,需要先创建一个 Jenkinsfile,很多小伙伴会说,第一次用,不知道是啥。没关系,「CODING 持续集成」已经给我们准备好了模板,非常容易理解,可以认为是特定格式语法写一套 task 流程。点击一下 “简易模板”,更具实际情况修改一下就可以。第二步:编写 Jenkinsfile为了方便理解,我们从简易模板开始,分别修改对应阶段的任务。1、配置构建环境,「CODING 持续集成」目前支持 java-8、python-3.5、ruby-2.3、go-1.11 等等。在 Jenkinsfile 的 pipeline 里添加: agent { // 此处设定构建环境,目前可选有 // default, java-8, python-3.5, ruby-2.3, go-1.11 等 // 详情请阅 https://dev.tencent.com/help/knowledge-base/how-to-use-ci#agents label “java-8” }2、检出这里不得不说,「CODING 持续集成」这里做的还是很方便的,提供了适用于好几种不同场景的模板。默认简易模板是带有检出部分的,我们可以根据实际情况进行修改。默认情况下,env.GIT_BUILD_REF 的值就是 master 主分支,实际上我们可以定制为其它专门用于构建发的分支。这里,大家可以自己修改具体要检出的分支。 stage(“检出”) { steps { sh ‘ci-init’ checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } }3、构建 stage(“构建”) { steps { echo “构建中…” sh ‘java -version’ sh ‘mvn package’ echo “构建完成.” archiveArtifacts artifacts: ‘/target/.jar’, fingerprint: true // 收集构建产物 } }这里需要注意,Spring Boot 的 pom 中需要添加一个插件。修改后: <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!– 下面是添加的插件 –> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.6</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin>4、测试这里我偷个懒,只做了单元测试,没有提取测试报告,大家可以根据实际项目定制这个流程。 stage(“测试”) { steps { echo “单元测试中…” sh ‘mvn test’ echo “单元测试完成.” //junit ’target/surefire-reports/.xml’ // 收集单元测试报告的调用过程 } }5、分发 jar 包到目标服务器这里比较无奈,我没有单独针对这次演示写部署 jar 包和上传 jar 包的 webhookApi,但是构建好的 jar 包需要要放置到待部署的服务器。于是有了这个过程,借助 scp 和私钥来上传构建好的jar包。这里千万记着提前部署好密钥。并且将密钥放到仓库一份,用于分发jar包。 stage(“分发jar包”) { steps { echo “分发中…” echo “chmod 600 pkey” sh ‘chmod 600 authorized_keys.pem’ echo “upload” sh ‘scp -i authorized_keys.pem ./target/*.jar root@yourip:/root/’ echo “准备部署” } }6、部署前面有提到,这里部署仍然需要触发一个钩子,否则只能手动部署了。这里我写了一个最简单的,实际上我们可以写细致一点,判断一下接口返回的结果再根据结果输出部署情况。 stage(“部署”) { steps { sh ‘curl http://youapi’ echo “部署完毕” } }第三步:保存 Jenkinsfile 并运行修改好 Jenkinsfile 和 pom.xml。我们要保存 Jenkinsfile,编辑框可以直接编辑内容,编辑好可以直接提交到仓库下的 ./Jenkinsfile 接下来, 平台会自动读取 Jenkinsfile 并开始走持续集成的流程:持续集成的流程是可以看到的:每个阶段都对应 Jenkinsfile 一个 stage, 我们可以点击查看对应阶段的构建结果。第四步:排查持续集成的报错如果某个过程出错,「CODING 持续集成」的流程会停止,并提示失败。此时我们可以进入具体节点查看具体失败原因。比如现在是提示“分发 jar 包失败”,那么我们可以点击对应节点展开看看日志,排查具体分发失败的原因。现在可以清晰地看到,报错原因是我没有填写正确的主机 ip。文中涉及的文件及代码Jenkinsfilepipeline { agent { // 此处设定构建环境,目前可选有 // default, java-8, python-3.5, ruby-2.3, go-1.11 等 // 详情请阅 https://dev.tencent.com/help/knowledge-base/how-to-use-ci#agents label “java-8” } stages { // 检出仓库 stage(“检出”) { steps { // 这里sh调用ci-init 初始化 sh ‘ci-init’ // 这里检出仓库,默认检出分支为环境变量中的GIT_BUILD_REF checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } } // 构建jar包 stage(“构建”) { steps { echo “构建中…” // 输出java版本 sh ‘java -version’ // 调用maven 构建jar包 sh ‘mvn package’ echo “构建完成.” //收集构建产物,这一步成功,我们就可以在平台上看到构建产物 archiveArtifacts artifacts: ‘/target/.jar’, fingerprint: true // 收集构建产物 } } // 测试 stage(“测试”) { steps { echo “单元测试中…” // 做单元测试 sh ‘mvn test’ echo “单元测试完成.” } } // 分发jar包,这里只是简单的通过scp分发jar包到目标机器指定目录 stage(“分发jar包”) { steps { echo “分发中…” echo “chmod 600 pkey” sh ‘chmod 600 authorized_keys.pem’ echo “upload” sh ‘scp -i authorized_keys.pem ./target/.jar root@youip:/root/’ echo “准备部署” } } // 部署jar包 stage(“部署”) { // 这里需要触发一个部署的webhook,可以是一个很简单的重启java进程的操作 steps { // 用curl 来触发hook sh ‘curl http://baidu.com’ echo “请登录服务器手动部署” } } }}pom.xml文中所用 Spring Boot 示例项目的 pom.xml实际上,大家可以直接去 start.spring.io 参考照这份 pom 来创建一个 demo。<?xml version=“1.0” encoding=“UTF-8”?><project xmlns=“http://maven.apache.org/POM/4.0.0" xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> <relativePath/> <!– lookup parent from repository –> </parent> <groupId>tech.hejian</groupId> <artifactId>codingj8</artifactId> <version>0.0.1-SNAPSHOT</version> <name>codingj8</name> <description>coding project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.6</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build></project>总结CODING 是一个面向开发者的云端开发平台,提供 Git/SVN 代码托管、任务管理、在线 WebIDE、Cloud Studio、开发协作、文件管理、Wiki 管理、提供个人服务及企业服务,其中「CODING 持续集成」集成了 SaaS 化的 Jenkins 等主流企业开发流程工具,实现了 DevOps 流程全自动化,为企业提供软件研发全流程管理工具,打通了从团队构建、产品策划、开发测试到部署上线的全过程。 ...

March 13, 2019 · 3 min · jiezi

能用机器完成的,千万别堆工作量|持续集成中的性能自动化测试

1.背景当前闲鱼在精益开发模式下,整个技术团队面临了诸多的能力落地和挑战,尤其是效能方面的2-1-1的目标(2周需求交付周期,1周需求开发周期,1小时达到发布标准),具体可见 闲鱼工程师是如何构建持续集成流水线,让研发效率翻倍的 ,在这个大目标下,就必须把每个环节都做到极致。自动化的建设是决定CI成败的关键能力,今天分享一下闲鱼Android客户端性能自动化环节的实践。2.面临的问题2.1 主要是两个方面的问题工具缺失:目前淘宝系,对于线上性能水位的监控有一套完善的体系,但是针对新功能的性能测试,每个业务团队都有对应的性能专项小组,产出的工具都是根据自己业务特点的定制开发的,闲鱼客户端目前使用Flutter做为客户端主开发语言,对于Flutter性能数据的获取及UI自动化测试支撑工具目前是缺失的,同时业界对Flutter自动化和性能相关的实践几乎没有;测试工作量翻N倍(N=一个版本周期内的分支数):原先的开发模式是功能测试集成测试一起进行的,所以性能测试只需要针对集成后的包进行测试即可,到现在转变为泳道的开发模式,一个版本内会一般包含十几个左右的泳道分支甚至更多,我们必须确保每个泳道的分支的性能是达标的,如果有性能问题需要第一时间反馈出来,如果遗留到集成阶段,问题的排查(十几个分支中筛查),问题的解决将会耗费大量的时间,效率很难得到大的提升;2.2 问题思考体系化解决,要让每个泳道分支都得到有效测试覆盖,测试件能够自动化执行,持续反馈结果3. 解决方案综合上述问题,梳理如下解决方案:针对Flutter性能数据的获取(比如,Flutter有自己的SurfaceView,原有Native计算FPS的方式无法直接使用)针对Flutter UI自动化的实现(Flutter/Native UI混合栈的处理)性能自动化脚本 / 性能数据自动采集、上报 融入CI流程性能问题的通知 / 报表展示 / 分析3.1 性能数据[FPS]解析处理 adb shell dumpsys SurfaceFlinger –latency 的数据,详细请见文末参考链接(该方式兼容Flutter及Native的解决方案,已在Android4.x-9.x验证可行),处理SurfaceFlinger核心代码如下:dumpsys SurfaceFlinger –latency-clear#echo “dumpsys SurfaceFlinger…“if [[ $isflutter = 0 ]];then window=dumpsys window windows | grep mCurrent | $bb awk '{print $3}'|$bb tr -d '}' # Get the current window echo $windowfiif [[ $isflutter = 1 ]];then window=dumpsys SurfaceFlinger --list |grep '^SurfaceView'|$bb awk 'NR==1{print $0}'if [ -z “$window” ]; then window=“SurfaceView"fiecho $windowfi$bb usleep $sleep_tdumpsys SurfaceFlinger –latency “$window”|$bb awk -v time=$uptime -v target=$target -v kpi=$KPI ‘{if(NR==1){r=$1/1000000;if(r<0)r=$1/1000;b=0;n=0;w=1}else{if(n>0&&$0==”")O=1;if(NF==3&&$2!=0&&$2!=9223372036854775807){x=($3-$1)/1000000/r;if(b==0){b=$2;n=1;d=0;D=0;if(x<=1)C=r;if(x>1){d+=1;C=int(x)r;if(x%1>0)C+=r};if(x>2)D+=1;m=r;o=0}else{c=($2-b)/1000000;if(c>1000){O=1}else{n+=1;if(c>=r){C+=c;if(c>kpi)o+=1;if(c>=m)m=c;if(x>1)d+=1;if(x>2)D+=1;b=$2}else{C+=r;b=sprintf(”%.0f”,b+r1000000)}}};if(n==1)s=sprintf("%.3f",$2/1000000000)};if(n>0&&O==1){O=0;if(n==1)t=sprintf("%.3f",s+C/1000);else t=sprintf("%.3f",b/1000000000);T=strftime("%F %T",time+t)".“sprintf(”%.0f",(time+t)%11000);f=sprintf("%.2f",n1000/C);m=sprintf("%.0f",m);g=f/target;if(g>1)g=1;h=kpi/m;if(h>1)h=1;e=sprintf("%.2f",g60+h20+(1-o/n)*20);print s",“t”,“T”,“f+0”,“n”,“d”,“D”,“m”,“o”,“e”,“w;n=0;if($0==”"){b=0;w+=1}else{b=$2;n=1;d=0;D=0;if(x<=1)C=r;if(x>1){d+=1;C=int(x)*r;if(x%1>0)C+=r};if(x>2)D+=1;m=r;o=0}}}}’ >>$file[CPU]使用的是top的命令获取(该方式获取性能数据时,数据收集带来的损耗最少)export bb="/data/local/tmp/busybox"$bb top -b -n 1|$bb awk ‘NR==4{print NF-1}’[内存]解析 dumpsys meminfo $package 拿到 Java Heap,Java Heap Average,Java Heap Peak,Native Heap,Native Heap Average,Native Heap Peak,Graphics,Unknown,Pss 数据do_statistics() { ((COUNT+=1)) isExist="$(echo $OUTPUT | grep “Dalvik Heap”)" if [[ ! -n $isExist ]] ; then old_dumpsys=true else old_dumpsys=false fi if [[ $old_dumpsys = true ]] ; then java_heap="$(echo “$OUTPUT” | grep “Dalvik” | $bb awk ‘{print $6}’ | $bb tr -d ‘\r’)" else java_heap="$(echo “$OUTPUT” | grep “Dalvik Heap[^:]” | $bb awk ‘{print $8}’ | $bb tr -d ‘\r’)" fi echo “1."$JAVA_HEAP_TOTAL “2."$java_heap “3."$JAVA_HEAP_TOTAL ((JAVA_HEAP_TOTAL+=java_heap)) ((JAVA_HEAP_AVG=JAVA_HEAP_TOTAL/COUNT)) if [[ $java_heap -gt $JAVA_HEAP_PEAK ]] ; then JAVA_HEAP_PEAK=$java_heap fi if [[ $old_dumpsys = true ]] ; then native_heap="$(echo “$OUTPUT” | grep “Native” | $bb awk ‘{print $6}’ | $bb tr -d ‘\r’)” else native_heap="$(echo “$OUTPUT” | grep “Native Heap[^:]” | $bb awk ‘{print $8}’ | $bb tr -d ‘\r’ | $bb tr -d ‘\n’)” fi ((NATIVE_HEAP_TOTAL+=native_heap)) ((NATIVE_HEAP_AVG=NATIVE_HEAP_TOTAL/COUNT)) if [[ $native_heap -gt $NATIVE_HEAP_PEAK ]] ; then NATIVE_HEAP_PEAK=$native_heap fi g_Str=“Graphics” if [[ $OUTPUT == $g_Str ]] ; then echo “Found Graphics…” Graphics="$(echo “$OUTPUT” | grep “Graphics” | $bb awk ‘{print $2}’ | $bb tr -d ‘\r’)” else echo “Not Found Graphics…” Graphics=0 fi Unknown="$(echo “$OUTPUT” | grep “Unknown” | $bb awk ‘{print $2}’ | $bb tr -d ‘\r’)" total="$(echo “$OUTPUT” | grep “TOTAL”|$bb head -1| $bb awk ‘{print $2}’ | $bb tr -d ‘\r’)"}[流量]通过 dumpsys package packages 解析出当前待测试包来获取流量信息uid="$(dumpsys package packages|$bb grep -E “Package |userId”|$bb awk -v OFS=" " ‘{if($1==“Package”){P=substr($2,2,length($2)-2)}else{if(substr($1,1,6)==“userId”)print P,substr($1,8,length($1)-7)}}’|grep $package|$bb awk ‘{print $2}’)“echo “Net:"$uidinitreceive=$bb awk -v OFS=" " 'NR&gt;1{if($2=="wlan0"){wr[$4]+=$6;wt[$4]+=$8}else{if($2=="rmnet0"){rr[$4]+=$6;rt[$4]+=$8}}}END{for(i in wr){print i,wr[i]/1000,wt[i]/1000,"wifi"};for(i in rr){print i,rr[i]/1000,rt[i]/1000,"data"}}' /proc/net/xt_qtaguid/stats | grep $uid|$bb awk '{print $2}'inittransmit=$bb awk -v OFS=" " 'NR&gt;1{if($2=="wlan0"){wr[$4]+=$6;wt[$4]+=$8}else{if($2=="rmnet0"){rr[$4]+=$6;rt[$4]+=$8}}}END{for(i in wr){print i,wr[i]/1000,wt[i]/1000,"wifi"};for(i in rr){print i,rr[i]/1000,rt[i]/1000,"data"}}' /proc/net/xt_qtaguid/stats | grep $uid|$bb awk '{print $3}'echo “initnetarray”$initreceive”,"$inittransmitgetnet(){ local data_t=date +%Y/%m/%d" "%H:%M:%S netdetail=$bb awk -v OFS=, -v initreceive=$initreceive -v inittransmit=$inittransmit -v datat="$data_t" 'NR&gt;1{if($2=="wlan0"){wr[$4]+=$6;wt[$4]+=$8}else{if($2=="rmnet0"){rr[$4]+=$6;rt[$4]+=$8}}}END{for(i in wr){print datat,i,wr[i]/1000-initreceive,wt[i]/1000-inittransmit,"wifi"};for(i in rr){print datat,i,rr[i]/1000-initreceive,rt[i]/1000-inittransmit,"data"}}' /proc/net/xt_qtaguid/stats | grep $uid echo $netdetail>>$filenet}3.2 性能自动化脚本基于Appium的自动化用例,这个技术业界已经有非常多的实践了,这里我不再累述,如果不了解的同学,可以到Appium官网 http://appium.ioFlutter和Native页面切换使用App内的Schema跳转Flutter页面的文本输入等交互性较强的场景使用基于Flutter框架带的Integration Test来操作An integration testGenerally, an integration test runs on a real device or an OS emulator, such as iOS Simulator or Android Emulator. The app under test is typically isolated from the test driver code to avoid skewing the results.Flutter的UI自动化及Flutter/Native混合页面的处理在测试上的应用后续单独开文章介绍,原理相关可以先参考 千人千面录制回放技术3.3 性能自动化CI流程3.4 性能数据报表FPS相关Framediff: 绘制帧的开始时间和结束时间差FPS: 每秒展示的帧数Frames: 一个刷新周期内所有的帧jank: 一帧开始绘制到结束超过16.67ms 就记一次jank,jank非零代表硬件绘制掉帧,和屏幕硬件性能及相关驱 动性能有关jank2: 一帧开始绘制到结束超过33.34ms 就记一次jank2MFS: 在一个刷新周期内单帧最大耗时(每两行垂直同步的时间差代表两帧绘制的帧间隔)OKT: 在一个刷新周期内,帧耗时超过16.67ms的次数SS: 流畅度,通过FPS,MFS,OKT计算出来,流畅度 = 实际帧率比目标帧率比值60【目标帧率越高越好】 + 目标时间和两帧时间差比值20【两帧时间差越低越好】 + (1-超过16ms次数/帧数)*20【次数越少越好】CPUMemory4. 成果展示4.1 指定泳道分支性能监控泳道分支出现了性能问题再报表上一目了然4.2 性能专项支撑1、Flutter商品详情页重构 14轮测试2、客户端图片统一资源测试 4轮测试5. 总结性能自动化只是整个CI流程中的一个环节,为了极致效率的大目标,闲鱼质量团队还产出了很多支撑工具,CI平台,遍历测试,AI错误识别,用例自动生成等等,后续也会分享给大家。6. 参考https://testerhome.com/topics/2232https://testerhome.com/topics/4775本文作者:闲鱼技术-灯阳阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 22, 2019 · 3 min · jiezi

持续集成之理论篇

本文作者:CODING 用户 - 何健持续集成 ?——?大概数周前,突然有学长问我有没有接触过“持续集成”。在我脑海中,这是一个陌生的词汇,于是百度了解了一番。实际上有开发和部署经验的小伙伴对持续集成不会非常陌生的,特别是那些喜欢自己写 webhook 的小伙伴。这篇文章来聊聊持续集成。互联网软件从开发到上线,后续迭代更新,已经有一套近乎标准的流程。其中 持续集成(Continuous integration,简称 CI)则是核心流程。像「CODING 持续集成」也直接支持自定义配置流程。概念大师 Martin Fowler 对持续集成是这样定义的:持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。简单说,持续集成就是指频繁自动将代码集成到主干和生产环境,比如「CODING 持续集成」所实现的功能。目的持续集成的目的,快速迭代,保持高质量,避免不必要的成本投入。优点快速定位错误,测试环节可以及时暴露问题;避免大幅度偏离主干,借助统一的代码库;减少不必要的成本投入,可以自动化解决的重复乏味的事情,没必要浪费人力和时间;实际上还有很多有点,大家慢慢感受啦~一般步骤持续集成的核心措施, 集成到主干前, 自动化测试, 只有通过,才可以集成到主干。成功集成到主干后,也意味着可以部署上线。这便牵扯出另外两个相关概念,持续交付、持续部署。这里一起看一下集成的一般步骤:设计开发测试发布每次集成都是这样的步骤,因此持续集成会时这些基本步骤合体的循环,只要项目还在迭代,我们就会不停重复这个步骤。持续交付 (Continuous delivery)这里借用阮一峰老师的说法:持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。注意,持续交付在自动化测试和集成结束后,不一定会自动部署。如果有自动部署,则是持续部署的概念了。持续部署 (continuous deployment)持续部署(continuous deployment)则是持续交付的下一步,代码通过评审,自动化部署到生产环境。其目的时可以随时部署,迅速投入生产阶段。持续部署这一步,意味着产品和观众见面,但是要通过重重考验,测试、构建、部署等步骤,而且每一步都是自动的。流程通常如下几步:1. 提交就是常见的代码提交到 CODING 仓库2. 单元测试这个过程 通常是一个针对 commit 操作的钩子,只要由提交,就会跑自动化测试,测试通过才可以推代码到主干。(这轮测试至少要有单元测试)常见测试:单元测试:针对函数或模块的测试集成测试:针对整体产品的某个功能的测试,也叫功能测试端对端测试:从用户界面直达数据库的全链路测试3. 构建第一轮测试通过,代码可以成功合并到主干,交付。那么接下来,就要构建(build),进入第二轮测试。但是,构建并不是绝对必须的过程,构建就是为了让源码变成可以运行的程序或代码。如果是 java、golang 项目,通常要 build 后才可以运行。但如果是 php、python,可能并没有构建过程,只要更新代码到对应的 cgi 容器的工程目录就可以了。构建过程,我们可以自己写一些脚本和接口,挂到对应的钩子里。当然,也可以用一些成熟的构建工具:jenkins (开源免费)Traviscodeship (开源免费)Strider「CODING 持续集成」4. 全面测试这轮测试 ,应该是一次全面测试,除了前面提到的自动化测试,还应该包含一些无法自动化测试的部分。如果第一轮测试已经很全面(意味着前一步和第一轮测试合并了,不构建,自然无法全面测试),那么这轮测试可以作为第一轮测试的补集存在。这里需要注意的是,测试的覆盖率。每次版本更新,更新点都应测试到位。要素统一的代码库自动构建自动测试每个人每天都要向代码库主干提交代码每次代码递交后都会在持续集成服务器上触发一次构建保证快速构建模拟生产环境的自动测试每个人都可以很容易的获取最新可执行的应用程序每个人都清楚正在发生的状况自动化的部署原则所有的开发人员需要在本地机器上做本地构建,然后再提交的版本控制库中,从而确保他们的变更不会导致持续集成失败。开发人员每天至少向版本控制库中提交一次代码。开发人员每天至少需要从版本控制库中更新一次代码到本地机器。需要有专门的集成服务器来执行集成构建,每天要执行多次构建。每次构建都要 100% 通过。每次构建都可以生成可发布的产品。修复失败的构建是优先级最高的事情。测试是未来,未来是测试小结从开发到上线,整体流程:持续集成——>持续交付——>持续部署可以用「CODING 持续集成」进行实践。Jenkins 和持续集成什么关系Jenkins 是一个开源软件项目,是基于 Java 开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。没错,它就是一个具体的持续集成解决方案。基于 Java 实现。可以实现:持续版本发布/测试;监控外部调用执行的工作;持续集成和 webhook 什么关系说到这里,一些有 php 开发经验的小伙伴很容易联想到写 webhook。没错,php 程序通常由 Http Server(比如 apache2、nginx 等)通过反响代理 fpm-cgi 或者直接内置 cgi 来执行 php 程序。这个过程更像是直接请求了 html 文档。说这里是因为,一些 php 写手为了方便更新线上代码,并不想每次都手动 scp 命令上传新的代码,特别时有时候有些代码可能是有问题的。这时候,大家都想到用版本管理,git 就是很好的选择,其中 github 和 CODING 都是不错的选择。我们的话题是持续集成,为什么会突然扯到 php 和 git 呢?那是因为,github 和 CODING 很早就都支持了 webhook 功能。换句话说,我们可以通过开放一个特别的接口,这个接口就一个功能,执行一系列操作,每当接口被调用时,接口可以执行我们预设好的一系列任务指令。这样,我们每次写好代码,只要 push 到仓库,触发 webhook,github 等平台就会去请求我们开放的接口,用来执行更新代码和重启服务等操作。简单说,我们给服务器上留了一个“小工”,指派给他一个接头人,接到信号就做预先安排好的事儿。这个过程,是不是很像持续部署最后自动部署的阶段?没错,就是这样,这个过程很可能时没有自动测试环节,直接自动交付,自动部署。当然,如果 webhook 写复杂点,完全可以配合一些脚本命令做自己的一套 CICD。总结CODING 是一个面向开发者的云端开发平台,提供 Git/SVN 代码托管、任务管理、在线 WebIDE、Cloud Studio、开发协作、文件管理、Wiki 管理、提供个人服务及企业服务,其中实现了 DevOps 流程全自动化,为企业提供软件研发全流程管理工具,打通了从团队构建、产品策划、开发测试到部署上线的全过程。「CODING 持续集成」集成了 Jenkins 等主流企业开发流程工具。 ...

February 20, 2019 · 1 min · jiezi

基于 CODING 的 Spring Boot 持续集成项目

本文作者:CODING 用户 - 廖石荣持续集成的概念持续集成(Continuous integration,简称 CI)是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。持续集成的模式如图所示:CI 过程:代码编写 -> 源代码库(GitHub or gitlab)-> CI 服务器(代码构建、自动化测试、结果反馈【构建结果】)涉及 CI 工具:Jenkins、Travis CI、TeamCity、Gitlab CI、CircleCI、Codeship 等,相关资料可以查询对应的官网,其中应用广泛的 Jenkins 和 Travis CI,市场上也推出了智能化的持续集成服务商,比如「CODING 持续集成」,它是基于 Jenkins 配置集成服务,真正实现了一键提交代码,持续集成,部署服务。持续集成的优点1.解放了重复性劳动。自动化部署工作可以解放集成、测试、部署等重复性劳动,而机器集成的频率明显比手工高很多。2.更快地修复问题。持续集成更早的获取变更,更早的进入测试,更早的发现问题,解决问题的成本显著下降。3.更快的交付成果。更早发现错误减少解决错误所需的工作量。集成服务器在构建环节发现错误可以及时通知开发人员修复。集成服务器在部署环节发现错误可以回退到上一版本,服务器始终有一个可用的版本。4.减少手工的错误。在重复性动作上,人容易犯错,而机器犯错的几率几乎为零。5.减少了等待时间。缩短了从开发、集成、测试、部署各个环节的时间,从而也就缩短了中间可以出现的等待时机。持续集成,意味着开发、集成、测试、部署也得以持续。6.更高的产品质量。集成服务器往往提供代码质量检测等功能,对不规范或有错误的地方会进行标致,也可以设置邮件和短信等进行警告。持续集成服务的选择关于网上集成服务的工具很多,其中尤其以 Jenkins 服务最受欢迎,但是 Jenkins 服务需要在自己服务器上进行配置安装,以及安装各种插件,对于刚上手的小白来说,可能存在一定的门槛,操作步骤繁多,操作不够智能,不是真正的自动化运维,缺少一键发布构建服务。所以我们选择了「CODING 持续集成」。CODING 提供的集成服务是什么「CODING 持续集成」是基于 Jenkins 的,兼容 Jenkinsfile 配置文件,如果您之前有使用过或者写过 Jenkinsfile 相信您会很快上手。如何使用CODING持续集成服务「CODING 持续集成」是基于 Jenkins 的,通过 Jenkinsfile 配置文件完成 CI 的步骤,接下来将引导您一步步创建一个持续集成示例。登录 CODING,进入项目中心,点击左边菜单集成服务,开通集成服务,配置完成之后会手动触发第一次构建过程。找到或者创建 Jenkinsfile,如果你对于 Jenkins 比较熟悉的话,可以自己编写 Jenkinsfile 配置文件,也可以采用 CODING 提供的模板文件,如下我就采用了 Jenkinsfile 模板文件来实行自动化持续集成服务,您可以在修改 Jenkinsfile 的时候修改触发方式,您可以自行选择是推送到某个标签或者某个分支时间触发构建。Jenkins 以及能够为 agent 默认配置好 timezone 和 localtime (默认中国上海)。配置好 Jenkinsfile 文件以及配置好环境变量,点击保存,便可以进行持续集成项目了。如图所示,集成步骤分为拉取代码-》构建-》测试-》部署等步骤,点击每个步骤可以看到相应的命令执行情况,下面来一个一个步骤配合 Jenkinsfile 文件解释命令的一些执行情况:代码工程结构如图所示:1.检出项目,如下所示 Jenkinsfile 配置文件第一步通过 Git 检出在远程仓库分支的代码,至于哪个分支可以通过环境变量配置读取 REF 这个环境变量stage(“检出”) { steps { sh ‘ci-init’ checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } }如上图所示,第一步主要是执行从 Git 仓库远程拉取代码,所以命令都是 Git 里面的,包括读取 Git 配置的环境变量包括更新 Jenkinsfile 文件2.构建项目,如下命令所示构建这一步主要是初始化代码和打包代码,因为我们这个工程是以 Java 为主要开发语言,所以重点关注 Java 版本和安装 Maven 命令即可打包,目前 CODING 提供的语言环境包括了 java-1.8.0_181, go-1.7.4, node-10.11.0, php-7.0.30, ruby-2.3, python-2.7.13 等。如有需要可以联系客服开通其它语言环境。stage(“构建”) { steps { echo “构建中…” sh ‘go version’ sh ’node -v’ sh ‘java -version’ // sh ‘php -v’ // sh ‘python -V’ // sh ‘gcc -v’ // sh ‘make -v’ // 请在这里放置您项目代码的单元测试调用过程,例如: sh ‘mvn clean’ // mvn 清除缓存 sh ‘mvn install’ // 构建 Maven 工程 // sh ‘make’ // make 示例 echo “构建完成.” // archiveArtifacts artifacts: ‘**/target/.jar’, fingerprint: true // 收集构建产物 } }因为这个 SpringBoot 项目是以 Java 为主的项目,所以在 Jenkinsfile 文件命令里面其实可以把其它语言的检查版本命令去掉,只需要执行 java -version 命令即可。第一次构建失败:如上图所示,第一次执行执行构建 jar 包失败,因为在本地可以正常 mvn install,所以起初我百思不得其解,上网找了很多资料,经过多番查找,最后在 Stack Overflow 找到了答案,这是由于 OpenJDK 1.8.0_181 这个版本中存在的一个 bug 所致,原文如下:链接,最终解决方案采用更改 pom.xml 文件:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <useSystemClassLoader>false</useSystemClassLoader> <skipTests>true</skipTests> </configuration></plugin>成功构建结果如下:3.测试项目,如下所示,我们 SpringBoot 工程通过 mvn test 测试命令即可,比如下面我们测试其中一个用户信息相关的单元测试:stage(“测试”) { steps { echo “单元测试中…” // 请在这里放置您项目代码的单元测试调用过程,例如: sh ‘mvn test -Dtest=com.my.segmentfault.website.Pwdtest’ //测试其中一个单元测试 echo “单元测试完成.” } }第一次失败测试结果如下:后来经检查,是单元测试代码其中存在 bug,修正之后,正确的第二次测试结果如下:4.部署项目,如下所示,部署项目命令可以执行自己写的部署脚本文件。各位可以结合自己项目的真实环境,编写简单的部署脚本,比如上传 jar 包到服务器,然后通过 java - jar XXXX.jar 包执行方式,以及上传 war 包到 tomcat 服务器,然后启动 tomcat 服务器等,也可以结合自己公司项目需要编写复杂的执行脚本文件,然后调用执行脚本命令,比如下面举一个简单的执行脚本例子。部署命令:stage(“部署”) { steps { echo “部署中…” sh ‘./deploy.sh start’ // 启动 tomcat 服务 // sh ‘./deploy.sh stop’ // 停止 tomcat 服务 echo “部署完成” } }deploy.sh 脚本:(其中一些 tomcat 服务路径配置根据自己需要进行修改)#!/bin/bash tomcat_home=/usr/tomcat/apache-tomcat-8.0.48 //修改为自己服务器的 tomcat 路径SHUTDOWN=$tomcat_home/bin/shutdown.sh STARTTOMCAT=$tomcat_home/bin/startup.sh case $1 instart) echo “启动$tomcat_home”$STARTTOMCAT ;; stop) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist #!/bin/bash tomcat_home=/usr/tomcat/apache-tomcat-8.0.48 SHUTDOWN=$tomcat_home/bin/shutdown.sh STARTTOMCAT=$tomcat_home/bin/startup.sh case $1 instart) echo “启动$tomcat_home”$STARTTOMCAT ;; stop) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist stop) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist #删除日志文件,如果你不先删除可以不要下面一行 rm $tomcat_home/logs/ -rf #删除tomcat的临时目录 rm $tomcat_home/work/* -rf ;; restart) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist #删除日志文件,如果你不先删除可以不要下面一行 rm $tomcat_home/logs/* -rf #删除tomcat的临时目录 rm $tomcat_home/work/* -rf sleep 5 echo “启动$tomcat_home”$STARTTOMCAT #看启动日志 #tail -f $tomcat_home/logs/catalina.out ;; logs) cd /mnt/alidata/apache-tomcat-7.0.68/logstail -f catalina.out ;; esac 服务启动展示系统主页如下图所示:文章详情如下图所示:归档页面如下图所示:系统后台管理如图所示:总结CODING 是一个面向开发者的云端开发平台,提供 Git/SVN 代码托管、任务管理、在线 WebIDE、Cloud Studio、开发协作、文件管理、Wiki 管理、提供个人服务及企业服务,其中实现了 DevOps 流程全自动化,为企业提供软件研发全流程管理工具,打通了从团队构建、产品策划、开发测试到部署上线的全过程。「CODING 持续集成」集成了 Jenkins 等主流企业开发流程工具,如上所示,这个以 SpringBoot 打造的 CMS 社区系统便可以在 CODING 上面实现团队协作开发,一键部署作为团队以及公司文档共享社区论坛等作用。本文适量引用:“持续集成”词条的百度百科 ...

February 20, 2019 · 2 min · jiezi

使用 CODING 进行 Hexo 项目的持续集成

本文作者:CODING 用户 - 廖石荣关于持续集成的概念持续集成指的是,频繁地(一天多次)将代码集成到主干。持续集成的过程如图所示:CI 过程:代码编写 -> 源代码库(GitHub or gitlab)-> CI 服务器(代码构建、自动化测试、结果反馈【构建结果】)涉及 CI 工具:Jenkins、Travis CI、TeamCity、Gitlab CI、CircleCI、Codeship 等,相关资料可以查询对应的官网,其中应用广泛的 Jenkins 和 Travis CI,Gitlab CI 是开源的 Rails 项目 GitLab 的一个组成部分,GitLab CI 能与 GitLab 完全集成,可以通过使用 GitLab API 轻松地作为项目的钩子。关于持续集成的优点快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。持续集成服务的选择关于网上集成服务的工具很多,其中尤其以 Jenkins 服务最受欢迎,但是 Jenkins 服务需要在自己服务器上进行配置安装,以及安装各种插件,对于刚上手的小白来说,可能存在一定的门槛,操作步骤繁多,操作不够智能,不是真正的自动化运维,缺少一键发布构建服务。所以我们选择了「CODING 持续集成」。CODING 提供的集成服务是什么CODING 推出的持续集成服务,「CODING 持续集成」是基于 Jenkins 的,兼容 Jenkinsfile 配置文件,如果您之前有使用过或者写过 Jenkinsfile 相信您会很快上手。如何使用 CODING 持续集成服务「CODING 持续集成」是基于 Jenkins 的,通过 Jenkinsfile 配置文件完成CI的步骤,接下来将引导您一步步创建一个持续集成示例。登录 coding,进入项目中心,点击左边菜单集成服务,开通集成服务,配置完成之后会手动触发第一次构建过程找到或者创建 Jenkinsfile,如果你对于Jenkins 比较熟悉的话,可以自己编写 Jenkinsfile 配置文件,也可以采用CODING 提供的模板文件,如下我就采用了Jenkinsfile 模板文件来实行自动化持续集成服务,您可以在修改 Jenkinsfile 的时候修改触发方式,您可以自行选择是推送到某个标签或者某个分支时间触发构建。jenkins 以及能够为 agent 默认配置好 timezone 和 localtime(默认中国上海)配置好 Jenkinsfile 文件以及配置好环境变量,点击保存,便可以进行持续集成项目了如图所示,集成步骤分为拉取代码-》构建-》测试-》部署等步骤,点击每个步骤可以看到相应的命令执行情况,下面来一个一个步骤配合 Jenkinsfile 文件解释命令的一些执行情况:1.检出项目,如下所示 Jenkinsfile 配置文件第一步通过 Git 检出在远程仓库分支的代码,至于哪个分支可以通过环境变量配置读取 REF 这个环境变量stage(“检出”) { steps { sh ‘ci-init’ checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } }如上图所示,第一步主要是执行从 Git 仓库远程拉取代码,所以命令都是 Git 里面的,包括读取 Git 配置的环境变量包括更新 Jenkinsfile 文件2.构建项目,如下命令所示构建这一步主要是初始化代码和打包代码,因为我们这个工程是以 Node.js 为主要开发语言,所以重点关注 Node.js 版本和 安装 hexo 脚手架命令即可打包,目前Coding 提供的语言环境包括了 java-1.8.0_181, go-1.7.4, node-10.11.0, php-7.0.30, ruby-2.3, python-2.7.13 等。如有需要可以联系客服进行开通其它语言环境。stage(“构建”) { steps { echo “构建中…” sh ‘go version’ sh ’node -v’ sh ‘java -version’ sh ‘php -v’ sh ‘python -V’ sh ‘gcc -v’ sh ‘make -v’ // 请在这里放置您项目代码的单元测试调用过程,例如: // sh ‘mvn package’ // mvn 示例 // sh ‘make’ // make 示例 sh ’npm install -g hexo-cli’ //安装hexo 脚手架 echo “构建完成.” // archiveArtifacts artifacts: ‘**/target/.jar’, fingerprint: true // 收集构建产物 } }因为这个 Hexo 项目是以 Node.js 为主的项目,所以在 Jenkinsfile 文件命令里面其实可以把其它语言的检查版本命令去掉,只需要执行 node - v 命令即可3.测试项目,如下所示,如果是 maven 项目可以通过 mvn 命令执行测试语句,我们 Hexo 这个工程通过 hexo 脚手架构建测试命令即可,如果单元测试不通过则会显示不通过,(hexo 对文件格式存在要求,如果文件格式不符合正规 MarkDown 语法,则会抛出错误)stage(“测试”) { steps { echo “单元测试中…” // 请在这里放置您项目代码的单元测试调用过程,例如: sh ‘hexo clean’ //清除缓存 sh ‘hexo g ’ // 将 md 文件构建为 html 页面示例 echo “单元测试完成.” // junit ’target/surefire-reports/.xml’ // 收集单元测试报告的调用过程 } }*正确构建测试结果如下图:4.部署项目如下所示,部署项目命令可以执行自己写的部署脚本文件,也可以配置好“_config.yml”文件之后直接执行 hexo 脚手架自带的命令。如下图整个代码结构图:配置文件部分截图:部署命令:stage(“部署”) { steps { echo “部署中…” // 请在这里放置收集单元测试报告的调用过程,例如: // sh ‘mvn tomcat7:deploy’ // Maven tomcat7 插件示例: // sh ‘./deploy.sh’ // 自研部署脚本 sh ’npm install hexo-deployer-git –save’ // 安装 deploy 脚手架 sh ‘hexo deploy’ // 部署 echo “部署完成” } }服务启动展示系统主页,可以作为团队以及小型公司共享文件的社区论坛,hexo 构建速度快,采用纯静态框架,语法采用纯markdown 语言,适合编写文档。页面详情,可以通过配置是否开启评论功能以及可以添加赞赏功能,并且可以统计字数,建议时长等功能,分类标签等适合文档归集等功能总结CODING 是一个面向开发者的云端开发平台,提供 Git/SVN 代码托管、任务管理、在线 WebIDE、Cloud Studio、开发协作、文件管理、Wiki 管理、提供个人服务及企业服务,其中「CODING 企业版」实现了 DevOps 流程全自动化,为企业提供软件研发全流程管理工具,打通了从团队构建、产品策划、开发测试到部署上线的全过程。 集成了 Jenkins 等主流企业开发流程工具,如上所示,这个 Hexo 博客便可以在 CODING 上面实现团队协作开发,一键部署作为团队以及公司文档共享社区论坛等作用。本文适量引用:阮一峰的博客 ...

February 13, 2019 · 2 min · jiezi

使用 CODING 进行 Spring Boot 项目的集成

本文作者:CODING 用户 - 高文持续集成 (Continuous integration) 是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。成员之间的代码相互影响,可能会出现各种编译、运行的错误,为了避免提交代码影响到其他开发者,每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现错误,使得开发过程更加简单方便。通用的持续集成流程大体是像上图所示一样,借助 Jenkins 连通 Git 与 Docker 镜像仓库,为后续的持续部署做准备。而在「CODING 持续集成」中,可以省去其中很多环境部署的麻烦事,下面说一下我在 CODING 平台做的持续集成工作。我与 CODING 之缘CODING 是国内首个一站式云端软件服务平台,致力于通过技术创新推动软件开发升级转型,让开发更简单。将代码托管、项目管理、Cloud Studio、一键部署等开发工具集成到浏览器中,免除繁杂的开发环境部署,降低软件开发部署成本。最初了解 「CODING」 ,是我在开发微信小程序时,腾讯云推荐托管代码到 CODING 上,于是注册了一个 CODING 账号。开始使用时,主要以Web版开发工具为主,觉得只是一个 Eclipse 的 Che 版本,当时也自己部署一个 Eclipse 的 Che 版本。但部署 Che 版本时,才发现, CODING 其实比 Che 好用得不是一点半点。流畅性、易用性已经高出 Che 一个等级了,功能上也比 Che 更丰富。后来逐渐用起来了,发现 「CODING」 不只是 WebIDE ,还是 Git 、 Jenkins 、 Wiki 、敏捷开发工具、项目管理工具……现在持续集成功能出来了,可以免费试用15天,于是注册一个玩一玩。wencst 的个人主页「CODING 持续集成」基础操作首先需要创建企业账号;然后创建自己的项目;进入项目维护项目代码。本文所使用的源代码为本人开源的自动开发框架。Git 操作下面为 Git 的操作了,相信看文章的大部分人可以略过这一步。详细的 Git 步骤可以参考:《 CODING 中的 Git 操作》Git 操作主要为后续持续集成操作的触发器。持续集成持续集成操作的设置相对比较简单,按照提示一步步下来即可。有一块需要注意的,就是构建所用的分支,在配置持续集成时,需要选择构建触发方式,触发时间(代码上传时触发/手动触发),以及完成时邮件发送提醒(提醒触发者/不做任何事/只有失败时提醒)。对于多分支代码工程一定要注意,选择自己所需的配置。我这里所用的为系统默认配置,即当有人提交代码至 master 时触发构建,完成时总是发邮件提示开发者。「CODING 持续集成」提供了三套不同的 Jenkinsfile 模板供开发者使用:简易模板、并行模板、自定义模板。我这里选用简易模板,并稍作修改。pipeline { agent { label “default” } stages { stage(“检出”) { steps { sh ‘ci-init’ checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } } stage(“构建”) { steps { echo “构建中…” sh ‘mvn clean install’ echo “构建完成.” archiveArtifacts artifacts: ‘/target/*.jar’, fingerprint: true // 收集构建产物 } } stage(“Docker”) { steps { echo “Docker镜像生成中…” sh ‘cd wencst-generatorJPA/target && cp classes/Dockerfile . && docker build -t wencst/wencst-generatorJPA .’ echo “镜像生成完成.” sh ‘docker push wencst/wencst-generatorJPA’ echo “镜像上传完毕” } } } }更新 Jenkinsfile 后,代码 push 到对应的分支上,会自动执行构建,发现构建失败。点开后,查看构建失败的具体原因,输出与 maven 编译时输出的没有什么差别。原因提示: there is no POM in this directory。原来我中间还有一层目录,需要进入目录后才能编译。pipeline { agent { label “default” } stages { stage(“检出”) { steps { sh ‘ci-init’ checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } } stage(“构建”) { steps { echo “构建中…” sh ‘cd wencst-generatorJPA && mvn clean install’ echo “构建完成.” archiveArtifacts artifacts: ‘/target/.jar’, fingerprint: true // 收集构建产物 } } stage(“Docker”) { steps { echo “Docker镜像生成中…” sh ‘cd wencst-generatorJPA/target && cp classes/Dockerfile . && docker build -t wencst/wencst-generatorJPA .’ echo “镜像生成完成.” sh ‘docker push wencst/wencst-generatorJPA’ echo “镜像上传完毕” } } } }提交代码后,会自动执行构建。可以显示程序编译过程,可以显示每一步详细输出,可以增加状态徽标到相应的文档或网页中。可以说「CODING 持续集成」 想的是比较周到的,基本集成了绝大部分开源系统中相应的职能。构建使用默认的 https://repo.maven.apache.org 源,构建速度也还可以。至此持续集成完成,界面清晰整洁,并且可以对测试报告和构建结果进行下载,构建过程也会发邮件给相关人员。确实让开发更简单了。以前在做这一系列工作时,架构师起码要做几件事情:1.搭建 git 仓库2.搭建 jenkins3.在 git 仓库中增加 CI 配置4.邮箱配置「CODING 持续集成」为开发者省去了很多工作,除了构建过程中必要的工作以外,其他的基本一键搞定,不用关心各个组件的安装配置,环境情况,网络情况,存储备份等内容。Jenkinsfile 拆解重点解释一下 stages 部分,整体分为三个 stages:第一步为代码检出 stage(“检出”) { steps { sh ‘ci-init’ checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } }这一步检出项目中的代码到 jenkins 的 workspace 目录下,这一步是 「CODING 持续集成」 默认的配置,无需过多解释。第二步为编译构建 stage(“构建”) { steps { echo “构建中…” sh ‘cd wencst-generatorJPA && mvn clean install’ echo “构建完成.” archiveArtifacts artifacts: ‘**/target/.jar’, fingerprint: true } }这一步是执行代码编译,我所用的是 maven 编译 spring boot 工程, 「CODING 持续集成」 集成了 mvn 命令,可以直接执行 maven 操作。注意: jenkins 执行 sh 命令的根路径都是在当前 workspace 下,所以切换路径与 maven 编译命令要在同一个 sh 命令下。编译执行后,收集编译的产物,archiveArtifacts artifacts: ‘**/target/*.jar’, fingerprint: true这一步的意思是,将所有工程的 target 路径下的 jar 包都算作工程产物。第三步为 docker 镜像生成 stage(“Docker”) { steps { echo “Docker镜像生成中…” sh ‘cd wencst-generatorJPA/target && cp classes/Dockerfile . && docker build -t wencst/wencst-generatorJPA .’ echo “镜像生成完成.” sh ‘docker push wencst/wencst-generatorJPA’ echo “镜像上传完毕” } } 对于熟悉 docker 的人并不是很陌生,依旧使用 shell 命令来执行 docker build 操作。cd wencst-generatorJPA/target 首先切换路径到 jar 包所在目录。cp classes/Dockerfile . 拷贝 Dockerfile 到当前路径下。docker build -t wencst/wencst-generatorJPA . 执行 docker build 操作,用以创建 docker 镜像。docker push wencst/wencst-generatorJPA 将创建出来的 docker 镜像上传到 dockerhub 中去。总结整体来说 「CODING 持续集成」 想的很周全了,无论从易用性、美观度以及人性化角度上来说,做得都非常不错。下面着重说说我使用 「CODING 企业版」 的持续集成后的感受:满足了从开发到代码管理,到代码集成,到单元测试,甚至到后续部署,一站式管理;配置相对简单,只需配置 Jenkinsfile 即可完成,无需花费大量的人力物力来做各系统间的整合操作;系统集成后,会给开发人员发送邮件,报告集成成功或失败,这一点还是比较人性化的;「CODING 持续集成」平台集成了很多种命令,起码我用到的 mvn/java/docker/git 这一类的命令基本都集成在服务中了。希望 CODING 会越来越完善,越来越好! ...

February 13, 2019 · 2 min · jiezi

CODING 最佳实践:快课网研发效能提升之路

快课企业移动学习平台是上海快微网络科技有限公司自主研发的企业级 SaaS 平台,提供移动学习、考试练习、培训管理、知识分享、统计分析等学习和培训功能,为员工、经销商及客户等全价值链合作伙伴提供全面的知识服务。本文将详细介绍快课网的研发团队是如何使用 CODING 研发管理系统提高研发效能。为什么选择 CODING快课网从创立至今已有 4 年多,作为一个规模比较小的创业团队,我们一直在寻找和尝试各种能提升研发效能的管理方案,这样能够帮助团队节省时间,更加专注于业务。第一步就是上云,我们一开始使用的是阿里云,通过容器化、弹性计算和可视化管理帮助我们节省了不少运维成本。但是仅有这些还不够,要开发还需要搭建很多服务,例如 BUG 跟踪管理、代码版本管理和同步、npm 私服、maven 私服、docker 私服等等。虽然后台团队通过使用 docker 让搭建服务方便了不少,但是我们还不满足。大量的服务为研发团队带来了极高的管理成本。再加上不菲的服务器成本、所使用的开源项目更新较慢等原因导致很多问题短时间内都解决不了,同时很多管理方案还不支持中文。所以我们决定寻找一个集成度比较高的国内的商业平台来帮助我们进行研发流程管理。当时的想法很简单,只要功能齐全,收费能够弹性一些就好。在尝试了很多平台之后,我们最后决定使用 CODING,主要是看中 CODING 的网络连接速度比较快,界面简洁,交互比较友好,功能齐全,反馈处理也非常及时,可以很好地帮我们解决代码托管和 BUG 管理等研发流程问题。我们最开始使用的是 CODING 个人版的团队功能,在 CODING 推出企业版之后我们团队很快迁移到了企业版,相对于个人版来说企业版功能更完善,管理起来也更方便,后续还有持续集成和部署相关功能升级,这些功能正是我们团队所需要的。目前快微团队的整个开发是在 CODING 和阿里云上完成的,CODING 主要用来管理代码、里程碑和持续集成等研发流程。版本规划与任务流程里程碑是我们使用比较多的功能之一。最初,我们使用 CODING 的里程碑来规划版本,比如 1.0 版本对应的里程碑就叫做 1.0,每个任务都是版本中的功能点。后来由于新版本的重构采用了分布式服务化开发,由多个子项目组成。由于各个子项目地版本相对独立导致粒度太细不方便产品的规划,便做了一些调整。目前里程碑主要是用来做长周期的规划,每一个任务都是一个小的项目,由一个或多个人来完成,比如将课件服务 1.1 版本分就单独为一个任务。快课技术团队目前的绩效考核也是基于 CODING 的任务管理和里程碑实现的:由产品发布相关版本的产品说明书,包含原型图和功能点文档部分。创建任务,分派给项目负责人,项目负责人需要评估任务的工作量。工作量给定的有参考标准,将最简单的帐号密码登录接口的工作量定为 1,最小为 1。评估工作量之后进行审核,确定起止时间和奖金。进入开发阶段,开始倒计时。开发完成之后进行验收,由技术审查代码(每次发起合并请求也有审查),产品检查 UI 交互,顺利完成验收则关闭任务,将工作量的值作为绩效值。对于不能按期完成的任务,进行惩罚措施,每逾期一天扣 10% 绩效。对于工作量比较大的任务,可以由一个人主要负责,多人完成,负责人需要为每个人安排详细的工作内容,最终由负责人按贡献比例分配绩效和奖金。这样累计下来,每半年或一年可以根据绩效进行一次评定,给表现好的员工涨薪。分支管理快课目前的分支管理方案与 CODING 文档中的最佳实践比较接近,master 作为主分支只发布正式版本,新增一个 dev 分支作为开发中的分支,并且同时对这两个分支设置保护,禁止直接推送代码到这两个分支上。快课的每个子项目都在项目配置文件里写有明确的版本号,后端 maven 项目写在 pom.xml 中,前端 node 项目写在 package.json 中。开发中的版本号一律带有 SNAPSHOT 后缀,以表示这是快照版本,会不断发生变化,不能在生产环境使用。比如正在开发 1.1 版本,此时 master 分支的版本号是 1.0.0(随着补丁的增加,最后一位也会不断增加,比如版本号有可能为 1.0.9),dev 分支的版本号是 1.1.0-SNAOSHOT。当需要开发一个新版本的时候,首先基于 dev 分支新起一个分支,可以根据实际情况来命名新分支,比如可以叫 dev-v1.1 或者 dev-tom 等等,没有限制。在新分支上完成开发之后,在 CODING 上发起合并请求申请合并到 dev,此时合并请求的标题和内容必须写的详细一些,审核之后进行合并,合并的同时删除原分支,只在 CODING 上保留 master 和 dev 两个分支。最终所有新开发内容都完整合并到 dev 分支后,测试通过,再从 dev 分支新起一个分支,更改版本号为正式版本号,进行推送并新建合并请求,合并到 master 分支上。对于已经上线的版本,如果有 bug 需要修改,则从 master 分支新起分支进行修改,完成后将版本号最后一位 +1,然后推送并新建合并请求合并到 master。持续集成我们团队很有幸获得了 CODING 持续集成功能的内测资格,之前也有尝试过自建 Jenkins 服务,对持续集成有一定积累能很快上手,于是我们便开始转向 CODING,毕竟一站式的 DevOps 工具链服务更方便,可以给研发团队节省很多精力。CODING 对 Jenkins 进行了封装,只需要在项目根目录下创建一个 Jenkinsfile 文件,配置好之后推送上去,推送完成之后在后台开启持续集成即可。持续集成主要用在后端 maven 项目上,来做规范检查(checkstyle 插件)、单元测试和代码质量检查(spotBugs 插件),这样当团队成员在创建合并请求时,管理者可以看一下代码是否规范并跑通了必要的测试,在 CODING 上构建成功后才能继续对修改进行审查。自动化构建为研发提供了很大的便利,避免了一些人为的不稳定因素,也为项目管理者节省了不少时间。目前快课的项目都是直接发布到 docker 私服上的,推送成功之后修改 k8s 中的镜像版本来完成自动部署。我们也期待 CODING 未来会上线的部署管理功能,能支持在目前的构建基础之上自动发布 docker 镜像,然后再自动更新 k8s 相关配置的镜像版本,补充 CI/CD 功能,这样的话就能更好的实现研发流程的自动化了。点击立即体验一站式 DevOps 工具链 ...

February 12, 2019 · 1 min · jiezi

【工程化】持续集成

持续集成(Continuous integration,简称CI)是软件开发工程化的关键流程之一。最近跟朋友做个练手的项目,用Jenkins进行持续集成和部署,相关的东西在这里进行一些记录。刚接触不多,一些东西还没有完全理清楚,埋坑待填。CI的概念CI这个概念其实是比较模糊的。这里的“集成”,最早似乎是指代码的集成。阮一峰-持续集成是什么?对相关概念有所阐述。具体而言,就是对提交到分支的代码进行较高频率的构建、测试,通过后就“集成”到主干。这个频率通常为一日多次。这篇文章提到的工作流在目前看来是比较罕见的,里面解释的持续集成跟我们现在常说的持续集成也有不小区别。而现在说起持续集成,往往是指代码提交后,自动触发自动化测试与构建的过程。这时对“集成”的解释大体有两种说法,一种是说,把测试、构建之类的步骤自动化地集成在一起;另一种说,通过测试、构建来判断代码集成得是否成功。总体而言,CI在现在的运用中,是在代码提交后触发的检查步骤,而不是代码提交前的前置步骤。代码提交这一行为,往往根据团队的工作流进行具体定制,不会跟CI强绑定。浏览网上资料的时候要注意,很多时候虽然大家说的都是持续集成这个词,但由于随时间的演化,其内涵可能有很大的不同。CI的工具CI的工具有很多,大体上分为两大类。一种是第三方平台上的,比如你用github,相关的CI平台就有Travis CI,Circle CI等。进行相关配置后,代码提交到github就能自动触发,不需要自己部署服务器,当然,这些CI服务通常是收费的。如果是开源项目会有一定的免费资源。一种是自己部署的,比如Jenkins。这种其实不复杂,规定一个触发方式,是定时触发还是通过github的钩子去触发;然后自己写个脚本做测试、构建。完了之后想要部署的话也是自己写脚本来搞。Jenkins主要是对项目、版本、每次构建做下管理,提供UI让我们进行一些配置。这里我只用过Jenkins,emmm,吐槽一下,上古界面,看起来就没有商用CI平台舒畅…未完待续。

February 12, 2019 · 1 min · jiezi

Travis CI 实现自动备份Segmentfault文章到Github

上一篇简单介绍了 Travis CI, 这里再简单介绍一个应用,利用Travis CI的Cron Jobs功能,实现自动备份segmentfault文章到Github。第一步:抓取文章内容Segmentfault 非常友好的为每个专栏提供了一个RSS,我们很方便就可以抓取到文章内容,稍做转化就可以了,省略不写,详见代码第二步:配置 SSH keysGithub 上有详细的说明,省略不写,敬请查看第三步:编写.travis.yml 配置我们采用git命令行提交commits的方式备份文章。要实现自动提交,需要把私钥也和代码一起上传,但是私钥泄漏相当于放弃了仓库的所有权,所以需要对私钥进行加密。(这是个比较麻烦的方法,但是实际上开发中我们部署代码到自己的服务器常用的也是 ssh 远程操作,有借鉴意义)1.安装 travis我们通过 Ruby 的 gem 包管理器来安装 travis, 如果未安装 Ruby,先下载最新版本,并安装它,然后执行如下命令确认 gem 是否安装成功gem -v能够正常列出版本号,表示安装成功因为众所周知不可说的原因,在安装包时,使用官方源地址会非常慢。我们切换成国内的镜像gem sources –add https://gems.ruby-china.com/ –remove https://rubygems.org/ # 老版本 Ruby 这里会证书相关的错误,所以确认安装了最新版本gem sources -l #确保列出的源地址只有镜像地址准备工作做好了,我们执行如下命令安装gem install travis2.登录 Travis CItravis login –auto执行命令,根据提示输入 github 的用户名和密码。这里有个坑,window 用 cmd 操作时死活不好使,如果你在输入密码时显示的明文,那么恭喜你也踩坑了,你可以改用 power shell 来操作,不过后面还是会遇到一些莫名其妙的问题,建议在 inux 环境下操作,哪怕是虚拟机也行。3.填加私钥执行如下命令travis encrypt-file ~/.ssh/id_rsa –add实际使用中很有可能会报错Can’t figure out GitHub repo name. Ensure you’re in the repo directory, or specify the repo name via the -r option (e.g. travis <command> -r <owner>/<repo>)这个的意思是找不到仓库,需要指定,可以这么操作travis encrypt-file -r actors315/actors315.github.io ~/.ssh/id_rsa –add执行完成后,在 .travis.yml 文件中会自动填加如下代码openssl aes-256-cbc -K $encrypted_xxxxxx_key -iv $encrypted_xxxxxxx_iv -in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d并生成一个 id_rsa.enc 文件,你可以手动移到合适的目录,并调整上面命令文件的位置并在 Travis CI Setting 页面会看到增加了如下两个变量如果在 windows 下生成的文件,travis-ci 构建时很可能会报这个错。0.02s$ openssl aes-256-cbc -K $encrypted_2805aa35fedb_key -iv $encrypted_2805aa35fedb_iv -in .travis/id_rsa.enc -out ~/.ssh/id_rsa -dbad decrypt4.编写配置.travis.yml 增加如下配置,详细见源码# 配置环境before_install: # 替换为刚才生成的解密信息 - openssl aes-256-cbc -K $encrypted_79258127fb87_key -iv $encrypted_79258127fb87_iv -in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d # 改变文件权限 - chmod 600 ~/.ssh/id_rsa # 配置 ssh - eval “$(ssh-agent -s)” - ssh-add ~/.ssh/id_rsa - cp .travis/ssh_config ~/.ssh/config # 配置 git 替换为自己的信息 - git config –global user.name ‘actors315’ - git config –global user.email actors315@gmail.com # 用 ssh 方法提交 - git remote set-url origin git@github.com:actors315/actors315.github.io.git # 切换到提交的目的分支 - git checkout masterinstall: - composer install –prefer-dist –optimize-autoloader –quietscript: - php -f bin/console.phpafter_success: - git add README.md - git add ./markdown/ - git add ./files/* # 这里很重要,commit message 一定要填加 [skip travis] , 不然可能会进入死循环,一直在提交一直在自动构建 - git commit -m “[skip travis] auto build by travis-ci” - git push origin master第四步:填加 Cron jobs最后一步,配置完后就可以自动跑了。有三个时间周期可供选择,每月、每周、每天,按需选择就好了这样就大功告成了,每天自动跑一次其他方法1.使用 Personal access tokens 实现这也是 git 命令行自动提交,使用 Personal access tokens 也很方便,也是推荐。2.使用 Travis CI 官方推荐的 deploy 流程如果你需要自动提交的分支和自动构建不是同一个分支,这就非常方便了,你只需要生成一个 Personal access tokens ,在.travis.yml 文件中简单增加一点配置就好了。deploy: provider: pages skip-cleanup: true github-token: $GITHUB_ACCESS_TOKEN target-branch: gh-pages keep-history: true on: branch: master这个方式还没有研究出来是否可能指定 commit message, 如果同分支又会进入到死循环,同分支部署慎用详见官方文档 ...

January 18, 2019 · 2 min · jiezi

自动化部署工具Syncd v1.1.0发布,提供二进制安装包

Syncd是一款开源的代码部署工具,它具有简单、高效、易用等特点,可以提高团队的工作效率。项目地址(Github) 项目地址(Gitee) 下载地址 v1.1.0 使用文档特性:Go语言开发,编译简单、运行高效Web界面访问,交互友好灵活的角色权限配置支持Git仓库分支、tag上线部署hook支持完善的上线工作流邮件通知机制更新内容安装脚本通过go env获取GOPATH #8utf8 to utf8mb4 #13支持go modules #4压缩登录背景图 #5添加服务器支持填入域名 #3解决没有添加集群的时候添加项目出错 #7提供二进制安装包

January 16, 2019 · 1 min · jiezi

Travis CI 简介

什么是Travis CITravis CI 是目前新兴的开源持续集成构建服务。构建并自动提交代码到 Github 1.填加私钥执行如下命令travis encrypt-file ~/.ssh/id_rsa –add实际使用中很有可能会报错Can’t figure out GitHub repo name. Ensure you’re in the repo directory, or specify the repo name via the -r option (e.g. travis <command> -r <owner>/<repo>)这个的意思是找不到项目,需要指定,可以这么操作travis encrypt-file -r actors315/actors315.github.io ~/.ssh/id_rsa –add

January 14, 2019 · 1 min · jiezi

Syncd - 自动化部署工具

syncd是一款开源的代码部署工具,它具有简单、高效、易用等特点,可以提高团队的工作效率.目录特性原理安装使用帮助授权特性Go语言开发,编译简单、运行高效Web界面访问,交互友好灵活的角色权限配置支持Git仓库分支、tag上线部署hook支持完善的上线工作流邮件通知机制原理GitSyncd服务通过git-ssh(或password)方式从仓库中拉取指定tag(分支)代码构建运行配置好的构建脚本, 编译成可上线的软件包在这一环节中,可运行单元测试 (例如 go test php phpunit, 下载依赖 (如 go: glide install php: composer install), 编译软件包 (如 js: npm build go: go build xx.go java: javac xx.java c: cc xx.c) 等.分发通过 scp 命令分发软件包到各机房生产服务器的临时目录, 远程执行 pre-deploy 配置的命令, 执行完毕后解压缩软件包到目标目录,然后执行 post-deploy 命令分发上线过程是串行执行,并且任意步骤执行失败整个上线单会终止上线并将状态置为上线失败,需要点击 再次上线 重试.将来会支持同一集群服务器并行执行, 集群之间串行发布的特性SSH信任生产服务器与部署服务器之间通过ssh-key建立信任配置方法请参考 秘钥配置 章节安装准备工作Go推荐Go1.10以上版本, 用来编译源代码NginxWeb服务依赖NginxMySQL系统依赖Mysql存储持久化数据, 推荐版本 Mysql 5.7Linux + Bash系统会使用到 git, ssh, scp 等命令,所以目前只推荐在Linux上使用, 并且需要提前安装或更新这些命令道最新版本秘钥配置由于部署服务器(Syncd服务所在的服务器)与生产服务器(代码部署目标机)之间通过ssh协议通信,所以需要将部署机的公钥 (一般在这里: /.ssh/id_rsa.pub)加入到生产机的信任列表中(一般在这里 /.ssh/authorized_keys)可使用 ssh-copy-id 命令添加,或手动拷贝. 拷贝后不要忘记进行测试连通性 ssh {生产机用户名}@{生产机地址} 最后建议将以下配置加入到部署服务器ssh配置/etc/ssh/ssh_config中,关闭公钥摘要的显示提示,防止后台脚本运行失败Host * StrictHostKeyChecking no请注意: ssh目录权限需按此设置,否则会出现无法免密登录的情况/.ssh 0700/.ssh/authorized_keys 0600安装运行以下命令curl https://raw.githubusercontent.com/dreamans/syncd/master/install.sh |bash当前路径中若生成 syncd-deploy 或者 syncd-deploy-xxx 目录则表明安装成功生成的 syncd-deploy 目录可拷贝或移动到你想要的地方,但不要试图将此目录拷贝到其他服务器上运行,会造成不可预料的结果.数据库依赖你需要将 github.com/dreamans/syncd/syncd.sql 数据表结构和数据导入到MySQL数据库中修改配置文件修改 syncd-deploy/etc/syncd.ini 中相关配置信息, 具体配置描述可参考注释启动服务cd syncd-deploy➜ syncd-deploy ./bin/syncd -c ./etc/syncd.ini __ _____ __ __ ____ _____ / / / / / / / / / __ \ / / / __ / ( ) / // / / / / / / / / // /// _, / // // ___/ _,/ /___/Service: syncdVersion: 1.0.0Config Loaded: ./etc/syncd.iniLog: stdoutDatabase: 127.0.0.1Mail Enable: 0HTTP Service: :8868Start Running…添加Nginx配置upstream syncdServer { server 127.0.0.1:8868 weight=1;}server { listen 80; server_name deploy.syncd.cc; # 此处替换成你的真实域名 access_log logs/deploy.syncd.cc.log; location / { try_files $uri $uri/ /index.html; root /path/syncd-deploy/public; # 此处/path请替换成真实路径 index index.html index.htm; } location ^~ /api/ { proxy_pass http://syncdServer; proxy_set_header X-Forwarded-Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Origin $host:$server_port; proxy_set_header Referer $host:$server_port; }}重启nginx服务修改hosts若域名未解析,可修改hosts进行临时解析sudo vim /etc/hosts127.0.0.1 deploy.syncd.cc;安装完成打开浏览器,访问 http://deploy.syncd.cc初始账号:用户名: syncd邮箱: syncd@syncd.cc密码: syncd.cc!!!登录后请尽快修改密码使用系统使用流程图使用截图 帮助遇到问题请提 issue或者加微信进讨论群授权本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 LICENSE 文件中 ...

January 12, 2019 · 1 min · jiezi

10分钟读懂阿里巴巴高级专家在Flutter Live2018的分享

12月4日,google flutter团队宣布第一个flutter正式版本发布。次日,Flutter Live Beijing 会议上,google flutter团队邀请了在这一技术方案中重要的合作伙伴闲鱼团队分享这半年以来的通过flutter产出的业务结果以及对应的技术挑战。本文根据Flutter Live Beijing嘉宾闲鱼客户端团队负责人于佳(宗心)的演讲内容进行整理,从flutter的优势和挑战引出闲鱼这半年来针对flutter基础设施进行重新的构建,定义,以及优化的过程,最后是这半年来对社区的一些贡献和未来的规划。Flutter的优势与挑战众所周知,Flutter提供了一套解决方案,既能用原生ARM代码直接调用的方式来加速图形渲染和UI绘制,又能同时运行在两大主流移动操作系统上,其像素级别的还原,保证了不同平台的UI强一致性。同时其提供了一整套机制(hot reload/attach Debug)保证开发的高效,基于此闲鱼团队在众多跨平台方案中选择了Flutter作为其未来主要的开发方案。从4月份开始尝试在业务侧接入flutter到现在,闲鱼在线上已经有10+的页面使用了flutter进行开发,其中覆盖了核心主链路发布和详情。闲鱼目前是市场上最大的闲置交易社区,作为一款有巨大用户体量的C端创新类产品,我们对体验以及研发迭代效率都有比较高的要求。在享受flutter带来的收益的过程中,同样会面临技术转型过程中的一些挑战。主要的挑战来源于以下的三个方面工程体系在现有工程体系下如何将flutter体系融入,并保持团队不同技术栈(Android/iOS/Flutter)的同学能各自独立高效进行开发。业务架构如何提供一套flutter之上的业务架构,保证上层代码的统一标准,同时尽可能的使得代码的复用度及隔离性更好。基础中间件如何保证不同技术栈背后使用的基础能力是一致的(底层统一使用具有相同优化策略的图片库/音视频库),且在这个过程中如何解决flutter融入后产生的问题。面对这些挑战,闲鱼团队在下半年开始了针对基础设施的改造与重建。基础设施重建之路工程体系工程体系部分,首当其冲需要考虑的是不同技术栈同学的协同问题,举例说明,我们的详情和发布页面是flutter的,而首页以及搜索部分目前暂时采用native进行开发。这就需要考虑到flutter的环境要对开发native的同学透明,甚至在native同学没有安装flutter环境的情况下,依然可以保持原来的方式进行开发native页面。如图中所示,以iOS为例,我们针对flutter的框架flutter.framewrok和业务代码App.framework通过持续集成服务进行打包并自动上传至云端的pod repo上,native同学只需在Podfile内指定对应的两个库的版本即可,同理,针对flutter的plugin代码,同样打包上传至pod repo即可。这套体系整体不复杂,需要说明的是,由于多人开发flutter工程,因此打包是一件非常频繁的事情,因此我们这半年构建了持续集成体系来帮助大家将打包上传等整个体系做成一键式服务,另外,由于原有iOS平台的flutter产物是需要依赖我们的native主工程的代码的,这种默认的打包方式,代码量巨大,造成持续集成时间在10-20分钟不等,因此在这个过程中,闲鱼团队通过直接基于xcode_backend.sh + insert_dylib的自定义脚本完成了不依赖native主工程源码的打包,将持续集成时间降至2分半。同理在android上面,也进行了一些基础的改造,感兴趣的同学可以给我们留言,我们会根据大家的需求程度在后续安排贡献给flutter社区。另外一部分比较重要的内容是混合栈相关的,由于flutter没有提供flutter到混合工程的最佳实践,所以我们在上半年自建了一整套混合栈的体系,这里主要是分享一些混合栈的关键思考,在混合栈的实现过程中,需重点测试验证dart这一侧widget的生命周期,并简化堆栈的管理(目前闲鱼的做法是将堆栈管理统一交由native进行控制,简化Dart层API),并需要考虑如何兼容Dart上层的比如Navigtor API的调用。整体这部分闲鱼团队还在验证当中,总之,这部分看似简单,但实际是比较深的坑,需要重点优化。另外,截至发文时间前,我们跟google flutter团队就混合栈交换了一些看法,flutter团队后续如果可以提供多flutterview,单flutter engine的基础能力,就可以使得闲鱼现有的混合栈实现成本整体大幅度降低,后续大家有什么特别好的建议,也欢迎跟我们进行交流。业务架构今年下半年由于有更多的业务迁移至flutter,这意味着更多的团队成员开始了Dart侧的研发。很快我们发现团队的代码风格,层次结构都比较混乱,bug也层出不穷,因此我们需要找到一种可以保证大家研发规范,同时确保多人协同过程中,代码既能更好的复用,又可以在适当的场景下做到相互隔离的这么一种方案。在经过社区的多个框架库的实践和比较以后,不管是flex还是redux都不能完全解决我们的问题。最后我们选择了自己进行设计和实现,我们对框架进行基础分层以后,将重点最终落在了基于单一数据源的组件化框架上面,因此我们产生了自己的框架fishRedux,我们严格参考标准js的redux规范和源码(redux的设计三原则)进行了完整的dart侧的实现,并在此基础上提供扩展能力用于我们的组件化开发。如图所示,component将redux中的view,reducer,middleware以及我们的扩展能力effect进行组装,从而可以在不同的页面进行组件的复用,当然,全局依然遵循redux的单一数据源的原则,但我们将逻辑本身通过更细粒度的拆解,保证了这些逻辑在不同的component组装下都可以尽可能的进行复用。基于这种结构,我们可以将任意的component进行挂载和拼装,通过更多小粒度的组件,产生不同场景下的复杂页面。另外,针对于component的多层组装,大家可以细看下dependents这个字段,通过基于这个字段的组装,在我们提供的这段代码里面,实际上是提供了一个详情页面的插槽的功能,详情页面目前在闲鱼有近10种不同的组合,在这个场景下,可以在保证组件可以服用的同时,做到不同流程下的代码隔离。我们只要针对dependents的components里面进行替换,就可以很容易的达到在详情页面插入不同widget以及逻辑的效果。fishRedux框架目前已经接近修改的尾声,目前还有部分微调和文档的补充,明年4月份前,我们有计划进行该框架的开源,为后续业务架构提供一个新的标准,大家敬请期待。基础中间件在阿里集团内部,已经产出了较多的基础中间件,因此如何复用这个中间件到flutter侧是一个新的挑战,针对于传统的比如网络库,crash收集等中间件,由于不涉及到UI的复用,相对容易,但针对音视频,图片库等这类的中间件,虽然flutter提供了flutterTexture的方案,但依然不是特别完美。我们在做音视频及图片库的复用过程中,主要的问题在于flutter原生提供的机制,针对图片的渲染存在GPU到CPU,然后CPU再到GPU的这样一个过程,如图所示。根本原因在于不同的glContext无法共享texture。因此,我们目前采取的方案是修改flutter引擎,并暴露出glContext的shareGroup(以iOS为例)。目前整个方案已经上线。由于该改动目前在闲鱼自己fork的engine里面,因此目前将我们之前踩到的一些坑同步给大家,如果大家有在flutter和native侧同时使用音视频的情况,建议特别注意ppt中的前两点,否则会造成flutter侧或者native侧音视频的错乱。当然如果按照闲鱼团队的提供的修改方案进行engine改造后,也可以通过第三点,对native设置跟flutter相同的sharegroup来解决这个问题。在flutter live Beijing结束之后,我也将该方案正式介绍给google flutter团队,希望后续能将类似的功能融入flutter的官方实现。闲鱼与flutter社区闲鱼这半年,对于flutter社区,也有一些小小的贡献。我们针对flutter的方案进行整理并在各个技术社区进行传播。另外我们将已有的一些问题和解决方案提供给google flutter官方团队,直接或者间接的推动了flutter的整体进度,并改变了这个技术未来的部分走向。我为自己的团队感到由衷的骄傲,但同时我意识到,要想让flutter成为终端未来的主流技术,依然任重道远,因此我们后续也会将目前的一些相对稳定的框架和解决方案,逐步开源到社区,我们的要求是,至少闲鱼团队需要在线上有应用和验证。目前我们已经有一些初步的demo和小工具放在上面,大家感兴趣的可以往我们的github上提issue,我们后续会逐步开放更多的代码。最近会公布的比较重要的框架会是fishRedux,因此请大家持续关注我们。总结与展望我们首先带大家回顾了flutter带来的优势以及在闲鱼的实际例子,并引出在复杂工程下的一些挑战。我们针对这些挑战,在下半年进行了整个体系的重新建设,初步完成了隔离的混合工程体系统一标准的业务架构高效复用基础中间件设施本次的分享,其实只是我们目前团队的一部分内容,我们基于flutter和dart还有更多的技术方案目前在预研和研发中,所以没有在这次live中进行宣讲。在后续跟google flutter团队的沟通中也了解到,他们对我们的多个方案都有较大的兴趣。对于未来来说,一方面,除了本文分享的内容以外,我们自己在代码自动生成/Dart Server/线上问题自动回放/国际化/动态模版等/持续集成等多个方面都在持续关注和调研。另一方面,在flutter 1.0公布后,类似hummingbrid这一类全新的方案也有机会让flutter具有全终端制霸的可能性,我们也会持续跟进和进行尝试。Anyway,依然希望有更多的同学可以加入我们一起完善flutter的生态,同时通过新的技术手段,让天下没有闲置。来闲鱼一起改变世界吧,少年!PPT下载:https://yq.aliyun.com/download/3130本文作者:闲鱼技术-宗心.阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 11, 2018 · 1 min · jiezi

安装 gitlab CI 服务.md

安装 gitlab-ce安装依赖包yum install curl policycoreutils openssh-server openssh-clientssystemctl enable sshdsystemctl start sshdyum install postfixsystemctl enable postfixsystemctl start postfixfirewall-cmd –permanent –add-service=httpsystemctl reload firewalld下载 gitlab-ce 镜像vim /etc/yum.repos.d/gitlab-ce.repo[gitlab-ce]name=Gitlab CE Repositorybaseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/gpgcheck=0enabled=1yum makecacheyum install gitlab-ce配置vi /etc/gitlab/gitlab.rbexternal_url ‘http://ip’启动gitlabgitlab-ctl reconfigure遇到报错Error executing action run on resource ’execute[semodule -i /opt/gitlab/embedded/selinux/rhel/7/gitlab-7.2.0-ssh-keygen.pp]stop gitlabyum install libsemanage-static libsemanage-devel安装CI服务下载安装CIwget https://mirrors.tuna.tsinghua.edu.cn/gitlab-runner/yum/el7/gitlab-runner-10.5.0-1.x86_64.rpmrpm -ivh gitlab-runner-10.5.0-1.x86_64.rpmsudo useradd –comment ‘GitLab Runner’ –create-home gitlab-runner –shell /bin/bashgitlab-runner uninstallgitlab-runner install –working-directory /home/gitlab-runner/ –user gitlab-runnergitlab-runner restartgitlab-runner status注册 runnersudo gitlab-ci-multi-runner register– 输入Gitlab CI地址, (e.g. https://gitlab.xunlei.cn/ci)http://192.168.1.249/gitlab/-- 输入项目CI tokenfuXXXXXXXXXX– 输入 Runner 描述(e.g. home.xl9.xunlei.com 测试runner)测试Runner– 输入 Runner 标签,可以多个,用逗号隔开(e.g. 10.10.34.91-dev)251-dev– 输入 Runner 执行的语言 (e.g. shell)shell– 认证是否注册成功sudo gitlab-ci-multi-runner verify编写脚本在项目下面创建.gitlab-ci.ymlstages: - deploydeploy_dev: stage: deploy tags: - 251-dev only: - develop script: - deploy_stage.sh然后在部署服务器上的 gitlab-runner 用户路径下创建deploy_stage.shecho “delete old xyj-admin-api"sudo rm -rf /raid1/www/testsudo git clone git@192.168.1.249:test/xyj-test-api.git /raid1/www/testsudo git fetch –allsudo git reset –hard origin/testecho “=============重启服务====================“source /etc/profilesudo supervisorctl restart testtime=dateecho “部署结束: $time.“echo “================================================“其中 测试项目是被 supervisorctl 管理的要确保几件事改服务器能够正常从远端克隆数据命令几点要带上sudo用户sudo无密码及在tty下可以使用需要参考 Linux sudo 相关操作如果克隆下来的文件放在挂载盘,需要在 ~/ 路径下执行 clone 然后放到对应路径,否则报错 fatal: could not create work tree dir遇到无法克隆,且 gitlab 日志为gitlab JWT::DecodeError (Nil JSON web token) 修改 nginx 配置upstream gitlab-workhorse { server unix:/var/opt/gitlab/gitlab-workhorse/socket; }…proxy_pass http://gitlab-workhorse;…git push develop 后触发脚本 ...

November 11, 2018 · 1 min · jiezi