概述

在实际生产环境当中,应用服务要通过API接口来操作调用Ceph文件存储服务,Ceph的Rgw服务提供了Rest 风格的API, 支持Amazon S3和Openstack Swift两种接口。

Swift是由Rackspace开发的用来为云计算提供可扩展存储的项目。专注于对象存储, 并提供一套REST风格的Api来访问, 与Ceph强一致性不同, 它是最终一致性。两者都是优秀的开源项目, 并无明显优劣之分,在使用场景上有所不同, 如果是专注于对象存储, 那么可以选择swift即可满足需要, 如果还有块存储要求, 那么选择Ceph更为合适。Ceph通过Rgw网关可以适配兼容swift api, 同时在数据访问上具有较强的扩展性。

本教程讲解如何通过Java Swift接口来实现文件的上传与下载。

脉络

  • Rgw网关介绍
  • Rgw网关配置
  • Swift Api接口封装测试

知行

1. Rgw 介绍

RGW就是提供对象存储的网关,也即对象存储网关。本质上是一个HTTP服务器,与Nginx和Apache无特殊差别。通过这个网关入口,用户可以采用HTTP协议,以RESTful的方式访问Ceph的对象存储。
Ceph 对象存储模型:

ceph SWIFT接口 ceph和swift_swift


每个用户下面可以创建多个桶, 桶里面可以存储对象,对象就是各种数据文件, 包括文档, 图片等。

2. Rgw 网关配置

  1. 检查集群和rgw服务正常启动
[root@CENTOS7-1 ~]# docker exec mon ceph -s
 cluster:
   id:     646aa796-0240-4dd8-83b3-8781779a8feb
   health: HEALTH_OK

 services:
   mon: 3 daemons, quorum CENTOS7-1,CENTOS7-2,CENTOS7-3 (age 7d)
   mgr: CENTOS7-1(active, since 8d), standbys: CENTOS7-3, CENTOS7-2
   mds: cephfs:1 {0=CENTOS7-1=up:active} 2 up:standby
   osd: 3 osds: 3 up (since 8d), 3 in (since 8d)
   rgw: 3 daemons active (CENTOS7-1, CENTOS7-2, CENTOS7-3)

 data:
   pools:   8 pools, 360 pgs
   objects: 256 objects, 46 KiB
   usage:   3.0 GiB used, 27 GiB / 30 GiB avail
   pgs:     360 active+clean

Rgw服务没有启动或安装, 参考上篇或中篇教程。

  1. 访问验证网关服务
    地址: http://{服务器IP}:7480
    正常可以看到以下信息。

    修改访问端口:
    编辑ceph.conf文件, 增加:
[client.rgw.CENTOS7-1]
rgw_frontends = "civetweb port=20003"

CENTOS7-1代表的是主机名称。

  1. 创建API操作用户
docker exec rgw  radosgw-admin user create --subuser="cephtester:subtester" --uid="cephtester" --display-name="cephtester" --key-type=swift --secret="654321" --access=full

创建了一个名为cephtester的用户, 密钥为654321。不指定secret参数, 密钥则随机生成。
命令执行成功后, 返回结果如下:

{
    "user_id": "cephtester",
    "display_name": "cephtester",
    "email": "",
    "suspended": 0,
    "max_buckets": 1000,
    "auid": 0,
    "subusers": [
        {
            "id": "cephtester:subtester",
            "permissions": "full-control"
        }
    ],
    "keys": [],
    "swift_keys": [
        {
            "user": "cephtester:subtester",
            "secret_key": "654321"
        }
    ],
    "caps": [],
    "op_mask": "read, write, delete",
    "default_placement": "",
    "placement_tags": [],
    "bucket_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "user_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "temp_url_keys": [],
    "type": "rgw",
    "mfa_ids": []
}
  1. 创建管理用户
    这里的管理用户是用于dashboard的管理。
docker exec rgw  radosgw-admin user create --uid=mgruser --display-name=mgruser  --system

执行成功后, 会生成对应的access_key与secret_key信息, 需要记住留存:

{
    "user_id": "mgruser",
    "display_name": "mgruser",
    "email": "",
    "suspended": 0,
    "max_buckets": 1000,
    "auid": 0,
    "subusers": [],
    "keys": [
        {
            "user": "mgruser",
            "access_key": "L3SUWKU1GVHLZLJ7HGPG",
            "secret_key": "XBBwbpXGhtNSIxNDShCtZPdFklLfJmCESgoWlncK"
        }
    ],
    "swift_keys": [],
    "caps": [],
    "op_mask": "read, write, delete",
    "system": "true",
    "default_placement": "",
    "placement_tags": [],
    "bucket_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "user_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "temp_url_keys": [],
    "type": "rgw",
    "mfa_ids": []
}

再将密钥信息加入dashboard中:

docker exec mgr ceph dashboard set-rgw-api-access-key L3SUWKU1GVHLZLJ7HGPG
docker exec mgr ceph dashboard set-rgw-api-secret-key XBBwbpXGhtNSIxNDShCtZ
PdFklLfJmCESgoWlncK

