概述
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
。