如何为BlobContainerClient配置DFS端点替代Blob端点及相关问题解决
基于Java开发Azure存储操作应用,必须对接DFS端点https://xxxx.dfs.core.windows.net,支持文件上传、追加、重命名、存在性校验等功能,当前遇到两个问题。
报错原因
BlobContainerClient属于Azure Blob存储SDK的客户端,默认适配的是*.blob.core.windows.net端点,直接用其访问DFS端点时,DFS服务要求所有请求必须携带x-ms-version请求头,而Blob客户端默认不会自动添加该头,因此触发必填头缺失报错。
修复方式
不推荐直接用Blob客户端访问DFS端点,优先使用Data Lake专用客户端完成操作。如果必须使用Blob客户端访问DFS端点,需要手动全局添加x-ms-version请求头,取值为Azure存储服务支持的正式版本号(比如2021-08-06),配置示例:
BlobContainerClient blobContainerClient = new BlobContainerClientBuilder() .endpoint("https://xxxx.dfs.core.windows.net/你的容器名") .credential(你的认证凭证) // 全局添加x-ms-version请求头 .addPolicy((context, next) -> { context.getHttpRequest().setHeader("x-ms-version", "2021-08-06"); return next.process(); }) .buildClient();
说明
该逻辑不是Bug,是Azure Data Lake SDK的原有设计:早期版本的Data Lake SDK部分功能复用Blob SDK的实现,因此构建DataLakeFileSystemClient时会自动把DFS端点转换为Blob端点传递给内部的BlobContainerClient。
最优解决方案(仅用一个DataLake客户端完成所有操作)
将azure-storage-file-datalake依赖升级到12.7.0及以上版本,该版本开始DataLakeFileClient、DataLakeDirectoryClient已经原生提供了exists()方法,该方法直接调用DFS端点,不会触发内部Blob客户端的请求,你需要的所有功能都可以通过Data Lake系列客户端完成,不需要单独维护Blob客户端:
- 文件上传:
DataLakeFileClient.upload()/uploadFromFile() - 追加写入:
DataLakeFileClient.append()+flush() - 重命名:
DataLakeFileClient.rename() - 存在性校验:
DataLakeFileClient.exists()
配置与使用示例:
// 仅配置DFS端点,构建DataLake文件系统客户端 DataLakeFileSystemClient fileSystemClient = new DataLakeFileSystemClientBuilder() .endpoint("https://xxxx.dfs.core.windows.net/你的文件系统名") .credential(你的认证凭证) .buildClient(); // 获取目标文件的客户端 DataLakeFileClient fileClient = fileSystemClient.getFileClient("文件路径/文件名"); // 校验文件存在性,直接访问DFS端点,不会调用Blob端点 boolean fileExists = fileClient.exists();
低版本兼容方案(不推荐)
如果无法升级SDK版本,可以通过反射修改DataLakeFileSystemClient内部持有的BlobContainerClient的端点为DFS端点,同时按问题1的方案添加x-ms-version请求头,该方案依赖SDK内部实现,版本升级可能失效。
内容的提问来源于stack exchange,提问作者Miko

