JuiceFS分布式文件系统源码分析(Java层)

简介: 讲解了hadoop-common java api层面JuiceFS的实现流程

01 引言

在前面的博客《JuiceFS-开源分布式文件系统入门(一篇就够了)》,我们大致了解了JuiceFS的一些基本概念,它的架构图大致如下:
在这里插入图片描述
本文主要针对HadoopJava API来分析下它的源码。

02 JuiceFS Hadoop Java API

官方使用教程: 《在 Hadoop 生态使用 JuiceFS 存储》

2.1 如何使用?

使用Hadoop Java API去调用JuiceFS是很简单的,一般分为如下几个步骤。

STEP1:引入依赖

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>版本号</version>
</dependency>

<dependency>
    <groupId>io.juicefs</groupId>
    <artifactId>juicefs-hadoop</artifactId>
    <version>版本号</version>
</dependency>

STEP2:代码使用,只需要修改下Configuration就可以了

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class JuiceFSDemo {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        conf.set("fs.jfs.impl", "io.juicefs.JuiceFileSystem");
        conf.set("juicefs.meta", "redis://127.0.0.1:6379/0");  // JuiceFS 元数据引擎地址
        Path p = new Path("jfs://{JFS_NAME}/");  // 请替换 {JFS_NAME} 为正确的值
        FileSystem jfs = p.getFileSystem(conf);
        FileStatus[] fileStatuses = jfs.listStatus(p);
        // 遍历 JuiceFS 文件系统并打印文件路径
        for (FileStatus status : fileStatuses) {
            System.out.println(status.getPath());
        }
    }
}

STEP3:接下来,直接使用hadoop-common的java api即可使用JuiceFS系统了。

可以看得出,操作是十分简单的,只要引入了hadoop-common以及juicefs-hadoop的依赖,修改一下配置,即可使用。那么其底层的代码又是怎么走的呢?接下来讲讲。

2.2 入口

从上面的代码,我们可以知道,仅仅是配置了两项,然后指定了地址,即可使用JuiceFS文件系统了,如下代码:

Configuration conf = new Configuration();
conf.set("fs.jfs.impl", "io.juicefs.JuiceFileSystem");
conf.set("juicefs.meta", "redis://127.0.0.1:6379/0");  // JuiceFS 元数据引擎地址
Path p = new Path("jfs://{JFS_NAME}/");  // 请替换 {JFS_NAME} 为正确的值
FileSystem jfs = p.getFileSystem(conf);

其中主要核心是 p.getFileSystem(conf) 这一段代码。

2.2.1 getFileSystem方法

跟着断点走,会进入到org.apache.hadoop.fs.FileSystem.Cache#getInternal方法:
在这里插入图片描述
其中较为核心的是createFileSystem方法,进去看看:
在这里插入图片描述
可以看到,createFileSystem方法主要做了获取类的元数据对象以及初始化操作,我们主要看卡getFileSystemClass方法:
在这里插入图片描述
该方法会加载所有的文件系统,对应的方法为loadFileSystems,继续断点:
在这里插入图片描述
当然到这里,并没有我们需要的JuiceFS系统,继续走下一步:
在这里插入图片描述
可以看到红框的那一行,原来是通过拼接scheme来去动态加载JuiceFileSystem的对象,也就是对应前面设置的:

conf.set("fs.jfs.impl", "io.juicefs.JuiceFileSystem");

2.2.2 小结

