lakefs 对象模型-对象存储
了解lakefs 的对象模型对于我们更好的学习lakefs 是比较重要的
lakefs 对象存储
对象存储借鉴自s3,包含一些特性
- 包含一些内容,无限大小以及格式
- 一些元数据,大小,创建时间,时间戳,内容检查值,
- 一些用户自定义的元数据
和其他对象存储类似,lakfe 的对象是不可变的,不能重写,可以被整体的替换以及删除,但是不能修改
路径是一个可读的url,典型是utf-8 编码的,lakefs 路径与对象的映射是基于特定的规则(lakefs 协议)
说明
lakefs 的对象存储是自己基于golang 的http包,写的s3 gateway层处理,具体代码在pkg/gateway/handler.go 中
对于不同操作的包装可以参考pkg/gateway/operations 里边包含了get,put,delete 等操作,也是值得学习的包含了如何
编写一个s3 gateway服务,如果想偷懒的话,minio 的gateway 是一个可以直接拿来使用的比如juicefs 就使用的minio
对于lakefs 的http api 服务以及s3 gateway 服务lakefs 是复用了一个链接,对于处理的时候基于特征进行简单路由
server := &http.Server{
Addr: cfg.GetListenAddress(),
Handler: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
// If the request has the S3 GW domain (exact or subdomain) - or carries an AWS sig, serve S3GW
if httputil.HostMatches(request, cfg.GetS3GatewayDomainNames()) ||
httputil.HostSubdomainOf(request, cfg.GetS3GatewayDomainNames()) ||
sig.IsAWSSignedRequest(request) {
s3gatewayHandler.ServeHTTP(writer, request)
return
}
// Otherwise, serve the API handler
apiHandler.ServeHTTP(writer, request)
}),
}
包装的ServeHttp
func OperationHandler(sc *ServerContext, handler operations.AuthenticatedOperationHandler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
o := ctx.Value(ContextKeyOperation).(*operations.Operation)
perms, err := handler.RequiredPermissions(req)
if err != nil {
_ = o.EncodeError(w, req, gatewayerrors.ErrAccessDenied.ToAPIErr())
return
}
authOp := authorize(w, req, sc.authService, perms)
if authOp == nil {
return
}
handler.Handle(w, req, authOp)
})
}
参考s3 response 响应处理,基于EncodeError 以及EncodeResponse方法
func (controller *ListBuckets) Handle(w http.ResponseWriter, req *http.Request, o *AuthorizedOperation) {
o.Incr("list_repos")
repos, _, err := o.Catalog.ListRepositories(req.Context(), -1, "", "")
if err != nil {
_ = o.EncodeError(w, req, errors.Codes.ToAPIErr(errors.ErrInternalError))
return
}
// assemble response
buckets := make([]serde.Bucket, len(repos))
for i, repo := range repos {
buckets[i] = serde.Bucket{
CreationDate: serde.Timestamp(repo.CreationDate),
Name: repo.Name,
}
}
// write response
o.EncodeResponse(w, req, serde.ListAllMyBucketsResult{
Buckets: serde.Buckets{Bucket: buckets},
}, http.StatusOK)
}