在 ceph 的使用上, 互联网大规模的文件场景下, fs 并不能满足生产的使用要求, rados 本地化操作也不便于服务的接入与使用, 这里我们就要采用 Ceph Swift Api 来实现文件的存储管理。
Swift 是由 Rackspace 开发,用来为云计算提供可扩展存储的项目。专注于对象存储, 并提供一套 REST风格的Api 来访问, 与 Ceph 强一致性不同, 它是最终一致性。两者都是优秀的开源项目, 并无明显优劣之分,在使用场景上有所不同, 如果是专注于对象存储, 那么可以选择swift 即可满足需要, 如果还有块存储要求, 那么选择Ceph 更为合适。这里选择 Ceph , 因为通过网关可以适配兼容 swift api , 同时在数据访问上具有较强的扩展性:
Ceph 可以提供块、文件和对象三种形态的存储。 RGW 就是提供对象存储的网关,也即对象存储网关。 所谓对象存储网关,也就是对象存储的入口,本质上是一个HTTP 服务器,与 Nginx 和 Apache 无特殊差别。通过这个网关入口,用户可以采用HTTP 协议,以 RESTful 的方式访问 Ceph 的对象存储。
在使用对象存储之前, 先要了解桶(container容器)概念及其存储结构:
Ceph Swift Api 的调用, 需要先创建相应用户进行认证才能操作, 每个用户下面可以创建多个桶, 桶里面可以存储对象,对象就是各种数据文件, 包括文档, 图片等。传统上传文件的使用, 我们往往会指 定路径信息, 在这里, 桶和对象的关系好比文件夹与文件的概念, 不同之处是桶不能再嵌套桶, 也就是没有层级路径的概念。
Ceph 存储结构 :
如果rgw没有显示, 检查服务状态:
systemctl list-unit-files|grep enabled|grep ceph
重启RGW服务:
ceph-deploy --overwrite-conf --ceph-conf ceph.conf rgw create CENTOS7-1
systemctl restart ceph-radosgw@*.service
访问地址, http://192.168.88.161:7480
出现以下提示代表正常
sudo radosgw-admin user create --subuser="cephtester:subtester" --uid="cephtester" --display-name="cephtester" --key-type=swift --secret="654321" --access=full
uid 为主用户, subuser 为子用户信息, secret 指定密钥, 不指定则随机生成, access 拥有权限设定。
返回结果:
[root@CENTOS7-1 ceph-cluster]# sudo radosgw-admin user create --subuser="cephtester:subtester" --uid="cephtester" --display-name="cephtester" --key-type=swift --secret="654321" --access=full
{
"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": []
}
记住swift_keys下面的user和secret_key信息, 代码中需使用。
radosgw-admin user create --uid=mgruser --display-name=mgruser --system
返回结果:
[root@CENTOS7-1 ceph-cluster]# radosgw-admin user create --uid=mgruser --display-name=mgruser --system
{
"user_id": "mgruser",
"display_name": "mgruser",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"auid": 0,
"subusers": [],
"keys": [
{
"user": "mgruser",
"access_key": "W462B8SE31NDCOQR4E6I",
"secret_key": "XPZcugMWRhYccFlEPIHKcyFVr73grVuiJgFD4rDR"
}
],
"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": []
}
根据生成的access_key与secret_key, 执行:
ceph dashboard set-rgw-api-access-key W462B8SE31NDCOQR4E6I
ceph dashboard set-rgw-api-secret-key XPZcugMWRhYccFlEPIHKcyFVr73grVuiJgFD4rDR
打开管理界面,https://192.168.88.161:18843 可以查看到我们刚才创建的两个用户:
增加SwiftOperator接口:
@Component
public class SwiftOperator {
/**
* 用户名信息, 格式: 主用户名:子用户名
*/
private String username ="cephtester:subtester";
/**
* 用户密码
*/
private String password = "654321";
/**
* 接口访问地址
*/
private String authUrl = "http://192.168.88.161:7480/auth/1.0";
/**
* 默认存储的容器名称(bucket)
*/
private String defaultContainerName = "user_datainfo";
/**
* Ceph的账户信息
*/
private Account account = null;
/**
* Ceph的容器信息
*/
private Container container;
/**
* 进行Ceph的初始化配置
*/
public SwiftOperator() {
// 1. Ceph的账户信息配置
AccountConfig config = new AccountConfig();
config.setUsername(username);
config.setPassword(password);
config.setAuthUrl(authUrl);
config.setAuthenticationMethod(AuthenticationMethod.BASIC);
account = new AccountFactory(config).createAccount();
// 2.获取容器信息
Container newContainer = account.getContainer(defaultContainerName);
if(!newContainer.exists()) {
container = newContainer.create();
System.out.println("container create ==> " + defaultContainerName);
}else {
container = newContainer;
}
}
/**
* 文件上传处理
* @param remoteName
* @param filePath
*/
public void createObject(String remoteName, String filePath) {
// 1. 从容器当中获取远程存储对象信息
StoredObject object = container.getObject(remoteName);
// 2. 执行文件上传处理
object.uploadObject(new File(filePath));
}
/**
* 文件的下载处理
* @param objectName
* @param outPath
*/
public void retrieveObject(String objectName, String outPath) {
// 1. 从容器当中获取远程存储对象信息
StoredObject object = container.getObject(objectName);
// 2. 执行文件的下载方法
object.downloadObject(new File(outPath));
}
/**
* 获取用户下面的所有容器信息
* @return
*/
public List listContainer() {
List list = new ArrayList();
Collection<Container> containers = account.list();
for(Container container : containers) {
list.add(container.getName());
System.out.println("current container name : " + container.getName());
}
return list;
}
}
这里的用户名和密码填写上面我们所生成的信息。注意路径地址后缀为: /auth/1.0
CephDemoApplication启动类,测试验证:
@SpringBootApplication
@ComponentScan(basePackages = {"cn.it"})
public class CephDemoApplication {
public static void main(String[] args) throws Exception {
// Swift Api接口调用验证
swiftApi();
}
/**
* 通过Swift接口操作ceph集群
* @throws Exception
*/
public static void swiftApi() throws Exception {
ConfigurableApplicationContext appContext = SpringApplication.run(CephDemoApplication.class);
// 1. 先打印出用户的容器信息
SwiftOperator swiftOperator = appContext.getBean(SwiftOperator.class);
swiftOperator.listContainer();
String objName = "test_ceph";
// 2. 上传指定的文件
swiftOperator.createObject(objName, "E:\\test\\upload\\test_swift_ceph.txt");
// 3. 从ceph下载文件到指定的路径下面
swiftOperator.retrieveObject(objName, "E:\\test\\download\\test_swift_ceph.txt");
System.out.println("complete");
}
}