原则
- 业务和业务之间的文件交互使用接口处理;
- 业务内部各服务之间的文件交互使用对象存储,例如MinIO;
- 每个业务使用自己的对象存储账号、对象存储桶,不同业务间的账号及桶不互通;
- 业务负责自己的文件数据管理,例如从其它业务拿到的数据是否缓存、是否定期清理;
文件接口设计规范
- 每个业务必须有一个文件服务file;
- GET请求方式;
- 接口路径由 /file/file_address 组成,file_address可以是文件ID(例如UUID),也可以是随机码(临时路径,隐藏真实文件信息,控制访问时效),但不可以是对象存储桶路径;
- 接口路径使用小写字母;
- 单词间使用下划线分割;
- 文件接口应有时效控制机制;
MinIO开发文档
太养业务,MinIO对象存储访问信息
endpoint: 192.168.10.136:9000
bucket_name: taiyang
access_key: taiyang
secret_key: Ty123456
太财业务,MinIO对象存储访问信息
endpoint: 192.168.10.136:9000
bucket_name: taicai
access_key: taicai
secret_key: Tc123456
算法业务,MinIO对象存储访问信息
endpoint: 192.168.10.136:9000
bucket_name: alg
access_key: alg
secret_key: Aa123456
MinIO文档
https://docs.min.io/docs/
MinIO Java SDK
https://docs.min.io/docs/java-client-quickstart-guide.html
MinIO Java SDK Examples
https://github.com/minio/minio-java/tree/release/examples
MinIO Python SDK
https://docs.min.io/docs/python-client-quickstart-guide.html
MinIO Python SDK Examples
https://github.com/minio/minio-py/tree/release/examples
MinIO对象存储客户端设计规范
客户端封装成一个class;
客户端class包含函数read,需要参数path(对象存储桶内的路径),返回字节数据流;
客户端class包含函数write,需要参数path(对象存储桶内的路径)、data(需要写入的数据,Java可以根据data数据类型实现多个write重载函数,Python可以根据data数据类型实现不同的逻辑分支);
代码示例
from minio import Minio
from typing import Union
import io
import json
import numpy as np
from PIL import Image
from ..config import settings
class KVIO:
def __init__(self):
self.client = Minio(
endpoint=settings.MINIO_ENDPOINT,
access_key=settings.MINIO_ACCESS_KEY,
secret_key=settings.MINIO_SECRET_KEY,
secure=False,
)
self.bucket_name = settings.MINIO_BUCKET_NAME
def read(self, path: str) -> bytes:
path = path.rstrip("/")
data = self.client.get_object(self.bucket_name, path).read()
return data
def read_as_str(self, path: str) -> str:
data = self.read(path)
return data.decode()
def read_as_json(self, path: str) -> Union[dict, list]:
data = self.read(path)
return json.loads(data)
def read_as_numpy(self, path: str) -> np.ndarray:
data = self.read(path)
return np.frombuffer(data)
def read_as_image(self, path: str) -> Image.Image:
data = self.read(path)
return Image.open(io.BytesIO(data))
def write(self, path: str, data: Union[bytes, str, dict, list, tuple, np.ndarray, Image.Image]):
path = path.rstrip("/")
if isinstance(data, bytes):
with io.BytesIO(data) as fo:
self.client.put_object(self.bucket_name, path, fo, fo.getbuffer().nbytes)
elif isinstance(data, str):
with io.BytesIO(data.encode()) as fo:
self.client.put_object(self.bucket_name, path, fo, fo.getbuffer().nbytes)
elif isinstance(data, (dict, list, tuple)):
with io.BytesIO(json.dumps(data, ensure_ascii=False).encode()) as fo:
self.client.put_object(self.bucket_name, path, fo, fo.getbuffer().nbytes)
elif isinstance(data, np.ndarray):
with io.BytesIO(data.tobytes()) as fo:
self.client.put_object(self.bucket_name, path, fo, fo.getbuffer().nbytes)
elif isinstance(data, Image.Image):
with io.BytesIO() as fo:
data.save(fo, 'png')
fo.seek(0)
self.client.put_object(self.bucket_name, path, fo, fo.getbuffer().nbytes)
else:
raise Exception(f'不支持的数据类型 [{type(data)}]')
评论已关闭