客户端虚拟路径映射

概述

Alluxio 支持将一个路径映射成另一个路径,所有的读写请求以及元数据操作请求将不会在原始路径上执行,而是会转发到映射后的路径。

当前客户端虚拟路径映射仅仅适用与 Alluxio Fuse 与 Alluxio Cli.

启用虚拟路径映射

alluxio.user.virtual.path.mapping.enabled=true
alluxio.user.virtual.path.mapping.rule.file.path=/opt/alluxio/conf/path_mapping.json

path_mapping.json 是一个 json 文件,用于描述路径之间的映射关系。 这里举一个简单的例子,比如将 /a/b/c/xxx 映射成 /b/c/d/xxx,则可以进行如下配置:

{
  "rules": [
    {
      "src": "^/a/b/c/(.*)$",
      "dst": "/b/c/d/{{ var1 }}"
    }
  ]
}

这里 src 表示原始路径的正则表达式,括号用于取值,取到的值可以在 dst 中使用,用 var 来表示: var1 表示第一个括号里面的值,var2 表示第二个括号里面的值,以此类推,varN 表示第 N 个括号里的值。

下面我们举一个例子,比如我们想要实现以下路径之间的映射关系:

/foo/bar/[a-b].*  ------> /foo1/bar1/A/xxx
/foo/bar/[e-g].*  ------> /foo1/bar1/B/xxx
/foo/bar/[\d].*   ------> /foo1/bar1/C/xxx
/foo/bar/[acd].*  ------> /foo1/bar1/D/xxx

配置文件可以这样写,注意在 json 文件中写 \ 符号时,需要写成 \\,因为 \ 是 json 的转义字符:

{
  "rules": [
    {
      "src": "^/foo/bar/([a-b].*)$",
      "dst": "/foo1/bar1/A/{{ var1 }}"
    },
    {
      "src": "^/foo/bar/([e-g].*)$",
      "dst": "/foo1/bar1/B/{{ var1 }}"
    },
    {
      "src": "^/foo/bar/([\\d].*)$",
      "dst": "/foo1/bar1/C/{{ var1 }}"
    },
    {
      "src": "^/foo/bar/([acd].*)$",
      "dst": "/foo1/bar1/D/{{ var1 }}"
    }
  ]
}

注意:路径映射规则在匹配时,是从上到下逐条进行匹配,只有第一个匹配到的规则生效;如果路径没有匹配到任何规则,原始路径就是映射后的路径。

路径映射测试工具

我们提供了命令行工具来校验路径映射规则是否符合预期,强烈建议在上线之前使用此工具进行验证。

bin/alluxio fs pathmapping /foo/bar/a.txt

-----------------------------------------------------------------
Input:  /foo/bar/a.txt
Output: /foo1/bar1/A/1.txt
Virtual Directory: false
-----------------------------------------------------------------

这里 Output 字段表示映射后的路径,如果输入路径没有匹配到规则,Output 的值将为 null。 Virtual Directory 字段的含义将在下面的章节解释。

Fuse 路径映射(非常重要)

虚拟路径映射配置中,路径都是 Alluxio 的集群路径,对应到 Alluxio Fuse 的本地路径时,需要考虑到 Alluxio Fuse 在本地的挂载路径。

以如下规则为例:

{
  "rules": [
    {
      "src": "^/a/b/(.*)$",
      "dst": "/a1/b1/{{ var1 }}"
    }
  ]
}

下面的命令是等价的,因为我们将 /a/b/c 映射成 /a1/b1/c

bin/alluxio fs ls /a/b/c
bin/alluxio fs ls /a1/b1/c

假设 Alluxio Fuse 在本地的挂载路径为 /mnt/alluxio/alluxio-fuse,以上规则实际上是将/mnt/alluxio/alluxio-fuse/a/b/c 映射为 /mnt/alluxio/alluxio-fuse/a1/b1/c,因此下面的命令是才是等价的:

ls /mnt/alluxio/alluxio-fuse/a/b/c
ls /mnt/alluxio/alluxio-fuse/a1/b1/c

虚拟目录

在 Alluxio Fuse 里访问一个文件时,Alluxio Fuse 会检查这个文件的父路径是否存在,父路径不存在则会报错。

以如下规则为例:

{
  "rules": [
    {
      "src": "^/a/b/(.*)$",
      "dst": "/a1/b1/{{ var1 }}"
    }
  ]
}

我们读取 /a/b/c 时,Alluxio Fuse 会检查父路径 a/b 是否存在,如果 /a/b 不存在,则会报错。 这个检查与映射后的路径 /a1/b1 是否存在没有任何关系。为了避免这种情况,我们可以配置虚拟目录:

{
  "rules": [
    {
      "src": "^/a/b/(.*)$",
      "dst": "/a1/b1/{{ var1 }}"
    }
  ],
  "virtualDirectories": [
    "/a", "/a/b"
  ]
}

virtualDirectories 字段可以填写多个正则表达式,按填写的顺序进行匹配,匹配 virtualDirectories 的路径会始终认为它存在并且被当做一个目录。 配置的虚拟目录也能用命令行进行校验:

bin/alluxio fs pathmapping /a
-----------------------------------------------------------------
Input:  /a
Output: null
Virtual Directory: true
-----------------------------------------------------------------

其中输出的 Virtual Directory 代表路径是否匹配虚拟目录。

限制

规则数量限制

虚拟路径映射不适合有大量规则的场景,因为逐条匹配正则表达式将会影响性能。

ls 限制

在 ls 一个目录时,不能看到所有匹配的子路径。

这里举例说明,对于这个映射关系:

{
  "rules": [
    {
      "src": "^/foo/bar/([a-b].*)$",
      "dst": "/foo1/bar1/A/{{ var1 }}"
    },
    {
      "src": "^/foo/bar/([e-g].*)$",
      "dst": "/foo1/bar1/B/{{ var1 }}"
    },
    {
      "src": "^/foo/bar/([\\d].*)$",
      "dst": "/foo1/bar1/C/{{ var1 }}"
    },
    {
      "src": "^/foo/bar/([acd].*)$",
      "dst": "/foo1/bar1/D/{{ var1 }}"
    }
  ]
}

ls /foo/bar 时,看不到:

/foo1/bar1/A
/foo1/bar1/B
/foo1/bar1/C
/foo1/bar1/D

但是可以直接访问 /foo/bar 目录内的内容,比如可以 cat /foo1/bar1/A/1.txt

Last updated