OpenDAL


一、关于 OpenDAL

OpenDAL : Open Data Access Layer,愿景是 One Layer, All Storage


功能架构


二、快速入门


Apache OpenDAL™可以通过其Rust核心和多语言绑定轻松集成到不同的软件中。


1、Rust core


OpenDAL的核心是用Rust编程语言实现的。在Rust程序中使用OpenDAL的最方便方法是 将OpenDAL Cargo crate 添加为依赖项。


安装

在您的项目目录中运行以下Cargo命令:

cargo add opendal

或者将以下行添加到您的Cargo. toml:

opendal = "0.46.0"

演示

试试看:

use opendal::Result;
use opendal::layers::LoggingLayer;
use opendal::services;
use opendal::Operator;

#[tokio::main]
async fn main() -> Result<()> {
    // Pick a builder and configure it.
    let mut builder = services::S3::default();
    builder.bucket("test");

    // Init an operator
    let op = Operator::new(builder)?
        // Init with logging layer enabled.
        .layer(LoggingLayer::default())
        .finish();

    // Write data
    op.write("hello.txt", "Hello, World!").await?;

    // Read data
    let bs = op.read("hello.txt").await?;

    // Fetch metadata
    let meta = op.stat("hello.txt").await?;
    let mode = meta.mode();
    let length = meta.content_length();

    // Delete
    op.delete("hello.txt").await?;

    Ok(())
}

2、Java


OpenDAL的Java binding 作为org.apache.opendal:opendal-java:${version}发布到Maven Central。


安装
Maven

一般来说,你可以先添加os-maven-plugin根据你的平台自动检测分类器:

<build>
<extensions>
  <extension>
    <groupId>kr.motd.maven</groupId>
    <artifactId>os-maven-plugin</artifactId>
    <version>1.7.0</version>
  </extension>
</extensions>
</build>

然后将依赖项添加到opendal-java,如下所示:

<dependencies>
<dependency>
  <groupId>org.apache.opendal</groupId>
  <artifactId>opendal-java</artifactId>
  <version>${opendal.version}</version>
</dependency>
<dependency>
  <groupId>org.apache.opendal</groupId>
  <artifactId>opendal-java</artifactId>
  <version>${opendal.version}</version>
  <classifier>${os.detected.classifier}</classifier>
</dependency>
</dependencies>

Gradle

对于Gradle,您可以首先添加com.google.osdetector,用于根据您的平台自动检测分类器:

plugins {
    id "com.google.osdetector" version "1.7.3"
}

然后将依赖项添加到opendal-java,如下所示:

dependencies {
    implementation "org.apache.opendal:opendal-java:$opendal.version"
    implementation "org.apache.opendal:opendal-java:$opendal.version:$osdetector.classifier"
}

Classified library

有关指定分类库的详细信息,请阅读专用说明


演示

试试看:

// Configure service
final Map<String, String> conf = new HashMap<>();
conf.put("root", "/tmp");

// Construct operator
final Operator op = Operator.of("fs", conf);

// Write data
op.write("hello.txt", "Hello, World!").join();

// Read data
final byte[] bs = op.read("hello.txt").join();

// Delete
op.delete("hello.txt").join();

3、Python


OpenDAL的Python绑定作为opendal发布到PyPI存储库。


安装

运行以下命令安装opendal

pip install opendal

演示

试试看:

import opendal
import asyncio

async def main():
    op = opendal.AsyncOperator("fs", root="/tmp")
    await op.write("test.txt", b"Hello World")
    print(await op.read("test.txt"))

asyncio.run(main())

4、Node.js

OpenDAL的Node. js绑定作为opendal发布到NPM注册表opendal


安装

运行以下命令安装opendal

npm install opendal

演示

试试看:

import { Operator } from "opendal";

async function main() {
  const op = new Operator("fs", { root: "/tmp" });
  await op.write("test", "Hello, World!");
  const bs = await op.read("test");
  console.log(new TextDecoder().decode(bs));
  const meta = await op.stat("test");
  console.log(`contentLength: ${meta.contentLength}`);
}

三、愿景


1、Charter

One Layer, All Storage.

