日志的作用有两个:当构建日志的数据块通过消息队列进来时,更新数据库对应行,然后推送它到Pusher用于实时的用户界面更新。
日志块以流的形式在同一个时间从不同的进程中进来,然后被一个进程处理。这个进程每秒最高可处理100个消息。
一般情况下这样处理日志流的方式也相当OK,但是这也意味着我们很难处理某些时刻突然增长的日志消息,因此这个唯一的进程对于我们系统的扩展会成为一个很大的障碍。
问题在于,进程是按照这些消息到达消息队列的先后顺序来进行处理的,而Travis CI中的所有事情都依赖于这些消息。
更新数据库里的一条日志流意味更新包含所有日志的一行数据。更新用户界面的日志当然意味着在DOM树上附加一个新的结点。
为了解决这个棘手的问题,我们需要改很多代码。
但是首先,我们需要理清楚什么才是一个更好的解决方案,好的解决方案应该是能够让我们很方便的扩展日志处理的部分。
我们决定让处理的顺序作为消息本身的一个属性,而不是隐含的依赖于它们被放进消息队列的顺序。
这个想法是受到Leslie Lamport于1978年发表的一篇论文《Time, Clocks, and the Ordering of Events in a Distributed System》的启发。
在这篇论文中,Lamport描述了在分布式系统中,使用递增计数器来保留事件发生的顺序的方法。当一个消息被发送,发送者会在消息被接收者接收到之前增加计数器的值。
我们可以简化那个想法,因为在我们的场景中一个日志块只能来自一个发送者。进程只要不断增加计数器的值,就可以让之后的日志收集工作变得简单。
剩下的工作就是根据计数器的值来对日志块进行排列了。
困难之处在于,这样设计之后等同于允许向数据库写入小的日志块,这些小日志块只有在对应任务结束后才会写入到完整的日志中。
但是这会直接影响到用户界面。我们不得不面对消息以无序的方式到来。这个变化的确影响的范围大了些,但它反过来简化了很多部分的代码。
从表面看,这个改动似乎无关紧要。但是依赖于你本不需要依赖的顺序会带来更多潜在的复杂性。
我们现在不用依赖于信息是如何传送的,因为现在我们可以在任何时间得到他们的顺序。
我们修改了不少代码,因为那些代码做了一个假设,任何信息都是顺序过来的,而这个假设是完全错误的。在分布式系统中,事件可以以任何顺序在任何时间到达。我们只需要确保之后我们可以将这些片段重新组装回去。
你可以从我们的博客获取这个问题更详细的说明。
到了2013年,我们每天已经在运行45000次构建。我们还是在为早先的设计付出着代价,但是我们也在慢慢的改进设计。
我们现在还有一个麻烦。系统所有的组件还是在共享同一个数据库。如果数据库出现问题,自然的所有组件都会出现问题。这个故障上周我们刚刚遇见一次。
这同样意味着日志写入的数量(目前可以达到每秒300次)影响到了我们API的性能,当用户浏览我们的用户界面时可能会慢一点。
另外,当我们从构建任务的数量上考虑时,我们的下一个挑战就是如何去扩展我们的数据容量。
Travis CI在500台构建服务器上运行,这已经不能再算是一个小的分布式系统了。我们现在正着手解决的问题还是从一个相当小的维度来考虑的,但即便在那个维度上,你也能够遇到很多有趣的挑战。根据我们的经验,简单直接的解决方案总是比那些更复杂的要好。
相关推荐
开源项目-travis-ci-travis-ci.zip,[travis CI]: Go 1.10 is parsed as 1.1 if not passed as strings
hello-travis-ci:Travis CI教程,主要介绍如何使用Travis CI的检验代码功能和代码审查功能。 Travis CI的教程主要介绍如何使用Travis CI的检查代码功能和Code Review功能
后台的Travis CI插件 特征 列出Travis CI构建 触发生成 如何将Travis-ci项目依赖项添加到Backstage应用程序 如果您有不带此插件的后台应用程序,请按照以下说明进行添加: 在backstage/packages/app项目中,将该...
使用travis CI自动打包APK,并上传到fir,整个步骤执行成功的打印日志,帮助学习者分析错误问题。
travis-minikube:在Travis CI上运行minikube
Drupal / Travis CI 演示 该项目将在 GitHub 上演示基本的 Drupal/Travis-CI 集成。 目前展示的功能: 通过 Ansible 和/或 git 安装 Drupal 和 drush。 Drupal 核心测试通过 drush(simpletest 和 PHPUnit)运行...
travis.rb, Travis CI客户端( ruby 和库) Travis客户 Travis包含一个 命令行 客户端和一个 ruby 库插件,与 Travis CI服务接口。 无论你是使用 travis-ci.org, travis-ci.com 还是任何定制 Travis CI设置,你
用户可以设置默认值并将逻辑直接包含在Travis::Config类中,也可以将其扩展到例如Travis::Logs::Config 。 例如 require 'travis/config' module Travis class Config < Hashr define host : 'travis-ci.org'...
haskell-ci:Travis CI和Appveyor模板,用于测试Haskell应用程序并发布二进制发行版
字符串化-travis-徽章 从对象生成 Travis CI 徽章。使用安装npm i stringify-travis-badge --save用法 var travis = require ( 'stringify-travis-badge' ) ;travis ( 'assemble' , 'verb' ) ;//=> [![Build Status]...
该Ember插件为您提供了实用程序,用于检索任何公共Travis CI回购的构建状态,以及可根据返回的状态显示动态内容的组件。 构建状态会缓存在应用程序会话中,以避免不必要的API调用。 内容 安装 ember install ember...
从2020-11-25开始,我的项目不再使用Travis CI。 相反,我在GitHub Actions中使用 。 保持此仓库8年后,我很高兴通过接力棒。 如果您愿意并有能力支付Travis CI,您可能仍然会发现此回购很有用。 你可以分叉。 有...
Travis CI Webhook 简单的Webhook即可验证Travis CI通知并运行命令
从参数列表或对象生成 Travis CI URL。 使用安装 npm i stringify-travis-url --save 用法 var travis = require ( 'stringify-travis-url' ) ; travis ( 'jonschlinkert' , 'micromatch' ) ; //=> '...
Travis CI cron触发器该项目允许定期触发构建,例如测试刮板。 在Travis,他们最终将实现cron(ref: ),同时,我希望这会有所帮助:)技术上该项目由两部分组成: 一个Django网络应用程序(在运行),允许用户将新的...
Travis CI monorepo演示 该存储库是有关使用构建Monorepo项目的实验。 如果您对其他CI选项感兴趣,请确保签出我的。 这个怎么运作? 它利用Travis矩阵功能,在.travis.yml我们在.travis.yml为不同项目位置定义...
Travis CI对流星包运行速度测试的支持,已通过以下测试茉莉花,但也应与摩卡咖啡搭配使用。 指示 执行以下步骤,将travis ci测试添加到您的项目中: 将.travis-example.yml复制到您的软件包目录,将其重命名为....
tox-travis, Travis CI无缝集成 毒理检测Travis和 Travis Tox Travis是一个毒性测试插件可以简化毒物检测和Travis之间的设置。用法配置 python 版本以在 .travis.yml 中测试,并使用pip安装 tox-t
Travis API 警告!!!!! Master分支仅适用于.com。 如果您想为.org部署更改,请使用org-only分支 要求 您需要以下软件包才能使travis-api正常工作: PostgreSQL 9.3或更高版本 邦德勒 雷迪斯 可选: RabbitMQ...
Travis CI ember Web客户端运行应用该应用程序是使用开发的。 它需要安装了npm的nodejs。 为了运行该应用程序,您需要使用以下命令安装依赖项: npm ci然后全局安装ember-cli,以便可以访问ember命令: npm install ...