深入理解Moby Buildkit系列 #26 - Scheduler的构建源Edge

256 阅读2分钟

这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

为了理解龙飞讲解的scheduler,袁小白先是去了解了pipe的使用方法和设计原理,现在回忆起来,有以下特点:

  • pipe由sender和receiver组成
  • 当sender所依赖的用户函数执行完成后,会调用sender.Finalized,并回调pipe.OnSendCompletion方法,就是在这里建立了pipe的关键结点,当回调发生时,意味着用户函数已经执行完成
  • receiver可以通过Receive获取用户函数执行的结果
  • receiver还可以主动取消req,让用户请求被取消执行,取消成功时也会有一个回调函数pipe.OnReceiveCompletion

对于用户来说,使用起来也很方便,可以直接初始化一个pipe,也可以传入一个待执行函数来创建一个pipe。 如果关心用户函数执行的结果,就注册onSendCompletion函数;如果关心取消事件,则注册OnReceiveCompletion事件。

弄清楚了pipe的工作原理,现在是时侯去探索scheduler究竟是如何高效组织管理好构建事件了。

构建源Edge

回到构建事件的起点jobs.go j.Build,我们发现构建源就是在这里被准备好的:

...
v, err := j.list.load(e.Vertex, nil, j)
if err != nil {
   return nil, nil, err
}
e.Vertex = v
...

将原有的e.Vertex转换成了j.list.load的返回值,就是vertexWithCachOptions,而这个新的vertex,实现了Vertex的所有接口,其中就实现了Inputs() []Edge,也就是在这里将所有的Edge都关联了起来:

Edges inputs.jpg

用我们常用的例子来理解,我们现在有两个Op,一个是SourceOp,另一个是ExecOp,都被包裹在了常规的vertex中,为了对Edge进行构建,我们需要将这些初始的vertex包装成vertexWithCacheOptions,并用Edge来进行关联。 这样,DAG图变得更清晰了:

Edges inputs DAG.jpg

DAG有向无环图是由结点Vertex和边Edge组成。 目前我们的结点进行封闭后,最外层是vertexWithCacheOptions,原始层就是vertex,而vertex又连接着Op,也就是operation,我们这个简单的例子中有两个Op。 Vertex之间的关联方式是用Inputs()关联起来的,而Input就是Edge。 目前我们有两条Edge,就算是最后一个结点,也有一条边,而我们准备开始构建的源,就是这一条边 - Edge0。

那Scheduler究竟是怎么编排Edge的构建任务的呢?

下一篇:深入理解Moby Buildkit系列 #27 - 编排高手Scheduler