一层,全存储。


2、原则

原则是指导性原则。它们指导整个项目的决策。理想情况下,我们一直在做所有的事情。然而,在某些情况下,我们可能会被迫在稍微惩罚一个目标或另一个目标之间做出决定。在这种情况下,我们倾向于支持列表中较早出现的目标,而不是较晚出现的目标(但每种情况都不同)。


0) 开放社区

OpenDAL应该是一个开放的存储库。

OpenDAL是由OpenDAL PMC管理的ASF项目。在ASF,我们相信“社区优于代码”,并坚持阿帕奇的方式。我们的目标是开发OpenDAL来满足我们社区的需求。我们不维护私有版本或包含对他人无用的功能。

例如,OpenDAL更喜欢清晰易读的代码,因为这允许社区中的更多人加入开发。


1) 坚实的基础

OpenDAL应该是一个可靠的存储库。

OpenDAL是用户项目的坚实基础,用户可以信任OpenDAL对现实世界的存储服务执行操作。OpenDAL应该始终专注于构建坚实的基础。

例如,OpenDAL对AWS S3完整的多部分操作执行额外的错误检查,因为S3可能会返回错误以响应200状态代码,即使这可能会增加与“快速访问”冲突的额外成本。


2) 快速访问

OpenDAL应该是一个快速的存储库。

其快速访问确保OpenDAL以零开销实现存储支持。用户可以与OpenDAL集成,而无需担心额外成本。对于任何给定的存储服务,OpenDAL应该与SDK一样快,或者更快。

例如,OpenDAL使用Capability来描述不同服务的功能,并尽可能采用这些服务的本机功能。


3) 对象存储优先

OpenDAL应该是对象存储的第一个库。

OpenDAL确实支持所有存储服务,但它通常针对现代存储服务进行优化。在撰写本文时,我们可以说OpenDAL首先是对象存储。在设计功能时,OpenDAL倾向于优先考虑对象存储的优化。

例如,OpenDAL的Buffer设计主要针对基于HTTP的服务进行了优化,有助于减少额外分配、内存复制和内存使用。


4) 可扩展架构

OpenDAL应该是一个可扩展的存储库。

OpenDAL可以扩展到各种语言、后端和层。每个都是独立的,不依赖于其他的。用户可以组合不同的层,如指标、日志记录、跟踪和重试,并扩展自己的语言、后端和层。

例如,OpenDAL的核心从不依赖于单层的行为或依赖关系。用户可以在给定运算符上堆叠任意数量的层。


3、使用案例

谁是典型的OpenDAL用户?他们将如何使用OpenDAL?


3.1 基础设施建设者

例子:


用例:

  • 构建数据库等存储系统
  • 开发数据处理管道
  • 创建备份和归档解决方案

主要关注点:

  • 坚实的基础:需要保证存储操作的一致性和可预测性
  • 快速访问:需要最小的开销和最佳的性能
  • 为什么:基础设施服务要求可靠性和性能作为基本要求

3.2 应用程序开发人员

例子:


用例:

  • 构建最终用户应用程序
  • 开发CLI工具
  • 创建Web服务

主要关注点:

  • 快速访问:需要高效集成和最佳性能
  • 对象存储优先:受益于现代云存储的优化
  • 为什么:现代应用程序通常使用对象存储并需要响应式性能

3.3 平台开发者

例子:


用例:

  • 构建AI/ML平台
  • 开发云服务
  • 创建开发者工具

主要关注点:

  • 可扩展架构:需要定制和扩展存储能力
  • 坚实的基础:需要可靠的存储操作
  • 为什么:平台需要灵活性来适应各种用例,同时保持可靠性

四、Python API 调用

下面内容翻译自:https://opendal.apache.org/docs/python/opendal.html

import opendal

op = opendal.Operator("fs", root="/tmp")
op.write("test.txt", b"Hello World")
print(op.read("test.txt"))
print(op.stat("test.txt").content_length)

Or using the async API:

import asyncio

async def main():
op = opendal.AsyncOperator("fs", root="/tmp")
await op.write("test.txt", b"Hello World")
print(await op.read("test.txt"))

