本文提供标准化、可落地的 RGW(对象存储网关)连接与访问流程,从连接信息获取到代码级文件操作,帮助你快速、安全地对接 RGW 对象存储服务。

前置条件(必满足)

在执行以下操作前,需确保已完成以下准备工作:

第一步:获取 RGW 访问地址与端口

  • 登录 MStore 存储集群管理界面;
  • 在左侧导航栏依次点击 对象存储 → 网关,进入 RGW 网关列表页面;
  • 找到用于访问的 RGW 网关实例,记录以下信息:
    • 主机地址:如172.16.20.100(网关部署节点的 IP / 域名);
    • 服务端口:RGW 默认 S3 协议端口为8970(需确认端口未被防火墙 / 安全组拦截,网络可连通)。

示意图:

第二步:获取 RGW 用户访问凭证

  • 在左侧导航栏点击 对象存储 → 用户,进入 RGW 用户列表页面;
  • 找到需用于对接的 RGW 用户(如obj-test-user),点击该用户 “操作” 列的 获取使用方法(或 “访问凭证”)入口;
  • 在弹出窗口中,复制access_key(访问密钥)和secret_key(密钥)—— 这两个凭证是 RGW 身份认证的核心,需妥善保管,禁止泄露。

示意图:

第三步:确认 / 创建 RGW 存储桶

  • 在左侧导航栏点击 对象存储 → 桶,进入 RGW 存储桶列表页面;
  • 若已有目标存储桶(如obj-test-bucket),直接记录桶名称;
  • 若暂无目标存储桶:
    • 点击页面左上角 创建 按钮;
    • 按提示配置桶名称(全局唯一)、所属 RGW 用户、访问权限等参数;
    • 完成创建后记录桶名称。

示意图:

第四步:通过 Java 代码对接 RGW 实现文件操作

以下以 AWS SDK for Java 为例,演示如何连接 RGW 并实现存储桶管理、文件上传 / 下载 / 删除等核心操作。需将代码中占位符替换为实际获取的 RGW 信息后运行。

(一)代码示例

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;

public class RGWObjectStorageExample {
    // 替换为实际获取的RGW信息
    private static final String ACCESS_KEY = "你的RGW用户Access Key";
    private static final String SECRET_KEY = "你的RGW用户Secret Key";
    // 格式:http://RGW网关地址:端口
    private static final String RGW_ENDPOINT = "http://172.16.20.100:8970";
    // 替换为实际的RGW存储桶名称
    private static final String BUCKET_NAME = "obj-test-bucket";
    // 自定义对象名称(RGW中文件的标识)
    private static final String OBJECT_KEY = "test-file.txt";
    // 本地待上传文件路径
    private static final String UPLOAD_FILE_PATH = "/local/path/to/test-file.txt";
    // 文件下载后保存路径
    private static final String DOWNLOAD_FILE_PATH = "/local/path/to/downloaded-file.txt";

    public static void main(String[] args) {
        // 1. 初始化RGW S3客户端
        S3Client s3Client = initRgwS3Client();
        if (s3Client == null) {
            System.err.println("RGW客户端初始化失败!");
            return;
        }

        try {
            // 2. 创建存储桶(若已存在可跳过)
            createRgwBucket(s3Client, BUCKET_NAME);

            // 3. 上传文件到RGW存储桶
            uploadFileToRgw(s3Client, BUCKET_NAME, OBJECT_KEY, UPLOAD_FILE_PATH);

            // 4. 列出存储桶内所有文件
            listRgwBucketObjects(s3Client, BUCKET_NAME);

            // 5. 从RGW下载文件到本地
            downloadFileFromRgw(s3Client, BUCKET_NAME, OBJECT_KEY, DOWNLOAD_FILE_PATH);

            // 6. 删除RGW中的文件(测试用,可根据需求注释)
            deleteFileFromRgw(s3Client, BUCKET_NAME, OBJECT_KEY);

        } catch (S3Exception e) {
            System.err.println("RGW操作失败:" + e.awsErrorDetails().errorMessage());
        } finally {
            // 关闭客户端连接
            if (s3Client != null) {
                s3Client.close();
            }
        }
    }

    /**
     * 初始化RGW S3客户端
     */
    private static S3Client initRgwS3Client() {
        try {
            AwsBasicCredentials credentials = AwsBasicCredentials.create(ACCESS_KEY, SECRET_KEY);
            return S3Client.builder()
                    .credentialsProvider(StaticCredentialsProvider.create(credentials))
                    .endpointOverride(URI.create(RGW_ENDPOINT)) // 指定RGW网关地址
                    .region(Region.of("us-east-1")) // RGW兼容配置,无需修改
                    .build();
        } catch (Exception e) {
            System.err.println("客户端初始化异常:" + e.getMessage());
            return null;
        }
    }