在dashboard管理后台,就能看到用户信息, 便于管理维护:

ceph SWIFT接口 ceph和swift_swift_02

3. 封装Swift Api接口

  1. MAVEN依赖配置:
    pom.xml文件增加以下内容:
<dependency>
        <groupId>com.ceph</groupId>
        <artifactId>rados</artifactId>
        <version>0.6.0</version>
    </dependency>

    <dependency>
        <groupId>org.javaswift</groupId>
        <artifactId>joss</artifactId>
        <version>0.10.2</version>
    </dependency>

    <dependency>
        <groupId>com.ceph</groupId>
        <artifactId>libcephfs</artifactId>
        <version>0.80.5</version>
    </dependency>
  1. 封装Swift接口
/**
 * <p>Description: </p>
 * @date 2019/12/11
 * @name  Mirson
 * <p>Copyright:Copyright(c)2019</p>
 */
@Component
@Log4j2
public class SwiftOperator {

    /**
     * 用户名
     */
    String username = "cephtester:subtester";
    /**
     * 用户密码
     */
    String password = "Ceph@654321";
    /**
     * 接口认证地址
     */
    String authUrl  = "http://39.98.152.160:20003/auth/1.0";
    /**
     * 默认容器名称
     */
    String defaultContainerName = "user_datainfo";


    /**
     * 账户信息
     */
    private Account account;

    /**
     * 容器信息
     */
    private Container container;


    public SwiftOperator() {
        // 账户配置
        AccountConfig config = new AccountConfig();
        config.setUsername(username);
        config.setPassword(password);
        config.setAuthUrl(authUrl);
        config.setAuthenticationMethod(AuthenticationMethod.BASIC);
        // 创建账户
        Account account = new AccountFactory(config).createAccount();
        // 获取容器
        Container newContainer = account.getContainer(defaultContainerName);
        if(!newContainer.exists()) {
            // 如果容器不存在, 则创建
            container = newContainer.create();
            log.info("container create ==> " + defaultContainerName);
        }else {
            container = newContainer;
        }

    }

    /**
     * 上传文件对象
     * @param remoteName
     * @param filepath
     */
    public void createObject(String remoteName, String filepath) {
        StoredObject object = container.getObject(remoteName);
        object.uploadObject(new File(filepath));
    }


    /**
     * 获取下载指定文件对象
     * @param containerName
     * @param objectName
     * @param outpath
     */
    public void  retrieveObject(String objectName,String outpath){
        StoredObject object = container.getObject(objectName);
        object.downloadObject(new File(outpath));
    }

    /**
     * 获取所有容器信息
     * @return
     */
    public List listContainer() {
        List list = new ArrayList();
        Collection<Container> containers = account.list();
        for (Container currentContainer : containers) {
            list.add(currentContainer.getName());
            System.out.println(currentContainer.getName());

        }
        return list;
    }

}
  • 通过构造方法, 创建Ceph的连接配置信息。
  • 封装了文件上传和下载的接口。
  1. 创建启动测试类
    CephDemoApplication启动类代码:
@SpringBootApplication
public class CephDemoApplication {

    private static SwiftOperator swiftOperator;

    public static void main(String[] args) {
	
        ConfigurableApplicationContext appContext =  SpringApplication.run(CephDemoApplication.class, args);
        // 从容器中获取swiftOperator
        swiftOperator = appContext.getBean(SwiftOperator.class);
        // 获取所有容器信息
        System.out.println("list containers: ");
        swiftOperator.listContainer();
		
        String objName = "test_ceph";
        // 上传D盘的swift_test文件
        swiftOperator.createObject(objName, "d:/swift_test.txt");
        // 下载文件至E盘, 名称改为test_swift.txt
        swiftOperator.retrieveObject(objName, "e:/test_swift.txt");

        System.out.println("complete");

    }
  • 从容器中获取我们封装的swiftOperator对象
  • 上传D盘名为swift_test.txt的测试文件, 在ceph中存储名称为test_ceph,注意Ceph中是按用户和对象进行存储, 不支持路径多层级的存储方式。
  • 从ceph中下载名称为test_ceph的对象, 保存至E盘,重命名为test_swift.txt。
  1. 调用验证
    在D盘根目录创建名为swift_test.txt的文件, 随便填入些内容, 待程序执行完成, 检查E盘是否能够成功下载该文件。
    启动CephDemoApplication:
    可以看到程序能够正常连接Ceph集群, 获取Container信息, 成功完成文件的上传与下载。

合一

  • Ceph集群提供了多种API的调用方式, 这里采用兼容性较强的Ceph Swift Api, Ceph功能比较丰富, 更多用法大家可以再自行探索。
  • 这里的Swift封装为单例化操作, 避免连接反复建立产生过多开销,当然, 在实际生产环境当中, 大家应该针对用户和容器再做进一步封装, 每个微服务可以采用一个用户, 服务内的不同业务功能再采用不同容器去做处理, 这样能够提升处理效率, 整个Ceph文件的管理也更为清晰。