asyncio.run(main())


class Operator

Operator is the entry for all public blocking APIs

Create a new blocking Operator with the given scheme and options(**kwargs).


  • def layer(self, /, layer): 在现有操作器上添加新层
  • def open(self, /, path, mode): 为给定路径打开一个类文件读取器
  • def read(self, /, path): 将整个路径内容读取为字节
  • def write(self, /, path, bs, **kwargs): 将字节写入给定路径
  • def stat(self, /, path): 直接获取当前路径的元数据,无需缓存
  • def copy(self, /, source, target): 将源复制到目标
  • def rename(self, /, source, target): 重命名文件
  • def remove_all(self, /, path): 移除所有文件
  • def create_dir(self, /, path): 在给定地址创建文件夹
    注:要指示路径是目录,必须在路径中包含 尾随/。如果不这样做,可能会导致OpenDAL返回 NotADirectory错误。
    Behavior
    • 在现有目录上创建将成功。
    • Create dir 总是递归的,工作方式如 mkdir -p
  • def delete(self, /, path): : 删除给定位置
    注:删除位置不存在,不会返回错误。
  • def list(self, /, path): 列出当前目录路径
  • def scan(self, /, path): 以扁平方式列出目录
  • def capability(self, /): 获取操作能力
  • def to_async_operator(self, /): 转换为异步操作器

class AsyncOperator

AsyncOperator 是所有公开异步 APIs 的入口

使用给定的 scheme 和选项(**kwargs)创建一个新的 AsyncOperator


  • def layer(self, /, layer): 在现有操作器上添加新层
  • def open(self, /, path, mode): 为给定路径打开一个类文件读取器
  • def read(self, /, path): 将整个路径内容读取为字节
  • def write(self, /, path, bs, **kwargs): 将字节写入给定路径
  • def stat(self, /, path): 直接获取当前路径的元数据(无缓存)
  • def copy(self, /, source, target): 将源复制到目标
  • def rename(self, /, source, target): 重命名文件
  • def remove_all(self, /, path): 移除所有文件
  • def create_dir(self, /, path): 在给定路径创建目录
    注:要指示路径是目录,必须在路径中包含尾随/。如果不这样做,可能会导致OpenDAL返回“NotADirectory”错误。
    表现:
    • 在现有目录上创建将成功。
    • Create dir 始终是递归的,其工作原理类似于mkdir-p

  • def delete(self, /, path): 删除给定地址
    注:地址不存在,不会报错
  • def list(self, /, path): 列出当前目录路径
  • def scan(self, /, path): 以扁平方式列出目录
  • def presign_stat(self, /, path, expire_second): 为 stat(head) 操作生成预签名,过期时间为 expire_second
  • def presign_read(self, /, path, expire_second): 为读取操作生成预签名,过期时间为 expire_second
  • def presign_write(self, /, path, expire_second): 为写入操作生成预签名,过期时间为 expire_second
  • def capability(self, /):
  • def to_operator(self, /):

class File

一个类似文件的对象。可以用作上下文管理器。


  • def read(self, /, size=None): 读取最多 size 字节,若未指定 size 则读取至文件末尾
  • def readline(self, /, size=None): 从文件中读取一行。换行符(\n)留在字符串的末尾,如果文件不是以换行符结尾,则仅在文件的最后一行省略。如果指定了大小,则最多读取大小为字节的数据。
  • def readinto(self, /, buffer): 将字节读取到预分配的可写缓冲区
  • def write(self, /, bs): 将字节写入文件
  • def seek(self, /, pos, whence=0): 将流位置更改为给定的字节偏移量,whence 默认为 SEEK_SET,可选值为
    • SEEK_SET0 —— 流的开始(默认);偏移量应为零或正
    • SEEK_CUR1 —— 当前流位置;偏移量可能为负
    • SEEK_END2 —— 流的结束;偏移量通常为负值
      返回新的绝对位置。

  • def tell(self, /): 返回当前流位置
  • def close(self, /): 关闭流
  • def flush(self, /): 刷新底层写入器,若文件以读取模式打开则无操作
  • def readable(self, /): 返回流是否可读
  • def writable(self, /): 返回流是否可写
  • def seekable(self, /): 返回流是否可重新定位(仅限可读流)
  • closed: 返回流是否已关闭

