Java访问Ceph数据的相关细节

本文详细介绍了如何使用Java技术栈访问Ceph存储集群,包括部署LIBRADOS环境、配置集群句柄、创建I/O上下文等步骤,涵盖了安装JNA.jar、克隆rados-java代码库、编译代码、连接到Ceph Monitor、读写数据等关键操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ceph很多公司内部已经进行了部署,当然也有很多公司使用阿里的OSS或者亚马逊的S3。在现在硬件廉价的大环境下,更多的公司愿意把自己的数据内容自我保管,实现企业私有云。下面我们来看一下如何使用Java技术栈来访问Ceph。

1. 部署LIBRADOS环境

客户端应用程序需要librados才能连接到Ceph存储集群。

1.1 安装jna.jar

Debian/Ubuntu环境下执行以下命令

sudo apt-get install libjna-java

CentOS/RHEL环境下执行以下命令

sudo yum install jna

JAR文件位于/usr/share/java.

1.2 克隆rados-java代码库

git clone --recursive https://github.com/ceph/rados-java.git

1.3 编译rados-java代码:

cd rados-java
ant

JAR文件位于rados-java/target目录下

1.4 关联路径

复制该JAR文件到公共目录 (例如 /usr/share/java) ,并且确认该文件和JNA JAR在你的JVM’s classpath目录中. 举个例子,你可以按照以下的方法来关联路径:

sudo cp target/rados-0.1.3.jar /usr/share/java/rados-0.1.3.jar
sudo ln -s /usr/share/java/jna-3.2.7.jar /usr/lib/jvm/default-java/jre/lib/ext/jna-3.2.7.jar
sudo ln -s /usr/share/java/rados-0.1.3.jar  /usr/lib/jvm/default-java/jre/lib/ext/rados-0.1.3.jar

编译文档可执行以下的命令:

ant docs

2. 配置群集句柄

一个Ceph的客户端通过librados,直接与交互的OSD来存储和检索数据。要与OSD交互,客户端应用程序必须调用 librados 并连接到Ceph Monitor。连接后,librados从Ceph Monitor中检索 Cluster Map。当客户端应用程序想要读取或写入数据时,它会创建I/O上下文并绑定到池。该池具有关联的规则集,该规则集定义了如何将数据放入存储群集中。通过I/O上下文,客户端向librados提供对象名称,它获取对象名称和集群映射(即集群的拓扑)并计算用于定位数据的放置组和OSD。然后客户端应用程序可以读取或写入数据。客户端应用程序无需直接了解群集的拓扑。
在这里插入图片描述
Ceph存储集群句柄封装了客户端配置,包括:

  • 使用用户ID的rados_create() 或使用用户名称的rados_create2() (推荐使用此方法).
  • cephx认证密钥
  • 监视器ID和IP地址
  • 记录级别
  • 调试级别

因此,从您的应用程序使用群集的第一步是:1)创建应用程序将用于连接到存储群集的群集句柄,然后2)使用该句柄进行连接。要连接到群集,应用程序必须提供监视器地址,用户名和身份验证密钥(默认情况下启用cephx)。

注意 与不同的Ceph存储集群 - 或与不同用户的同一集群 - 交互需要不同的集群句柄。

RADOS提供了多种设置所需值的方法。对于监视器和加密密钥设置,一种处理它们的简单方法是确保您的Ceph配置文件包含密钥环文件的密钥环路径和至少一个监视器地址(例如,mon 主机)。例如:

[global] 
mon host = 192.168.1.1 
keyring = /etc/ceph/ceph.client.admin.keyring

创建句柄后,可以读取Ceph配置文件以配置句柄。还可以将参数传递给您的应用程序,并使用函数解析它们以解析命令行参数(例如,rados_conf_parse_argv()),或解析Ceph环境变量(例如,rados_conf_parse_env())。某些包装器无法实现便捷方法,因此需要实现这些功能。下图提供了初始连接的高级流程。
在这里插入图片描述
连接后,应用程序可以仅使用群集句柄调用影响整个群集的功能。例如,一旦有了集群句柄,您就可以:

  • 获取群集统计信息
  • 使用池操作(存在,创建,列表,删除)
  • 获取并设置配置
    Ceph的一个强大功能是能够绑定到不同的池。每个池可能具有不同数量的放置组,对象副本和复制策略。例如,可以将池设置为“热”池,其将SSD用于常用对象或使用擦除编码的“冷”池。

Java要求你指定用户ID(admin)或用户名(client.admin),并使用默认的ceph cluster name。Java绑定将基于C ++的错误转换为异常。

import com.ceph.rados.Rados;
import com.ceph.rados.RadosException;

import java.io.File;

public class CephClient {
   
   
        public static void main (String args[]){
   
   

                try {
   
   
                        Rados cluster = new Rados("admin");
                        System.out.println("Created cluster handle.");

                        File f = new File("/etc/ceph/ceph.conf");
                        cluster.confReadFile(f);
                        System.out.println("Read the configuration file.");

                        cluster.connect();
                        System.out.println("Connected to the cluster.");

                } catch (RadosException e) {
   
   
                        System.out.println(e.getMessage() + ": " + e.getReturnValue());
                }
        }
}

编译源代码; 然后,运行。如果你已经把连接Ceph的JAR文件复制到/usr/share/java并软连接到扩展路径, 就无需设置classpath. 如下运行:

javac CephClient.java
java CephClient

3. 创建I/O上下文

