docker distritubion源码分析之二:storage driver详解(基于2.6.0版本)
来源:互联网 发布:c语言实验交换字母 编辑:程序博客网 时间:2024/05/01 00:59
在上一篇文章中,分析了docker distribution的启动过程,本篇着重分析distribution使用storage driver的原理。
在NewApp函数中,会初始化app.driver:
app.driver, err = factory.Create(config.Storage.Type(), storageParams)if err != nil {// TODO(stevvooe): Move the creation of a service into a protected// method, where this is created lazily. Its status can be queried via// a health check.panic(err)}
Create函数在registry/storage/factory/factory.go中,它通过config.Storage的Type从driverFactories这个数组缓存中取出相对应的driverFactory,然后调用该driverFactory的Create函数,创建对应的StorageDriver:
func Create(name string, parameters map[string]interface{}) (storagedriver.StorageDriver, error) {driverFactory, ok := driverFactories[name]if !ok {return nil, InvalidStorageDriverError{name}}return driverFactory.Create(parameters)}
而driverFactories数组是通过各个storage driver在启动时自动执行的init()函数中调用factory.Registry函数来初始化的:
func Register(name string, factory StorageDriverFactory) {if factory == nil {panic("Must not provide nil StorageDriverFactory")}_, registered := driverFactories[name]if registered {panic(fmt.Sprintf("StorageDriverFactory named %s already registered", name))}driverFactories[name] = factory}
以s3 driver为例,在main函数执行之前,就会先执行registry/storage/s3-aws/s3.go中的init函数,把自己注册到driverFactories数组中:
func init() {
……// Register this as the default s3 driver in addition to s3awsfactory.Register("s3", &s3DriverFactory{})factory.Register(driverName, &s3DriverFactory{})}
这样,如果在配置文件中配置了s3 driver的话,调用driverFactory.Create函数就会调用到s3-aws/s3.go中的Create函数,进而调用到FromParameters函数:
func (factory *s3DriverFactory) Create(parameters map[string]interface{}) (storagedriver.StorageDriver, error) {return FromParameters(parameters)}
在FromParameters函数中,会根据配置文件中配置的s3的accessKey、regionName、bucket等一系列参数来完成初始化工作,最后调用New(params)函数来创建并返回最终的s3 storage driver:
// New constructs a new Driver with the given AWS credentials, region, encryption flag, and// bucketNamefunc New(params DriverParameters) (*Driver, error) {……d := &driver{S3: s3obj,Bucket: params.Bucket,ChunkSize: params.ChunkSize,Encrypt: params.Encrypt,KeyID: params.KeyID,MultipartCopyChunkSize: params.MultipartCopyChunkSize,MultipartCopyMaxConcurrency: params.MultipartCopyMaxConcurrency,MultipartCopyThresholdSize: params.MultipartCopyThresholdSize,RootDirectory: params.RootDirectory,StorageClass: params.StorageClass,ObjectACL: params.ObjectACL,}return &Driver{baseEmbed: baseEmbed{Base: base.Base{StorageDriver: d,},},}, nil}
这样,就完成了storage driver的初化化工作,driver最终保存在了app.driver变量中。
下面,以manifest的put为例,讲述registry镜像至storage的过程。
通过NewApp函数中的app.register(v2.RouteNameManifest, manifestDispatcher)这段代码,所有manifest的API请求都会registry/handlers/manifests.go中的manifestDispatcher这个函数来处理。在这个函数中,定义了http router的处理handler:
mhandler := handlers.MethodHandler{"GET": http.HandlerFunc(manifestHandler.GetManifest),"HEAD": http.HandlerFunc(manifestHandler.GetManifest),}if !ctx.readOnly {mhandler["PUT"] = http.HandlerFunc(manifestHandler.PutManifest)mhandler["DELETE"] = http.HandlerFunc(manifestHandler.DeleteManifest)}
manifest的PUT请求由manifestHandler.PutManifest来处理。
在PutManifest函数中,首先会调用imh.Repository.Manifests函数生成manifestService:
manifests, err := imh.Repository.Manifests(imh)if err != nil {imh.Errors = append(imh.Errors, err)return}
其中,imh.Repository变量是由registry启动时构建在context中的,这段代码会调用到registry/storage/registry.go中的Manifests函数,返回manifestStore结构体变量,manifestStore实现了manifests.go中的ManifestService接口。
之后,通过调用manifests.Put,调用到registry/storage/manifeststore.go中的Put函数。
_, err = manifests.Put(imh, manifest, options...)if err != nil {
在该Put函数中,会根据manifest的type是schemal1还是schema2,调用其相应的Put函数。以schema2为例,调用到registry/storage/schema2manifesthandler.go中的Put函数。
在这个Put函数中,进一步会调用到ms.blobStore.Put函数:
revision, err := ms.blobStore.Put(ctx, mt, payload)if err != nil {context.GetLogger(ctx).Errorf("error putting payload into blobstore: %v", err)return "", err}
接下来,在registry/storage/blobstore.go中最终会调用到bs.driver.PutContent函数:
return distribution.Descriptor{Size: int64(len(p)),// NOTE(stevvooe): The central blob store firewalls media types from// other users. The caller should look this up and override the value// for the specific repository.MediaType: "application/octet-stream",Digest: dgst,}, bs.driver.PutContent(ctx, bp, p)
如果storage driver是s3,那么会调用到registry/storage/driver/s3-aws/s3.go中的PutContent函数,在这个函数中,最终会调用s3 sdk的PutObject接口,完成数据的上传工作:
// PutContent stores the []byte content at a location designated by "path".func (d *driver) PutContent(ctx context.Context, path string, contents []byte) error {_, err := d.S3.PutObject(&s3.PutObjectInput{Bucket: aws.String(d.Bucket),Key: aws.String(d.s3Path(path)),ContentType: d.getContentType(),ACL: d.getACL(),ServerSideEncryption: d.getEncryptionMode(),SSEKMSKeyId: d.getSSEKMSKeyID(),StorageClass: d.getStorageClass(),Body: bytes.NewReader(contents),})return parseError(path, err)}
0 0
- docker distritubion源码分析之二:storage driver详解(基于2.6.0版本)
- docker distritubion源码分析之一:启动过程(基于2.6.0版本)
- Docker源码分析(二)之Docker Client
- Docker之几种storage-driver比较
- docker storage driver compare
- Docker storage driver 选择
- bt客户端源码分析之二: Storage 类
- BT客户端源码分析之二:Storage 类
- Docker之理解image,container和storage-driver
- docker最初版本源码分析
- Docker源码分析之容器日志处理与log-driver实现
- Docker源码分析(四):Docker Daemon之NewDaemon实现
- Docker源码分析(四):Docker Daemon之NewDaemon实现
- Docker源码分析(三)之Docker Daemon
- Docker源码分析(四)之Docker Server
- Docker源码分析(四):Docker Daemon之NewDaemon实现
- Spark源码分析之-Storage模块
- Spark源码分析之-Storage模块
- c++自定义队列
- 设置欢迎界面设置
- 轻松自动化---selenium-webdriver(python) (十二)--转自虫师
- Java代码编译和执行的整个过程
- SpringMVC 使用@ResponseBody返回json 中文乱码
- docker distritubion源码分析之二:storage driver详解(基于2.6.0版本)
- 前端培训班出身——吐槽下16年的艰辛
- 信号傅立叶变换后实际频谱图(Matlab)
- Javascript 中的神器——Promise
- (转)jQuery height()、innerHeight()、outerHeight()函数的区别详解
- 随机梯度下降算法学习心得
- Windows7旗舰版+Visual Studio2013的OpenGl配置
- Reactive Programming with RxJava-Chapter2:Reactive Extensions
- var a=b=5;