这是我参加11月更文挑战的第21天,活动概况查看:2021最后一次更文挑战
为了加强自己的了解,袁小白像以往相同,梳理了下流程图:
- solver接受到恳求后,在Solve办法中调用Bridge的Solve办法,开端解析
- 在bridge中调用Frontend进行解析,这儿的Frontend便是dockerfile
- 在dockerfile Frontend中,又调用了bridge的Solve办法,这一次和第一步不相同的当地在于传入的参数,这一次是传入了现已解析好的Definition
- 创立署理成果,由于这个时候并没有得到真实的构建成果,只是把中间所需求的对象都安排好,比方这儿预备的实践上是frontend.Result.Ref
- 预备好newResultProxy,回来第一步Solve的成果res
- 得到Frontend Solve的成果res后,加载署理成果的Result
- 实践调用的是创立代码成果的回调函数pr.cb – proxyResult.callBack
- 署理成果中实践恳求的是llbBridge.loadResult
- loadResult中先调用的是Load,注意,这儿的Load和咱们之前见到的相同,是将Definition转换为Edge。这儿Edge第一次呈现了
- 真实的Build开端了,而且呈现了一个新的文件 – jobs.go
源码是:
res, bi, err := b.builder.Build(ctx, edge)
b便是llbBridge实例,那b.builder是什么呢? 从上面流程图中可以知道,在第一步时,solver的Solve办法中,调用了Bridge的Solve:
res, err = s.Bridge(j).Solve(ctx, req, sessionID)
这儿是bridge实例化的当地:
func (s *Solver) Bridge(b solver.Builder) frontend.FrontendLLBBridge {
return &llbBridge{
builder: b,
frontends: s.frontends,
resolveWorker: s.resolveWorker,
eachWorker: s.eachWorker,
resolveCacheImporterFuncs: s.resolveCacheImporterFuncs,
cms: map[string]solver.CacheManager{},
sm: s.sm,
}
}
传入的参数便是便是builder,再看这个j
:
j, err := s.solver.NewJob(id)
再继续打开:
func (jl *Solver) NewJob(id string) (*Job, error) {
jl.mu.Lock()
defer jl.mu.Unlock()
if _, ok := jl.jobs[id]; ok {
return nil, errors.Errorf("job ID %s exists", id)
}
pr, ctx, progressCloser := progress.NewContext(context.Background())
pw, _, _ := progress.NewFromContext(ctx) // TODO: expose progress.Pipe()
_, span := trace.NewNoopTracerProvider().Tracer("").Start(ctx, "")
j := &Job{
list: jl,
pr: progress.NewMultiReader(pr),
pw: pw,
progressCloser: progressCloser,
span: span,
id: id,
}
jl.jobs[id] = j
jl.updateCond.Broadcast()
return j, nil
}
可以看到,这儿有一个list,用来存储新创立的job,回来的j中有对应的list引证。
在回来前咱们还看到了jl.updateCond.Broadcast()
,应该是向组内其它job进行广播,有新成员加入了。
绕了一圈回来,咱们找到了真实Build开端的当地 – jobs.Build:
func (j *Job) Build(ctx context.Context, e Edge) (CachedResult, BuildInfo, error) {
if span := trace.SpanFromContext(ctx); span.SpanContext().IsValid() {
j.span = span
}
v, err := j.list.load(e.Vertex, nil, j)
if err != nil {
return nil, nil, err
}
e.Vertex = v
res, err := j.list.s.build(ctx, e)
if err != nil {
return nil, nil, err
}
j.list.mu.Lock()
defer j.list.mu.Unlock()
return res, j.walkBuildInfo(ctx, e, make(BuildInfo)), nil
}
其中有两句招引了袁小白的注意:
- j.list.load
- j.list.s.build
不知道要用什么样的姿态,才干正确打开jobs的load和s.build