一旦应用程序具有集群句柄和与Ceph存储集群的连接,就可以创建I/O上下文并开始读取和写入数据。I/O上下文将连接绑定到特定池。用户必须具有适当的 CAPS权限才能访问指定的池。例如,具有读访问权但不具有写访问权的用户将只能读取数据。I/O上下文功能包括:

  • 写/读数据和扩展属性
  • 列出并迭代对象和扩展属性
  • 快照池,列表快照等

RADOS使应用程序可以同步和异步交互。一旦应用程序具有I/O上下文,读/写操作只需要知道object / xattr名称。封装在librados中的CRUSH算法使用群集映射来识别适当的OSD。OSD守护程序处理复制,如Smart Daemons启用超大规模中所述。所述librados库也映射对象来展示位置组,如在 计算PG的ID。

以下示例使用默认数据池。但是,也可以使用API​​列出池,确保它们存在,或者创建和删除池。对于写操作,这些示例说明了如何使用同步模式。对于读取操作,这些示例说明了如何使用异步模式。

注意 使用此API删除池时请小心。如果删除池,池中的池和所有数据将丢失。

3.1 写入数据代码

import com.ceph.rados.Rados;
import com.ceph.rados.RadosException;

import java.io.File;
import com.ceph.rados.IoCTX;

public class CephClient {
   
   
        public static void main (String args[]){
   
   

                try {
   
   
                        Rados cluster = new Rados("admin");
                        System.out.println("Created cluster handle.");
						//利用配置文件连接ceph
                        File f = new File("/etc/ceph/ceph.conf");
                        cluster.confReadFile(f);
                        System.out.println("Read the configuration file.");

                        cluster.connect();
                        System.out.println("Connected to the cluster.");

                        IoCTX io = cluster.ioCtxCreate("data");

                        String oidone = "hw";
                        String contentone = "Hello World!";
                        io.write(oidone, contentone);

                        String oidtwo = "bm";
                        String contenttwo = "Bonjour tout le monde!";
                        io.write(oidtwo, contenttwo);

                        String[] objects = io.listObjects();
                        for (String object: objects)
                                System.out.println(object);

                        io.remove(oidone);
                        io.remove(oidtwo);

                        cluster.ioCtxDestroy(io);

                } catch (RadosException e) {
   
   
                        System.out.println(e.getMessage() + ": " + e.getReturnValue());
                }
        }
}

3.2 一些基本操作

package com.ceph.rbd;

import java.io.File;
import java.util.Arrays;
import java.util.List;

import com.ceph.rados.IoCTX;
import com.ceph.rados.Rados;
import com.ceph.rados.exceptions.RadosException;
import com.ceph.rbd.jna.RbdImageInfo;
import com.ceph.rbd.jna.RbdSnapInfo;

public class RbdDao {
   
   
    
    private static Rados rados;
    private static IoCTX ioctx;
    private static Rbd rbd;
     /**
      * 连接上ceph环境
      */
     public static void connectCeph(){
   
   
           try {
   
   
           		//利用参数连接Ceph
                rados = new Rados("admin");
                rados.confSet("mon_host", "172.16.60.41");
                rados.confSet("key", "AQCdP9pYGI4jBBAAc96J8/OconCkVKWPBNU2vg==");
                rados.connect();
                ioctx = rados.ioCtxCreate("rbd");
                rbd = new Rbd(ioctx);
                System.out.println("successs connetc");
          } catch (Exception e) {
   
   
              e.printStackTrace();
            // TODO: handle exception
         }
     }
     
     /**
      * 返回所有的image,并展示其详细信息
      * @return
      */
     public static List<String> imageList(){
   
   
          List<String> imageList=null;
          try {
   
   
            imageList = Arrays.asList(rbd.list());
            for(String s:imageList){
   
   
                showDetailOfImage(s);
            }
        } catch (RbdException e) {
   
   
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
          return imageList;
     }
     
     /**
      * 显示image的详细信息
      * @param imageName
      */
     public static void showDetailOfImage(String imageName){
   
   
         RbdImage image;
        try {
   
   
              image = rbd.open(imageName);
              RbdImageInfo info = image.stat();
              System.out.println("=================================================================");
              System.out.println("imageName:    "+imageName);
              System.out.println("imageSize:    "+info.size);
              System.out.println("order:   "+info.order);
              rbd.close(image);
        } catch (RbdException e) {
   
   
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
     }
     
     /**
      * 以格式1创建image
      * @param imageName 名称
      * @param imageSize 大小
      */
     public static void createRbd_format1(String imageName, long imageSize){
   
   
            try {
   
   
                rbd.create(imageName, imageSize);
                RbdImage image = rbd.open(imageName);
                boolean oldFormat = image.isOldFormat();
                System.out.println("imageFormat:==========================="+oldFormat);
               
                rbd.close(image);
            } catch (RbdException e) {
   
   
                System.out.println(e.getMessage() + ": " + e.getReturnValue());
            }
     }
     
     /**
      * 以格式2创建image,ceph 仅支持克隆 format 2 映像(即用 rbd create –format 2 创建的),而且内核 rbd 模块还不支持。
  所以现在你 只能用 QEMU/KVM 或 librbd直接访问克隆品
      * @param imageName 名称
      * @param imageSize 大小
      */
     public static void createRbd_format2(String imageName, long imageSize){
   
   
            try {
   
   
                int features = (1<<0);
                System.out.p
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值