lakeFS Python SDK StagingApi 详解:两阶段对象上传与暂存链接机制
数据工程数据湖大数据对象存储后端【免费下载链接】lakeFSlakeFS - Data version control for your data lake | Git for data项目地址https://gitcode.com/gh_mirrors/la/lakeFS点击查看免费下载导读StagingApi 是 lakeFS Python SDKlakefs_sdk中负责暂存staging写入路径的核心 API它通过get_physical_address与link_physical_address两个方法把上传数据对象到对象存储和把对象登记到 lakeFS 仓库两个动作解耦从而在不经过 lakeFS 服务器中转数据的情况下安全写入对象。阅读完本文你将掌握 lakeFS 暂存写入的完整工作流、StagingLocation/StagingMetadata/ObjectStats三个关键模型的字段语义、presign与 ETag 条件写入的实战用法以及服务端与 SDK 中的对应实现细节。一、StagingApi 概览两个方法完成一次暂存写入StagingApi 的全部端点都挂在/api/v1之下共两个方法对应两条 HTTP 请求路径方法HTTP 请求描述get_physical_addressGET /repositories/{repository}/branches/{branch}/staging/backing生成一个客户端可以直接向其上传对象的地址link_physical_addressPUT /repositories/{repository}/branches/{branch}/staging/backing把该物理地址上的对象与仓库内的一个路径关联产生一次未提交uncommitted变更方法签名定义在 clients/python/lakefs_sdk/api/staging_api.py 中def get_physical_address(self, repository, branch, path, presignNone, **kwargs) - StagingLocation def link_physical_address(self, repository, branch, path, staging_metadata, if_none_matchNone, if_matchNone, **kwargs) - ObjectStats调用示例、参数表与返回类型详见 clients/python/docs/StagingApi.md服务端的行为契约定义在 api/swagger.yml 的/repositories/{repository}/branches/{branch}/staging/backing路径下operationId 分别为getPhysicalAddress与linkPhysicalAddress。1.1 两种认证方式两个方法都支持三种认证SDK 生成的客户端在 staging_api.py 中固定声明_auth_settings [basic_auth, cookie_auth, jwt_token]basic_authHTTP Basic 认证配置username与passwordcookie_authAPI KeyCookie通过configuration.api_key[cookie_auth]设置需要前缀时可用configuration.api_key_prefix[cookie_auth] Bearerjwt_tokenBearer JWT通过Configuration(access_token...)配置。1.2 为什么需要暂存两步lakeFS 的对象存储blockstore直接面向 S3、GCS、Azure Blob 等后端。两步设计的好处是数据不经过 lakeFS 服务器客户端直接向对象存储上传数据或直接引用外部已存在的对象地址避免服务器吞吐成为瓶颈元数据与数据分离上传完成后再通过link_physical_address把对象的 checksum、大小、路径等元数据登记进仓库形成未提交变更随后可用Commit固化支持外部地址link_physical_address允许关联仓库存储命名空间之外的地址为数据导入、跨仓库引用等场景提供可能。二、get_physical_address生成上传地址2.1 请求参数参数类型必填说明repositorystr是仓库名称路径参数branchstr是分支名称路径参数pathstr是相对分支的对象路径查询参数presignbool否是否生成预签名 URL2.2 返回模型 StagingLocation返回类型为StagingLocation定义在 clients/python/lakefs_sdk/models/staging_location.py共三个字段字段类型说明physical_addressstr对象在后端对象存储上的原生 URI如s3://...、gs://...或者当presigntrue时为可供 HTTP GET/PUT 使用的 URLpresigned_urlstr仅当请求传presigntrue时返回是可直接用于上传的预签名 URLpresigned_url_expiryint若存在且非零表示physical_address作为预签名 URL 的过期 Unix Epoch 时间该时间可能短于预签名 URL 本身的生命周期例如认证 token 即将过期时2.3 完整调用示例import time import os import lakefs_sdk from lakefs_sdk.models.staging_location import StagingLocation from lakefs_sdk.rest import ApiException from pprint import pprint # 配置认证Basic configuration lakefs_sdk.Configuration( usernameos.environ[USERNAME], passwordos.environ[PASSWORD] ) # 或配置 JWT # configuration lakefs_sdk.Configuration(access_tokenos.environ[BEARER_TOKEN]) with lakefs_sdk.ApiClient(configuration) as api_client: api_instance lakefs_sdk.StagingApi(api_client) repository repo_name branch main path data/part-0001.parquet # 相对分支的路径 presign True api_response api_instance.get_physical_address(repository, branch, path, presignpresign) pprint(api_response)HTTP 请求头Accept: application/json无请求体。状态码200成功返回暂存物理地址、400、401、404、429其余为500内部错误。2.4 服务端实现在 pkg/api/controller.go 的GetPhysicalAddress处理器中服务端完成以下工作鉴权要求WriteObjectAction权限controller.go通过Catalog.GetAddressWithSignature为对象生成带签名的物理地址通过BlockAdapter.ResolveNamespace把相对地址解析为完整对象存储 URI若presigntrue调用BlockAdapter.GetPreSignedURL(..., block.PreSignModeWrite, )生成写入型预签名 URL并填充PresignedUrl与PresignedUrlExpiry字段controller.go。三、link_physical_address把物理地址与路径关联3.1 请求参数参数类型必填说明repositorystr是仓库名称branchstr是分支名称pathstr是相对分支的对象路径staging_metadataStagingMetadata是上传对象的信息JSON 请求体if_none_matchstr否设为*表示仅当该路径尚无对象时才允许写入其它值不被支持if_matchstr否设为对象的 ETag表示仅当对象当前 ETag 与给定值匹配时才允许操作if_none_match与if_match在 SDK 生成代码中分别映射为 HTTP 头If-None-Match与If-Match见 staging_api.py二者提供原子化的写入条件用于避免并发覆盖或重复写入。3.2 请求体模型 StagingMetadataStagingMetadata定义在 clients/python/lakefs_sdk/models/staging_metadata.py字段如下字段类型必填说明stagingStagingLocation是上传地址通常直接回传get_physical_address的结果checksumstr是对象内容在后端存储上的唯一标识通常是 ETagsize_bytesint是对象字节大小user_metadatadict[str, str]否用户自定义元数据content_typestr否对象媒体类型mtimeint否Unix Epoch 秒数服务端可能忽略forcebool否默认False是否强制覆盖写入3.3 返回模型 ObjectStatslink_physical_address成功返回ObjectStats200 状态码定义在 clients/python/lakefs_sdk/models/object_stats.py。关键字段字段类型说明pathstr对象路径path_typestr枚举common_prefix或objectphysical_addressstr对象在后端对象存储上的位置原生 URIs3://...、gs://...等或presigntrue时的 HTTP URLphysical_address_expiryint预签名 URL 过期时间可选checksumstr对象校验和size_bytesint字节数mtimeintUnix Epoch 秒数metadatadict[str, str]对象元数据content_typestr对象媒体类型3.4 完整调用示例import os import lakefs_sdk from lakefs_sdk.models.object_stats import ObjectStats from lakefs_sdk.models.staging_metadata import StagingMetadata from lakefs_sdk.rest import ApiException from pprint import pprint configuration lakefs_sdk.Configuration( usernameos.environ[USERNAME], passwordos.environ[PASSWORD] ) with lakefs_sdk.ApiClient(configuration) as api_client: api_instance lakefs_sdk.StagingApi(api_client) repository repo_name branch main path data/part-0001.parquet # 第一步取得上传地址假定此前已完成上传并拿到 ETag staging_location lakefs_sdk.StagingLocation( physical_addresss3://.../..., presigned_urlhttps://..., ) staging_metadata lakefs_sdk.StagingMetadata( stagingstaging_location, checksum2e9ec317e197e02e4264d128c2e7e681, # 后端返回的 ETag size_bytes1048576, user_metadata{team: data-eng}, content_typeapplication/octet-stream, mtimeNone, forceFalse, ) if_none_match * # 仅当路径尚无对象时允许写入 if_match None # 或传入对象当前 ETag 做条件写入 api_response api_instance.link_physical_address( repository, branch, path, staging_metadata, if_none_matchif_none_match, if_matchif_match, ) pprint(api_response)HTTP 请求头Content-Type: application/jsonAccept: application/json。状态码语义状态码含义200成功返回对象元数据ObjectStats400校验错误如 checksum 为空401未认证403无权限404资源不存在409与某次提交冲突返回StagingLocation供重试412前置条件失败If-None-Match/If-Match不满足429请求过多501未实现0/ 默认内部服务器错误3.5 服务端实现controller.go 的LinkPhysicalAddress处理器揭示了完整流程鉴权要求WriteObjectActioncontroller.go校验请求体中的 blockstore 类型与仓库存储配置一致若addressType catalog.AddressTypeRelative地址位于仓库存储命名空间内调用Catalog.VerifyLinkAddress校验该地址确由 lakeFS 签发controller.go命名空间之外的地址则直接接受使用httputil.StripQuotesAndSpaces清洗 ETag若为空则返回 400controller.go通过catalog.NewDBEntryBuilder()构造对象条目路径、物理地址、大小、checksum、ContentType、元数据并用apiutil.BuildConditionFromParams将if_match/if_none_match转换为 graveler 条件controller.goCatalog.CreateEntry(..., graveler.WithForce(...), graveler.WithCondition(...))写入未提交条目controller.go。这里的CreateEntry走的是 graveler 层的 staging 管理pkg/graveler/staging/目录下的实现如 pkg/graveler/staging/manager_test.go即负责未提交staged数据的读写最终这些暂存条目会在 Commit 时被固化。四、完整实战预签名两段式上传结合presigntrue与两个 StagingApi 方法可以实现不经过 lakeFS 服务器的直传流程参考官方端到端测试 esti/presign_test.go 中的preSignGetPhysicalAddress用例获取预签名上传地址GET .../staging/backing?pathfoo/uploadedpresigntrue得到StagingLocation含presigned_url直传数据向presigned_url发起 HTTPPUT携带对象内容与Content-Type从响应头Etag取得校验和链接对象PUT .../staging/backing请求体StagingMetadata中staging回传第一步的结果、checksum填 ETag、size_bytes填实际字节数读取验证GET Object拉回对象内容确认与上传内容一致。Python 代码骨架import requests # 1. 获取预签名地址 loc api_instance.get_physical_address(repo, branch, foo/uploaded, presignTrue) # 2. 直传对象到预签名 URL resp requests.put(loc.presigned_url, dataobj_content, headers{Content-Type: application/octet-stream}) etag resp.headers.get(Etag) # 3. 链接物理地址与路径 stats api_instance.link_physical_address( repo, branch, foo/uploaded, staging_metadatalakefs_sdk.StagingMetadata( stagingloc, checksumetag, size_byteslen(obj_content), content_typeapplication/octet-stream, ), )4.1 高阶客户端中的实际用法在更上层的 Python 封装clients/python-wrapper中预签名上传正是依赖 StagingApi 完成的。见 clients/python-wrapper/lakefs/object.py 的_upload_presign实现staging_location self._client.sdk_client.staging_api.get_physical_address( self._obj.repo, self._obj.ref, self._obj.path, True) url staging_location.presigned_url # ... 直接向 url 发起 PUT提取 ETag ... staging_metadata StagingMetadata(stagingstaging_location, size_bytessize_bytes, checksumetag, user_metadataself.metadata, content_typeself.content_type, mtimeNone) if_none_match * if self._mode.startswith(x) else None return self._client.sdk_client.staging_api.link_physical_address( self._obj.repo, self._obj.ref, self._obj.path, staging_metadatastaging_metadata, if_none_matchif_none_match)注意两个细节写入模式为x排他创建时自动设置if_none_match*服务器返回 412 时映射为ObjectExistsExceptionAzure blockstore 场景下还会额外添加x-ms-blob-type: BlockBlob头object.py。对应的单测见 clients/python-wrapper/tests/utests/test_object.py。Go 侧参考实现位于 pkg/api/helpers/upload.go 的uploadObject它同样先调用getPhysicalAddressPresigntrue用http.MethodPut直传再以LinkPhysicalAddressJSONRequestBody关联元数据若响应为 409提交冲突返回ErrConflict供上层重试。五、条件写入与冲突处理最佳实践排他创建不存在才写传if_none_match*服务端仅在路径无对象时写入返回 412 表示对象已存在这是实现对象级原子创建的推荐手段。乐观并发更新ETag 匹配才写传if_match当前ETag仅当对象 ETag 与给定值一致时允许覆盖避免读-改-写之间的并发丢失更新。提交冲突409链接发生在某次提交进行时可能返回 409 并携带新的StagingLocation客户端应重新执行获取地址 → 上传 → 链接流程Go 客户端在 upload.go 中实现了带重试的上传循环。外部地址链接link_physical_address接受仓库存储命名空间之外的物理地址但命名空间内的地址会被校验签名防止伪造 lakeFS 地址。六、小结StagingApi 是 lakeFS 写入路径的关键拼图get_physical_address解决往哪传link_physical_address解决传完怎么登记。配合presign与 ETag 条件头可以在保证原子性与并发安全的前提下实现高吞吐的对象直传。若要进一步探索API 契约查看 api/swagger.yml 中staging标签下的getPhysicalAddress/linkPhysicalAddress定义服务端实现阅读 pkg/api/controller.go端到端验证运行或阅读 esti/presign_test.go上层封装参考 clients/python-wrapper/lakefs/object.py 与 pkg/api/helpers/upload.go。赞分享数据工程数据湖大数据对象存储后端【免费下载链接】lakeFSlakeFS - Data version control for your data lake | Git for data项目地址https://gitcode.com/gh_mirrors/la/lakeFS点击查看免费下载相关推荐lakeFS Rust SDK 的 StagingMetadata暂存对象元数据模型与两段式上传原理lakeFS Rust SDK 的 StagingMetadata暂存对象元数据模型与两段式上传原理 StagingMetadata 是 lakeFS 数据版数据工程数据湖大数据对象存储后端lakeFS Python SDK StagingLocation 模型详解staging 暂存上传与预签名 URL 机制lakeFS Python SDK StagingLocation 模型详解staging 暂存上传与预签名 URL 机制 在 lakeFS 的数据版本控制体数据工程数据湖大数据对象存储后端lakeFS 对象暂存上传核心模型 StagingLocation 深度解析lakeFS 对象暂存上传核心模型 StagingLocation 深度解析 本篇技术指南围绕 lakeFSGit for Data 数据湖版本控制系统的对数据工程数据湖大数据对象存储后端上一篇HTTP API Design GuideREST 路径中支持非 ID 解引用Non-ID Dereferencing的实践下一篇清算热力图与爆仓价位分析实战指南基于 ai_quant_trade 的杠杆清算信号框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考