168 lines
4.3 KiB
Markdown
168 lines
4.3 KiB
Markdown
# MinioStorage 使用指南
|
||
|
||
## 概述
|
||
|
||
`MinioStorage` 提供 APK 云存储功能,支持通过 `MINIO_ENABLED` 配置开关控制是否启用。
|
||
|
||
## 配置开关
|
||
|
||
在配置文件(如 `config/local.yaml` 或环境变量)中设置:
|
||
|
||
```yaml
|
||
# 启用 Minio(默认)
|
||
MINIO_ENABLED: true
|
||
MINIO_ENDPOINT: "minio.example.com:9000"
|
||
MINIO_ACCESS_KEY: "your-access-key"
|
||
MINIO_SECRET_KEY: "your-secret-key"
|
||
MINIO_BUCKET: "apk-storage"
|
||
MINIO_SECURE: false
|
||
|
||
# 禁用 Minio(跨团队部署或无 Minio 服务时)
|
||
MINIO_ENABLED: false
|
||
```
|
||
|
||
## 使用方式
|
||
|
||
### 方式 1:直接实例化(不推荐)
|
||
|
||
```python
|
||
from apk_cloud.storage import MinioStorage
|
||
|
||
try:
|
||
storage = MinioStorage()
|
||
# 使用 storage 进行操作
|
||
except RuntimeError as e:
|
||
print(f"Minio 功能已禁用: {e}")
|
||
# 降级到直接下载模式
|
||
```
|
||
|
||
**缺点**:当 `MINIO_ENABLED=False` 时会抛出异常,需要额外的异常处理。
|
||
|
||
### 方式 2:工厂方法(推荐)
|
||
|
||
```python
|
||
from apk_cloud.storage import MinioStorage
|
||
|
||
storage = MinioStorage.create()
|
||
if storage is None:
|
||
print("Minio 已禁用,使用直接下载模式")
|
||
# 执行降级逻辑,例如直接从 APK 源下载
|
||
else:
|
||
# 使用 storage 进行 Minio 操作
|
||
storage.push_download_queue(tasks)
|
||
```
|
||
|
||
**优点**:无需异常处理,代码更简洁清晰。
|
||
|
||
### 方式 3:预检查
|
||
|
||
```python
|
||
from apk_cloud.storage import MinioStorage
|
||
|
||
if MinioStorage.is_enabled():
|
||
storage = MinioStorage()
|
||
# 使用 Minio 功能
|
||
else:
|
||
# 使用降级方案
|
||
print("Minio 已禁用,跳过云存储同步")
|
||
```
|
||
|
||
## 降级方案
|
||
|
||
当 `MINIO_ENABLED=False` 时,推荐的降级方案:
|
||
|
||
### 1. APK 直接下载模式
|
||
|
||
配置 `APK_DOWNLOAD_MODE='direct'`,直接从 APK 源(如 Google Play、APKPure)下载到本地,不经过 Minio 中转。
|
||
|
||
```python
|
||
from config import APK_DOWNLOAD_MODE
|
||
|
||
if APK_DOWNLOAD_MODE == 'direct':
|
||
# 直接下载到 worker 本地
|
||
apk_path = download_apk_from_source(package_name)
|
||
else:
|
||
# 从 Minio 下载
|
||
storage = MinioStorage.create()
|
||
if storage:
|
||
apk_path = storage.download_apk(package_name, manifest, dest_dir)
|
||
```
|
||
|
||
### 2. 队列同步跳过
|
||
|
||
当 Minio 禁用时,跳过下载队列的云端同步,改为本地队列管理:
|
||
|
||
```python
|
||
storage = MinioStorage.create()
|
||
if storage:
|
||
# 同步云端队列
|
||
storage.push_download_queue(tasks)
|
||
else:
|
||
# 使用本地队列文件
|
||
with open("local_queue.json", "w") as f:
|
||
json.dump(tasks, f)
|
||
```
|
||
|
||
### 3. 结果存储本地化
|
||
|
||
下载结果存储到本地文件系统,而非 Minio:
|
||
|
||
```python
|
||
storage = MinioStorage.create()
|
||
if storage:
|
||
storage.write_download_result(package_name, result)
|
||
else:
|
||
# 本地存储
|
||
result_path = f"results/{package_name}.json"
|
||
os.makedirs("results", exist_ok=True)
|
||
with open(result_path, "w") as f:
|
||
json.dump(result, f)
|
||
```
|
||
|
||
## 向后兼容性
|
||
|
||
- **默认行为不变**:`MINIO_ENABLED` 默认为 `True`,现有代码无需修改即可继续使用。
|
||
- **旧代码兼容**:直接调用 `MinioStorage()` 的旧代码仍然有效(启用时),禁用时会抛出友好的错误提示。
|
||
- **新代码建议**:新代码推荐使用 `MinioStorage.create()` 工厂方法,以便更好地处理禁用场景。
|
||
|
||
## 部署场景示例
|
||
|
||
### 场景 1:单团队部署(有 Minio 服务)
|
||
|
||
```yaml
|
||
# config/prod.yaml
|
||
MINIO_ENABLED: true
|
||
MINIO_ENDPOINT: "minio.internal:9000"
|
||
APK_DOWNLOAD_MODE: "minio" # 通过 Minio 分发 APK
|
||
```
|
||
|
||
### 场景 2:跨团队部署(无 Minio 服务)
|
||
|
||
```yaml
|
||
# config/prod.yaml
|
||
MINIO_ENABLED: false
|
||
APK_DOWNLOAD_MODE: "direct" # 每个 worker 直接下载
|
||
```
|
||
|
||
### 场景 3:开发环境(可选 Minio)
|
||
|
||
```yaml
|
||
# config/local.yaml
|
||
MINIO_ENABLED: false # 本地开发不依赖 Minio
|
||
APK_DOWNLOAD_MODE: "direct"
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
### Q: 为什么不用环境变量 `MINIO_ENDPOINT` 空值判断?
|
||
|
||
A: 配置项可能因网络分区、配置错误等原因为空,不能作为功能开关的可靠信号。显式的 `MINIO_ENABLED` 开关语义更清晰,避免歧义。
|
||
|
||
### Q: 禁用 Minio 后,已有的云端数据会丢失吗?
|
||
|
||
A: 不会。禁用仅影响新操作,Minio 服务端的数据保持不变。重新启用后可继续访问。
|
||
|
||
### Q: 可以在运行时动态切换吗?
|
||
|
||
A: 不建议。`MINIO_ENABLED` 应在启动时通过配置文件或环境变量设置,运行时修改可能导致状态不一致。
|