saas应用用seaweed解决文件隔离存储问题

架构核心:为多租户设计存储策略

在SaaS环境中,不同租户的数据隔离至关重要。SeaweedFS主要通过 ​​Collection(集合)​​ 概念来实现这一目标。您可以将每个租户视为一个独立的Collection,这样他们的文件不仅在逻辑上隔离,在物理存储上也会被尽可能分开,非常安全。 整体的工作流程可以概括为:您的应用接收到租户的文件上传请求后,首先向SeaweedFS的Master节点为该租户的Collection申请一个文件ID(FID),然后使用这个FID将文件内容存储到Volume节点。当需要访问文件时,再通过FID从Volume节点读取。

部署SeaweedFS服务

您可以根据实际环境选择以下任一方式部署SeaweedFS。

特性单机模式(适合开发测试)集群模式(适合生产环境)
​部署复杂度​低,一条命令启动所有服务中,需分别配置和启动多个节点
​可靠性​较低,单点故障风险高,具备高可用和容错能力
​扩展性​优秀,可水平扩展

方式一:快速单机部署(开发测试)

在服务器上,使用weed server命令可以一键启动包含Master、Volume和Filer服务的单机环境。

# 创建数据目录
sudo mkdir -p /data/seaweedfs
# 启动服务(绑定所有IP,方便外网访问)
weed server -dir=/data/seaweedfs -master.port=9333 -volume.port=8080 -ip=0.0.0.0 -filer -filer.port=8888

启动后,您可以访问 http://你的服务器IP:9333查看Master管理界面,访问 http://你的服务器IP:8888使用Filer的Web界面。

方式二:生产级集群部署

对于生产环境,建议将服务拆分开,以提高可用性。

  1. ​启动Master节点​​(负责协调元数据) # 在主机1上执行 weed master -mdir=/data/mdata -port=9333 -ip=master_server_ip
  2. ​启动Volume节点​​(负责实际文件存储) # 在存储节点1上执行(可在一台或多台服务器上启动多个实例) weed volume -dir=/data/vdata1 -max=100 -mserver=master_server_ip:9333 -port=8080 -dataCenter=dc1 -rack=rack1 # 在存储节点2上执行 weed volume -dir=/data/vdata2 -max=100 -mserver=master_server_ip:9333 -port=8080 -dataCenter=dc1 -rack=rack1
  3. ​启动Filer服务​​(提供更易用的文件目录接口) weed filer -master=master_server_ip:9333 -port=8888

方式三:使用Docker Compose(推荐用于容器化部署)

编写一个docker-compose.yml文件可以更便捷地管理服务。

version: '3.9'
services:
  master:
    image: chrislusf/seaweedfs
    ports:
      - "9333:9333"
      - "19333:19333"
    command: "master -ip=master"  # 使用容器名作为IP

  volume:
    image: chrislusf/seaweedfs
    ports:
      - "8080:8080"
    command: 'volume -mserver="master:9333" -port=8080'
    depends_on:
      - master

  filer:
    image: chrislusf/seaweedfs
    ports:
      - "8888:8888"
    command: 'filer -master="master:9333"'
    depends_on:
      - master
      - volume

使用 docker-compose up -d启动所有服务。

为SaaS应用配置租户隔离

如前所述,​​使用Collection为每个租户创建独立的命名空间​​是实现隔离的关键。您可以在上传文件时,通过指定collection参数来实现。 例如,当租户“company_a”上传文件时,您的应用后端需要执行两步操作:

  1. ​向Master申请文件ID(FID)​​: curl "http://<seaweedfs_master>:9333/dir/assign?collection=tenant_company_a"返回结果示例: { "fid": "5,0abc1234de", "url": "172.20.0.3:8080", "publicUrl": "your_volume_server_public_ip:8080", "count": 1 }
  2. ​使用返回的URL和FID上传文件​​: curl -X PUT -F file=@/path/to/local/file.jpg http://172.20.0.3:8080/5,0abc1234de

在应用中进行文件操作

以下是基于租户Collection进行文件操作的基本代码逻辑示例(以Python/Flask为例,其他语言逻辑类似):

import requests
from flask import request, jsonify

# SeaweedFS Master 和 Volume 地址
MASTER_URL = "http://your_master_ip:9333"
VOLUME_PUBLIC_URL = "http://your_volume_public_ip:8080"

def upload_file(tenant_id, file):
    """ 为指定租户上传文件 """
    # 1. 申请FID,指定租户的Collection
    assign_url = f"{MASTER_URL}/dir/assign?collection=tenant_{tenant_id}"
    assign_resp = requests.get(assign_url).json()
    
    fid = assign_resp['fid']
    volume_url = assign_resp['url']  # 通常用内网地址上传更快
    
    # 2. 上传文件内容到Volume
    upload_url = f"http://{volume_url}/{fid}"
    files = {'file': (file.filename, file.stream, file.content_type)}
    upload_resp = requests.post(upload_url, files=files)
    
    if upload_resp.status_code == 201:
        # 构建最终可公开访问的URL
        public_file_url = f"http://{VOLUME_PUBLIC_URL}/{fid}"
        return public_file_url
    else:
        return None

def delete_file(tenant_id, fid):
    """ 删除指定租户的文件 """
    # 1. 查找文件所在的Volume服务器
    volume_id = fid.split(',')[0]
    lookup_url = f"{MASTER_URL}/dir/lookup?volumeId={volume_id}"
    lookup_resp = requests.get(lookup_url).json()
    
    # 2. 向Volume服务器发送删除请求
    volume_url = lookup_resp['locations'][0]['url']
    delete_url = f"http://{volume_url}/{fid}"
    delete_resp = requests.delete(delete_url)
    
    return delete_resp.status_code == 202

# 示例路由
@app.route('/api/tenant/<tenant_id>/upload', methods=['POST'])
def handle_upload(tenant_id):
    uploaded_file = request.files['file']
    file_url = upload_file(tenant_id, uploaded_file)
    if file_url:
        return jsonify({'success': True, 'url': file_url})
    else:
        return jsonify({'success': False}), 500

生产环境进阶考虑

  • ​使用Filer服务​​:对于复杂的目录结构管理,强烈建议通过Filer服务来操作文件。Filer提供了类似传统文件系统的目录树视图,并且​​支持S3兼容的API​​,这样您的应用可以直接使用AWS S3 SDK与SeaweedFS交互,集成更方便。
  • ​高可用与数据冗余​​:在启动Master时,可以通过-peers参数指定多个Master节点组成集群,使用Raft协议保证一致性。对于数据,可以在启动Volume时使用副本策略(如-replication=001)或纠删码(Erasure Coding)来提高可靠性并节省存储空间。
  • ​安全配置​​:可以通过-whiteList选项限制可访问的IP地址,防止未授权访问。

Comments

No comments yet. Why don’t you start the discussion?

发表回复