class AsyncFile

一个类似文件的异步阅读器。可以用作异步上下文管理器。

  • def read(self, /, size=None): 读取最多 size 字节,若未指定 size 则读取至文件末尾
  • def write(self, /, bs): 将字节写入文件

  • def seek(self, /, pos, whence=0):
    将流位置更改为给定的字节偏移量。偏移是相对于 whence 指示的位置来解释的。whence 的默认值是SEEK_SETwhence的值为:

  • SEEK_SET0 —— 流的开始(默认);偏移量应为零或正

  • SEEK_CUR1 —— 当前流位置;偏移量可能为负

  • SEEK_END2 —— 流的结束;偏移量通常为负值

返回新的绝对位置。


  • def tell(self, /): 返回当前流位置
  • def close(self, /): 关闭流
  • def flush(self, /): 刷新底层写入器,若文件以读取模式打开则无操作
  • def readable(self, /): 返回流是否可读
  • def writable(self, /): 返回流是否可写
  • def seekable(self, /): 返回流是否可重新定位(仅限可读流)
  • closed: 返回流是否已关闭

class Entry


  • path : 入口路径。路径相对于运算符的根。

class EntryMode

  • def is_file(self, /): 返回是否为文件
  • def is_dir(self, /): 返回是否为目录
  • mode: 表示此条目的模式
  • content_md5: 此条目的内容 MD5
  • content_disposition: 此条目的内容描述
  • content_length: 此条目的内容长度
  • content_type: 此条目的内容类型

class PresignedRequest

  • headers : 返回 HTTP 请求头
  • url : 返回请求 URL
  • method : 返回 HTTP 请求方法

class Capability

Capability 用于描述 当前操作符 支持哪些操作。


  • read_with_override_content_type: 操作器是否支持读取时覆盖内容类型
  • write: 操作器是否支持写入
  • rename: 操作器是否支持重命名
  • write_total_max_size: 服务支持的写入总最大大小(例如 Cloudflare D1 支持 1MB)
  • read_with_override_cache_control: 操作器是否支持读取时覆盖缓存控制
  • stat_with_if_none_match: 操作器是否支持带 if-none-match 的 stat
  • write_with_cache_control: 操作器是否支持写入时设置缓存控制
  • delete: 操作器是否支持删除
  • presign_read: 操作器是否支持预签名读取
  • presign_write: 操作器是否支持预签名写入
  • shared: 操作器是否支持共享
  • read_with_if_none_match: 操作器是否支持带 if-none-match 的读取
  • copy: 操作器是否支持复制
  • write_with_content_type: 操作器是否支持写入时设置内容类型
  • write_with_content_disposition: 操作器是否支持写入时设置内容描述
  • list_with_start_after: 后端是否支持从指定位置开始列出
  • list_with_limit: 后端是否支持限制列出数量
  • presign: 操作器是否支持预签名
  • write_multi_min_size: 服务支持的多次写入最小大小(例如 AWS S3 要求至少 5MiB)
  • write_can_append: 操作器是否支持追加写入
  • read_with_if_match: 操作器是否支持带 if-match 的读取
  • read_with_override_content_disposition: 操作器是否支持读取时覆盖内容描述
  • write_can_multi: 操作器是否支持多次写入
  • create_dir: 操作器是否支持创建目录
  • list_with_recursive: 后端是否支持递归列出
  • blocking: 操作器是否支持阻塞操作
  • read: 操作器是否支持读取
  • stat_with_if_match: 操作器是否支持带 if-match 的 stat
  • write_can_empty: 操作器是否支持写入空内容
  • write_multi_max_size: 服务支持的多次写入最大大小(例如 AWS S3 支持 5GiB)
  • stat: 操作器是否支持 stat
  • presign_stat: 操作器是否支持预签名 stat
  • list: 操作器是否支持列出

class WriteOptions`


2025-01-14(二)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程乐园

请我喝杯伯爵奶茶~!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值