    /**
     * 创建RGW存储桶
     */
    private static void createRgwBucket(S3Client s3Client, String bucketName) {
        try {
            // 检查桶是否已存在,避免重复创建
            HeadBucketRequest headRequest = HeadBucketRequest.builder().bucket(bucketName).build();
            s3Client.headBucket(headRequest);
            System.out.println("存储桶已存在:" + bucketName);
        } catch (NoSuchBucketException e) {
            // 桶不存在则创建
            CreateBucketRequest createRequest = CreateBucketRequest.builder().bucket(bucketName).build();
            s3Client.createBucket(createRequest);
            System.out.println("存储桶创建成功:" + bucketName);
        }
    }

    /**
     * 上传文件到RGW
     */
    private static void uploadFileToRgw(S3Client s3Client, String bucketName, String objectKey, String filePath) {
        File uploadFile = new File(filePath);
        if (!uploadFile.exists()) {
            System.err.println("待上传文件不存在:" + filePath);
            return;
        }

        try (FileInputStream fis = new FileInputStream(uploadFile)) {
            PutObjectRequest putRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(objectKey)
                    .build();
            s3Client.putObject(putRequest, RequestBody.fromInputStream(fis, uploadFile.length()));
            System.out.println("文件上传成功:" + objectKey);
        } catch (IOException e) {
            System.err.println("文件上传异常:" + e.getMessage());
            throw new S3Exception.Builder().message(e.getMessage()).build();
        }
    }

    /**
     * 列出RGW存储桶内所有文件
     */
    private static void listRgwBucketObjects(S3Client s3Client, String bucketName) {
        ListObjectsV2Request listRequest = ListObjectsV2Request.builder().bucket(bucketName).build();
        ListObjectsV2Response listResponse = s3Client.listObjectsV2(listRequest);

        System.out.println("\n存储桶[" + bucketName + "]内的文件列表:");
        for (S3Object object : listResponse.contents()) {
            System.out.println("- " + object.key() + " (大小:" + object.size() + "字节)");
        }
    }

    /**
     * 从RGW下载文件
     */
    private static void downloadFileFromRgw(S3Client s3Client, String bucketName, String objectKey, String targetPath) {
        try (FileOutputStream fos = new FileOutputStream(targetPath)) {
            GetObjectRequest getRequest = GetObjectRequest.builder()
                    .bucket(bucketName)
                    .key(objectKey)
                    .build();
            s3Client.getObject(getRequest, fos);
            System.out.println("\n文件下载成功,保存路径:" + targetPath);
        } catch (IOException e) {
            System.err.println("文件下载异常:" + e.getMessage());
            throw new S3Exception.Builder().message(e.getMessage()).build();
        }
    }

    /**
     * 删除RGW中的文件
     */
    private static void deleteFileFromRgw(S3Client s3Client, String bucketName, String objectKey) {
        DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
                .bucket(bucketName)
                .key(objectKey)
                .build();
        s3Client.deleteObject(deleteRequest);
        System.out.println("\n文件删除成功:" + objectKey);
    }
}

(二)代码说明

  • 客户端初始化:通过endpointOverride指定 RGW 网关地址,结合access_key和secret_key完成身份认证;
  • 核心操作:封装了存储桶创建(含存在性检查)、文件上传 / 下载 / 删除、文件列表查询等常用功能;
  • 异常处理:捕获 S3 协议异常并输出具体错误信息,便于问题定位。

第五步:执行结果验证

成功运行代码后,控制台将输出以下信息,表明 RGW 连接及文件操作已完成:

存储桶已存在:obj-test-bucket
文件上传成功:test-file.txt

存储桶[obj-test-bucket]内的文件列表:
- test-file.txt (大小:1024字节)

文件下载成功,保存路径:/local/path/to/downloaded-file.txt

文件删除成功:test-file.txt

注意事项

  • 网络连通性:确保客户端服务器与 RGW 网关节点的网络互通,放行 8970 端口(或实际使用端口)的入 / 出流量;
  • 凭证安全:禁止将access_key/secret_key硬编码到代码中,建议通过环境变量、配置中心或密钥管理服务托管;
  • 多语言支持:除 Java 外,RGW 兼容 Python、Go、Python 等主流语言的 S3 SDK,可根据技术栈替换对接示例;
  • 权限排查:若出现 “AccessDenied” 错误,需检查:
  • RGW 用户是否拥有该存储桶的操作权限;
  • 存储桶的访问策略是否允许当前 IP / 用户访问;
  • 文件大小限制:大文件(如 GB 级)建议使用分段上传(Multipart Upload),避免单次上传超时。
作者:吴升斌  创建时间:2025-02-27 16:23
最后编辑:吴升斌  更新时间:2025-12-19 18:40