remotes/docker/schema1: back off on locked ref

To allow concurrent pull of images of the v1 persuasion, we need to
backoff when multiple pullers are trying to operate on the same
resource. The back off logic is ported to v1 pull to match the behavior
for other images.

A little randomness is also added to the backoff to prevent thundering
herd and to reduce expected recovery time.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
Stephen J Day 2017-10-30 15:40:54 -07:00
parent 5fb3a0e0cf
commit 8eee47cf82
No known key found for this signature in database
GPG Key ID: 67B3DED84EDC823F
2 changed files with 20 additions and 5 deletions

View File

@ -9,6 +9,7 @@ import (
"fmt"
"io"
"io/ioutil"
"math/rand"
"strings"
"sync"
"time"
@ -215,13 +216,26 @@ func (c *Converter) fetchManifest(ctx context.Context, desc ocispec.Descriptor)
func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) error {
log.G(ctx).Debug("fetch blob")
ref := remotes.MakeRefKey(ctx, desc)
calc := newBlobStateCalculator()
var (
ref = remotes.MakeRefKey(ctx, desc)
calc = newBlobStateCalculator()
retry = 16
)
tryit:
cw, err := c.contentStore.Writer(ctx, ref, desc.Size, desc.Digest)
if err != nil {
if !errdefs.IsAlreadyExists(err) {
if errdefs.IsUnavailable(err) {
select {
case <-time.After(time.Millisecond * time.Duration(rand.Intn(retry))):
if retry < 2048 {
retry = retry << 1
}
goto tryit
case <-ctx.Done():
return err
}
} else if !errdefs.IsAlreadyExists(err) {
return err
}

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io"
"math/rand"
"time"
"github.com/containerd/containerd/content"
@ -84,7 +85,7 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc
// of writer and abort if not updated recently.
select {
case <-time.After(time.Millisecond * time.Duration(retry)):
case <-time.After(time.Millisecond * time.Duration(rand.Intn(retry))):
if retry < 2048 {
retry = retry << 1
}