hadoop-common初始化JuiceFS文件系统的流程:

  • 首先会解析地址获取scheme,如:(jfs://{JFS_NAME}/,它的schemejfs);
  • 接着hadoop-common里面的org.apache.hadoop.fs.FileSystem#getFileSystemClass方法通过拼接"fs." + scheme + ".impl"作为key值去获取config的内容,即:
//conf.set("fs.jfs.impl", "io.juicefs.JuiceFileSystem");
conf.get("fs.jfs.impl", null);
  • 最后即可实例化JuiceFS文件系统了。

2.3 JuiceFS源码

到这里我们知道了hadoop-common api对接JuiceFS的方式了,那么JuiceFS里的代码是如何的呢?

2.3.1 从hadoop-api到juicefs-api

我们可以从实际的业务入手,如下示例:

 private void initHdfsPath() {
        Path path = new Path(RESOURCE_UPLOAD_PATH);
        try {
            if (!fs.exists(path)) {
                fs.mkdirs(path);
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

断点看看fs.exists方法:
在这里插入图片描述
从断点可以看到,当前的文件系统为JuiceFileSystem了,继续断点进去:
在这里插入图片描述
会发下,这里会进入org.apache.hadoop.fs.FileSystem#exists方法,其中里面有一个getFileStatus方法,点击查看:
在这里插入图片描述
原来它是一个抽象方法,由子类实现:
在这里插入图片描述
在这里插入图片描述

它有多个子类实现,当然也包括我们目前的JuiceFileSystemImpl,进入看看:
在这里插入图片描述
终于进来了,接着继续看io.juicefs.JuiceFileSystemImpl#getFileStatusInternal方法:
在这里插入图片描述
可以看到,原来查询是否存在,JuiceFS是使用了lib去查,这个lib其实是调用到了底层的库了(JNI技术)。

2.3.2 JuiceFS底层库

我们通过搜索io.juicefs.JuiceFileSystemImpl#lib变量:
在这里插入图片描述
可以看到它是在io.juicefs.JuiceFileSystemImpl#loadLibrary方法初始化了,看看里面的代码:
在这里插入图片描述
可以看到它是通过识别当前操作系统来去加载JuiceFS的底层so库的,那么底层库的接口支持哪些呢?看看:
在这里插入图片描述
其实就是支持文件系统的CURD这些,也没啥好看的了。

简单的说,它的核心并不在java代码,而是通过JNI来调用底层的库来实现的

03 总结

通过阅读本文,我们可以知道,JucieFS对接hadoop-common api的流程如下:

  1. hadoop-common里面的FileSystem类首先会解析地址获取scheme,如:(jfs://{JFS_NAME}/,它的schemejfs);
  • 接着hadoop-common里面的getFileSystemClass方法通过拼接"fs." + scheme + ".impl"作为key值去获取config的内容并实例化JuiceFS文件系统了;
  • JuiceFS文件系统对象是继承FileSystem对象实现的,所以使用FileSystem的接口去调用,最终由JuiceFS文件系统来实现;
  • JuiceFS文件系统的java代码最终是调用了底层的so库去实现。

其实关键的核心还是在JuiceFS的底层库,不知道有无开源呢?感兴趣的小伙伴可以去参考它的源码:https://github.com/juicedata/juicefs

04 文末

本文主要讲解了hadoop-common java api层面JuiceFS的实现流程,希望能帮助到大家,谢谢大家的阅读,本文完!

目录
相关文章
|
22天前
|
Java
Java中ReentrantLock中部分加锁取消节点源码分析
Java中ReentrantLock中部分加锁取消节点源码分析
30 13
|
22天前
|
Java
Java中ReentrantLock中 lock.lock(),加锁源码分析
Java中ReentrantLock中 lock.lock(),加锁源码分析
16 0
|
5月前
|
消息中间件 NoSQL Java
Java高级开发:高并发+分布式+高性能+Spring全家桶+性能优化
Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师之路
|
2月前
|
运维 监控 Java
推荐一款好用的Java分布式任务调度框架!
推荐一款好用的Java分布式任务调度框架!
174 0
|
1月前
|
缓存 负载均衡 Java
Java分布式系统架构设计与实现
【4月更文挑战第2天】在快速发展的互联网时代,Java分布式系统成为应对复杂业务和高用户量的首选。通过服务化拆分、注册发现、负载均衡和缓存等技术,如Spring Cloud和Dubbo,开发者能构建高效、可靠、可扩展的系统。服务注册与发现确保服务间通信,负载均衡分配请求,分布式缓存如Redis提升性能。面对数据一致性和监控等挑战,Java提供工具解决,助力打造现代分布式应用。
Java分布式系统架构设计与实现
|
2天前
|
存储 搜索推荐 Java
Java远程连接本地开源分布式搜索引擎ElasticSearch
Java远程连接本地开源分布式搜索引擎ElasticSearch
|
8天前
|
分布式计算 Java 调度
[Java 探索者之路] 一个大厂都在用的分布式任务调度平台
[Java 探索者之路] 一个大厂都在用的分布式任务调度平台
|
9天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
|
9天前
|
安全 Java API
Java从入门到精通:3.2.1分布式与并发编程——深入Java并发包,精通多线程高级用法
Java从入门到精通:3.2.1分布式与并发编程——深入Java并发包,精通多线程高级用法
|
2月前
|
XML NoSQL Java
Java单体项目和分布式项目中的锁
Java单体项目和分布式项目中的锁 Java单体项目和分布式项目中的锁
32 2