Hadoop Azure 支持:ABFS — Azure Data Lake Storage Gen2

简介

hadoop-azure 模块通过“abfs”连接器为 Azure Data Lake Storage Gen2 存储层提供支持

要使其成为 Apache Hadoop 的默认类路径的一部分,请确保 HADOOP_OPTIONAL_TOOLS 环境变量在列表中包含 hadoop-azure群集中的每台计算机上都必须如此

export HADOOP_OPTIONAL_TOOLS=hadoop-azure

您可以在 .profile/.bashrc 中本地设置此项,但请注意它不会传播到群集中运行的作业。

ABFS 连接器的功能。

  • 支持读写存储在 Azure Blob 存储帐户中的数据。
  • 完全一致的跨所有客户端的存储视图。
  • 可以读取通过 wasb: 连接器写入的数据。
  • 通过实现标准 Hadoop FileSystem 接口来呈现分层文件系统视图。
  • 支持配置多个 Azure Blob 存储帐户。
  • 可以作为 Hadoop MapReduce、Apache Hive、Apache Spark 中数据的源或目标。
  • 已由 Microsoft 本身在 Linux 和 Windows 上大规模测试。
  • 可用于替代部署在 Azure 基础设施上的 Hadoop 群集中的 HDFS。

有关 ABFS 的详细信息,请参阅以下文档

入门

概念

Azure 存储数据模型提出了 3 个核心概念

  • 存储帐户:所有访问都通过存储帐户完成。
  • 容器:容器是多个 blob 的分组。一个存储帐户可以有多个容器。在 Hadoop 中,整个文件系统层次结构都存储在一个容器中。
  • Blob:使用现有 wasb 连接器存储的任何类型和大小的文件

ABFS 连接器连接到经典容器或使用分层命名空间创建的容器。

分层命名空间(和 WASB 兼容性)

ADLS Gen 2 的一个关键方面是对 分层命名空间 的支持。这些实际上是目录,并提供高性能重命名和删除操作,这极大地提高了写入数据的查询引擎的性能,包括 MapReduce、Spark、Hive 以及 DistCp。

仅当容器使用“命名空间”支持创建时,此功能才可用。

在创建新的存储帐户时,可以通过选中门户 UI 中的“分层命名空间”选项来启用命名空间支持,或者在通过命令行创建时使用选项 --hierarchical-namespace true

无法在现有存储帐户上启用分层命名空间

具有分层命名空间的存储帐户中的容器(目前)无法通过 wasb: 连接器读取。

某些 az storage 命令行命令也会失败,例如

$ az storage container list --account-name abfswales1
Blob API is not yet supported for hierarchical namespace accounts. ErrorCode: BlobApiNotYetSupportedForHierarchicalNamespaceAccounts

创建 Azure 存储帐户

有关使用 abfs 连接器开始使用 Azure Datalake Gen2 的最佳文档是 使用 Azure Data Lake Storage Gen2 和 Azure HDInsight 群集

其中包括 Azure 命令行工具 的创建说明,该工具可以安装在 Windows、MacOS(通过 Homebrew)和 Linux(apt 或 yum)上。

az storage 子命令处理所有存储命令,az storage account create 执行创建操作。

在 ADLS gen2 API 支持最终确定之前,需要向 ADLS 命令添加一个扩展。

az extension add --name storage-preview

通过验证用法命令是否包含 --hierarchical-namespace 来检查一切是否正常

$  az storage account
usage: az storage account create [-h] [--verbose] [--debug]
     [--output {json,jsonc,table,tsv,yaml,none}]
     [--query JMESPATH] --resource-group
     RESOURCE_GROUP_NAME --name ACCOUNT_NAME
     [--sku {Standard_LRS,Standard_GRS,Standard_RAGRS,Standard_ZRS,Premium_LRS,Premium_ZRS}]
     [--location LOCATION]
     [--kind {Storage,StorageV2,BlobStorage,FileStorage,BlockBlobStorage}]
     [--tags [TAGS [TAGS ...]]]
     [--custom-domain CUSTOM_DOMAIN]
     [--encryption-services {blob,file,table,queue} [{blob,file,table,queue} ...]]
     [--access-tier {Hot,Cool}]
     [--https-only [{true,false}]]
     [--file-aad [{true,false}]]
     [--hierarchical-namespace [{true,false}]]
     [--bypass {None,Logging,Metrics,AzureServices} [{None,Logging,Metrics,AzureServices} ...]]
     [--default-action {Allow,Deny}]
     [--assign-identity]
     [--subscription _SUBSCRIPTION]

您可以从 az account list-locations 中列出位置,其中列出了在 --location 参数中引用的名称

$ az account list-locations -o table

DisplayName          Latitude    Longitude    Name
-------------------  ----------  -----------  ------------------
East Asia            22.267      114.188      eastasia
Southeast Asia       1.283       103.833      southeastasia
Central US           41.5908     -93.6208     centralus
East US              37.3719     -79.8164     eastus
East US 2            36.6681     -78.3889     eastus2
West US              37.783      -122.417     westus
North Central US     41.8819     -87.6278     northcentralus
South Central US     29.4167     -98.5        southcentralus
North Europe         53.3478     -6.2597      northeurope
West Europe          52.3667     4.9          westeurope
Japan West           34.6939     135.5022     japanwest
Japan East           35.68       139.77       japaneast
Brazil South         -23.55      -46.633      brazilsouth
Australia East       -33.86      151.2094     australiaeast
Australia Southeast  -37.8136    144.9631     australiasoutheast
South India          12.9822     80.1636      southindia
Central India        18.5822     73.9197      centralindia
West India           19.088      72.868       westindia
Canada Central       43.653      -79.383      canadacentral
Canada East          46.817      -71.217      canadaeast
UK South             50.941      -0.799       uksouth
UK West              53.427      -3.084       ukwest
West Central US      40.890      -110.234     westcentralus
West US 2            47.233      -119.852     westus2
Korea Central        37.5665     126.9780     koreacentral
Korea South          35.1796     129.0756     koreasouth
France Central       46.3772     2.3730       francecentral
France South         43.8345     2.1972       francesouth
Australia Central    -35.3075    149.1244     australiacentral
Australia Central 2  -35.3075    149.1244     australiacentral2

选择位置后,创建帐户

az storage account create --verbose \
    --name abfswales1 \
    --resource-group devteam2 \
    --kind StorageV2 \
    --hierarchical-namespace true \
    --location ukwest \
    --sku Standard_LRS \
    --https-only true \
    --encryption-services blob \
    --access-tier Hot \
    --tags owner=engineering \
    --assign-identity \
    --output jsonc

该命令的输出是一个 JSON 文件,其 primaryEndpoints 命令包括存储端点名称

{
  "primaryEndpoints": {
    "blob": "https://abfswales1.blob.core.windows.net/",
    "dfs": "https://abfswales1.dfs.core.windows.net/",
    "file": "https://abfswales1.file.core.windows.net/",
    "queue": "https://abfswales1.queue.core.windows.net/",
    "table": "https://abfswales1.table.core.windows.net/",
    "web": "https://abfswales1.z35.web.core.windows.net/"
  }
}

abfswales1.dfs.core.windows.net 帐户是存储帐户引用的名称。

现在,询问包含帐户密钥的存储连接字符串

az storage account  show-connection-string --name abfswales1
{
  "connectionString": "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=abfswales1;AccountKey=ZGlkIHlvdSByZWFsbHkgdGhpbmsgSSB3YXMgZ29pbmcgdG8gcHV0IGEga2V5IGluIGhlcmU/IA=="
}

然后,您需要将访问密钥添加到 core-site.xml、JCEKs 文件或使用群集管理工具将选项 fs.azure.account.key.STORAGE-ACCOUNT 设置为该值。

<property>
  <name>fs.azure.account.key.abfswales1.dfs.core.windows.net</name>
  <value>ZGlkIHlvdSByZWFsbHkgdGhpbmsgSSB3YXMgZ29pbmcgdG8gcHV0IGEga2V5IGluIGhlcmU/IA==</value>
</property>

通过 Azure 门户创建

门户创建包含在 快速入门:创建 Azure Data Lake Storage Gen2 存储帐户

主要步骤

  1. 在适合您的位置创建新的存储帐户。
  2. “基本信息”选项卡:选择“StorageV2”。
  3. “高级”选项卡:启用“分层命名空间”。

您现在已创建存储帐户。接下来,获取用于使用默认“共享密钥”身份验证的身份验证密钥。

  1. 转到 Azure 门户。
  2. 选择“存储帐户”
  3. 选择新创建的存储帐户。
  4. 在设置列表中,找到“访问密钥”并选择它。
  5. 将其中一个访问密钥复制到剪贴板,添加到 XML 选项,在群集管理工具、Hadoop JCEKS 文件或 KMS 存储中设置。

创建新容器

一个 Azure 存储帐户可以有多个容器,每个容器的容器名称作为 URI 的 userinfo 字段来引用它。

例如,刚创建的存储帐户中的容器“container1”将具有 URL abfs://[email protected]/

您可以通过将选项 fs.azure.createRemoteFileSystemDuringInitialization 设置为 true 来通过 ABFS 连接器创建新容器。但当 AuthType 为 SAS 时不支持相同内容。

如果容器不存在,则尝试使用 hadoop fs -ls 列出它将失败

$ hadoop fs -ls abfs://[email protected]/

ls: `abfs://[email protected]/': No such file or directory

启用远程文件系统创建,第二次尝试成功,同时创建容器

$ hadoop fs -D fs.azure.createRemoteFileSystemDuringInitialization=true \
 -ls abfs://[email protected]/

这对于在命令行上创建帐户非常有用,尤其是在 az storage 命令完全支持分层命名空间之前。

列出和检查存储帐户的容器。

可以使用 Azure 存储资源管理器

配置 ABFS

任何配置都可以一般指定(或在访问所有帐户时指定为默认值),也可以绑定到特定帐户。例如,可以配置 OAuth 标识,以便无论使用哪个帐户访问,都使用属性 fs.azure.account.oauth2.client.id,或者可以配置仅对特定存储帐户使用标识,属性为 fs.azure.account.oauth2.client.id.<account_name>.dfs.core.windows.net

这在身份验证部分中显示。

身份验证

ABFS 的身份验证最终由 Azure Active Directory 授予。

此处涵盖的概念超出了本文档的范围;开发者应阅读并理解其中的概念,以利用不同的身份验证机制。

这里简要介绍的是如何配置 ABFS 客户端,以便在不同的部署情况下进行身份验证。

ABFS 客户端可以通过不同的方式部署,其身份验证需求由这些方式驱动。

  1. 在配置中使用存储帐户的身份验证密钥:“共享密钥”。
  2. 使用一种或另一种形式的 OAuth 2.0 令牌。
  3. 在 Azure 中部署,Azure VM 向应用程序提供 OAuth 2.0 令牌,“托管实例”。
  4. 使用由 SASTokenProvider 接口的自定义实现提供的共享访问签名 (SAS) 令牌。

可以更改的是用于对调用者进行身份验证的密钥/凭据。

身份验证机制在 fs.azure.account.auth.type(或特定于帐户的变体)中设置。可能的值是 SharedKey、OAuth、Custom 和 SAS。对于各种 OAuth 选项,请使用配置 fs.azure.account .oauth.provider.type。以下是受支持的实现 ClientCredsTokenProvider、UserPasswordTokenProvider、MsiTokenProvider 和 RefreshTokenBasedTokenProvider。如果指定的提供程序类型不是受支持的类型之一,则会引发 IllegalArgumentException。

所有密钥都可以存储在 JCEKS 文件中。这些文件经过加密和密码保护,尽可能使用它们或兼容的 Hadoop 密钥管理存储

AAD 令牌获取重试

用于 AAD 令牌获取重试的指数重试策略可以通过以下配置进行调整。* fs.azure.oauth.token.fetch.retry.max.retries:设置最大重试次数。默认值为 5。* fs.azure.oauth.token.fetch.retry.min.backoff.interval:最小退避时间间隔。添加到从增量退避计算的重试时间间隔。默认情况下,此值为 0。以毫秒为单位设置时间间隔。* fs.azure.oauth.token.fetch.retry.max.backoff.interval:最大退避时间间隔。默认值为 60000(六十秒)。以毫秒为单位设置时间间隔。* fs.azure.oauth.token.fetch.retry.delta.backoff:重试之间的退避时间间隔。此时间跨度的倍数用于后续重试尝试。默认值为 2。

默认:共享密钥

这是帐户 + 密码的最简单的身份验证机制。

帐户名称从 URL 中推断;密码,“密钥”,从 XML/JCECK 配置文件中检索。

<property>
  <name>fs.azure.account.auth.type.abfswales1.dfs.core.windows.net</name>
  <value>SharedKey</value>
  <description>
  </description>
</property>
<property>
  <name>fs.azure.account.key.abfswales1.dfs.core.windows.net</name>
  <value>ZGlkIHlvdSByZWFsbHkgdGhpbmsgSSB3YXMgZ29pbmcgdG8gcHV0IGEga2V5IGluIGhlcmU/IA==</value>
  <description>
  The secret password. Never share these.
  </description>
</property>

注意:帐户密钥的来源可以通过自定义密钥提供程序进行更改;其中一个存在于执行 shell 脚本以检索它。

可以使用配置 fs.azure.account.keyprovider 提供自定义密钥提供程序类。如果指定了密钥提供程序类,则将使用该类来获取帐户密钥。否则将使用简单密钥提供程序,它将使用为配置 fs.azure.account.key 指定的密钥。

要使用 shell 脚本进行检索,请为配置 fs.azure.shellkeyprovider.script 指定脚本的路径。ShellDecryptionKeyProvider 类使用指定的脚本来检索密钥。

OAuth 2.0 客户端凭据

OAuth 2.0 凭据(客户端 ID、客户端密钥、端点)在配置/JCEKS 文件中提供。

此过程的具体内容在 hadoop-azure-datalake 中进行了介绍;这里的键名略有不同。

<property>
  <name>fs.azure.account.auth.type</name>
  <value>OAuth</value>
  <description>
  Use OAuth authentication
  </description>
</property>
<property>
  <name>fs.azure.account.oauth.provider.type</name>
  <value>org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider</value>
  <description>
  Use client credentials
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.client.endpoint</name>
  <value></value>
  <description>
  URL of OAuth endpoint
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.client.id</name>
  <value></value>
  <description>
  Client ID
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.client.secret</name>
  <value></value>
  <description>
  Secret
  </description>
</property>

OAuth 2.0:用户名和密码

OAuth 2.0 端点、用户名和密码在配置/JCEKS 文件中提供。

<property>
  <name>fs.azure.account.auth.type</name>
  <value>OAuth</value>
  <description>
  Use OAuth authentication
  </description>
</property>
<property>
  <name>fs.azure.account.oauth.provider.type</name>
  <value>org.apache.hadoop.fs.azurebfs.oauth2.UserPasswordTokenProvider</value>
  <description>
  Use user and password
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.client.endpoint</name>
  <value></value>
  <description>
  URL of OAuth 2.0 endpoint
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.user.name</name>
  <value></value>
  <description>
  username
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.user.password</name>
  <value></value>
  <description>
  password for account
  </description>
</property>

OAuth 2.0:刷新令牌

使用现有的 Oauth 2.0 令牌,针对活动目录端点 https://login.microsoftonline.com/Common/oauth2/token 发出请求,以刷新此令牌。

<property>
  <name>fs.azure.account.auth.type</name>
  <value>OAuth</value>
  <description>
  Use OAuth 2.0 authentication
  </description>
</property>
<property>
  <name>fs.azure.account.oauth.provider.type</name>
  <value>org.apache.hadoop.fs.azurebfs.oauth2.RefreshTokenBasedTokenProvider</value>
  <description>
  Use the Refresh Token Provider
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.refresh.token</name>
  <value></value>
  <description>
  Refresh token
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.refresh.endpoint</name>
  <value></value>
  <description>
  Refresh token endpoint
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.client.id</name>
  <value></value>
  <description>
  Optional Client ID
  </description>
</property>

Azure 托管标识

Azure 托管标识,以前称为“托管服务标识”。

OAuth 2.0 令牌由特殊端点颁发,该端点仅可从执行的 VM 访问(http://169.254.169.254/metadata/identity/oauth2/token)。颁发的凭据可用于身份验证。

Azure 门户/CLI 用于创建服务标识。

<property>
  <name>fs.azure.account.auth.type</name>
  <value>OAuth</value>
  <description>
  Use OAuth authentication
  </description>
</property>
<property>
  <name>fs.azure.account.oauth.provider.type</name>
  <value>org.apache.hadoop.fs.azurebfs.oauth2.MsiTokenProvider</value>
  <description>
  Use MSI for issuing OAuth tokens
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.msi.tenant</name>
  <value></value>
  <description>
  Optional MSI Tenant ID
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.msi.endpoint</name>
  <value></value>
  <description>
   MSI endpoint
  </description>
</property>
<property>
  <name>fs.azure.account.oauth2.client.id</name>
  <value></value>
  <description>
  Optional Client ID
  </description>
</property>

自定义 OAuth 2.0 令牌提供程序

当调用其 getAccessToken() 方法时,自定义 OAuth 2.0 令牌提供程序会向 ABFS 连接器提供 OAuth 2.0 令牌。

<property>
  <name>fs.azure.account.auth.type</name>
  <value>Custom</value>
  <description>
  Custom Authentication
  </description>
</property>
<property>
  <name>fs.azure.account.oauth.provider.type</name>
  <value></value>
  <description>
  classname of Custom Authentication Provider
  </description>
</property>

声明的类必须实现 org.apache.hadoop.fs.azurebfs.extensions.CustomTokenProviderAdaptee,还可以选择实现 org.apache.hadoop.fs.azurebfs.extensions.BoundDTExtension

声明的类还负责在获取访问令牌时实现重试逻辑。

委派令牌提供程序

委派令牌提供程序通过实现 CustomDelegationTokenManager 接口向 ABFS 连接器提供委派令牌,并帮助续订和取消令牌。

<property>
  <name>fs.azure.enable.delegation.token</name>
  <value>true</value>
  <description>Make this true to use delegation token provider</description>
</property>
<property>
  <name>fs.azure.delegation.token.provider.type</name>
  <value>{fully-qualified-class-name-for-implementation-of-CustomDelegationTokenManager-interface}</value>
</property>

如果启用了委派令牌,并且未提供配置 fs.azure.delegation.token .provider.type,则会引发 IlleagalArgumentException。

共享访问签名 (SAS) 令牌提供程序

共享访问签名 (SAS) 令牌提供程序通过实现 SASTokenProvider 接口向 ABFS 连接器提供 SAS 令牌。

<property>
  <name>fs.azure.account.auth.type</name>
  <value>SAS</value>
</property>
<property>
  <name>fs.azure.sas.token.provider.type</name>
  <value>{fully-qualified-class-name-for-implementation-of-SASTokenProvider-interface}</value>
</property>

声明的类必须实现 org.apache.hadoop.fs.azurebfs.extensions.SASTokenProvider

技术说明

代理设置

连接器使用 JVM 代理设置来控制其代理设置。

请参阅 Oracle Java 文档,了解可设置的选项。

由于连接器默认使用 HTTPS,因此必须配置 https.proxyHosthttps.proxyPort 选项。

在 MapReduce 作业(包括 distcp)中,必须在 mapreduce.map.java.optsmapreduce.reduce.java.opts 中设置代理选项。

# this variable is only here to avoid typing the same values twice.
# It's name is not important.
export DISTCP_PROXY_OPTS="-Dhttps.proxyHost=web-proxy.example.com -Dhttps.proxyPort=80"

hadoop distcp \
  -D mapreduce.map.java.opts="$DISTCP_PROXY_OPTS" \
  -D mapreduce.reduce.java.opts="$DISTCP_PROXY_OPTS" \
  -update -skipcrccheck -numListstatusThreads 40 \
  hdfs://namenode:8020/users/alice abfs://[email protected]/users/alice

如果没有这些设置,即使可以从命令行访问 ADLS,distcp 访问也会因网络错误而失败。

安全性

与其他对象存储一样,登录密钥是宝贵的信息。组织应制定一个安全共享密钥的流程。

ABFS 连接器的限制

  • 不跟踪文件上次访问时间。
  • 不支持扩展属性。
  • 不支持文件校验和。
  • 如果 fs.azure.enable.flush 设置为 true(默认值为 true),则支持 Syncable 接口的 hsync()hflush() 操作。使用 Wasb 连接器,这会将任一调用的次数限制为 50,000 HADOOP-15478。如果 abfs 具有类似的限制,则过度使用同步/刷新可能会导致问题。

一致性和并发性

与所有 Azure 存储服务一样,Azure Datalake Gen 2 存储提供存储的完全一致视图,并为数据和元数据提供完全的创建、读取、更新和删除一致性。

性能和可伸缩性

对于具有分层命名空间的容器,可伸缩性数字(以大 O 符号表示)如下所示

操作 可伸缩性
文件重命名 O(1)
文件删除 O(1)
目录重命名 O(1)
目录删除 O(1)

对于非命名空间存储,可伸缩性变为

操作 可伸缩性
文件重命名 O(1)
文件删除 O(1)
目录重命名 O(files)
目录删除 O(files)

也就是说:文件越多,目录操作越慢。

进一步阅读:Azure 存储可伸缩性目标

可扩展性

ABFS 连接器支持一些受限的私有/不稳定的扩展点,以便第三方将自己的身份验证和授权服务集成到 ABFS 客户端中。

  • CustomDelegationTokenManager:增加签发 Hadoop 委派令牌的能力。
  • SASTokenProvider:允许自定义提供 Azure 存储共享访问签名 (SAS) 令牌。
  • CustomTokenProviderAdaptee:允许自定义提供 Azure OAuth 令牌。
  • KeyProvider.

查阅 org.apache.hadoop.fs.azurebfs.extensions 中的源代码和所有关联的测试,以了解如何使用这些扩展点。

警告 这些扩展点不稳定。

其他配置选项

查阅 org.apache.hadoop.fs.azurebfs.constants.ConfigurationKeysorg.apache.hadoop.fs.azurebfs.constants.FileSystemConfigurationsorg.apache.hadoop.fs.azurebfs.AbfsConfiguration 的 javadoc,以获取配置选项及其默认值的完整列表。

客户端关联选项

1. 客户端 CorrelationId 选项

配置 fs.azure.client.correlationid 提供了一个选项,使用这个客户端提供的标识符关联客户端请求。此 ID 将在 request-id-header 字段中显示在 Azure 存储分析日志中。参考:存储分析日志格式

此配置接受一个字符串,该字符串最多可包含 72 个字符,并且只能包含字母数字字符和/或连字符。如果输入无效,则默认为空字符串。

1. 关联 ID 显示选项

配置 fs.azure.tracingcontext.format 提供了一个选项,用于选择包含在 request-id-header 中的 ID 的格式。此配置接受一个字符串值,该值对应于以下枚举选项。SINGLE_ID_FORMAT:clientRequestId ALL_ID_FORMAT:所有 ID(默认)TWO_ID_FORMAT:clientCorrelationId:clientRequestId

刷新选项

1. Azure Blob 文件系统刷新选项

配置 fs.azure.enable.flush 提供了一个选项,将 ABFS 刷新 API - HFlush() 和 HSync() 呈现为无操作。默认情况下,此配置将设置为 true。

这两个 API 都将确保数据持久化。

2. OutputStream 刷新选项

配置 fs.azure.disable.outputstream.flush 提供了一个选项,将 OutputStream Flush() API 呈现为 AbfsOutputStream 中的无操作。默认情况下,此配置将设置为 true。

Hflush() 是唯一可以提供持久数据传输的已记录 API,而 Flush() 也尝试使缓冲数据持久化,这会导致性能问题。

百分百继续选项

fs.azure.account.expect.header.enabled:此配置参数用于指定是否希望随每个追加请求发送一个预期 100 继续标头。它默认配置为 true。此标志配置客户端在从输出流上传数据块之前向 Azure 存储进行检查。这允许客户端在实际尝试上传块之前优雅地进行节流。在实验中,这在高负载下提供了显著的吞吐量改进。有关更多信息:- https://mdn.org.cn/en-US/docs/Web/HTTP/Headers/Expect

帐户级节流选项

fs.azure.account.operation.idle.timeout:此值指定在分析器(读取或写入)的计时器在没有发出任何新请求之前应暂停的时间。其默认值为 60 秒。

HNS 检查选项

配置 fs.azure.account.hns.enabled 提供了一个选项,用于指定存储帐户是否已启用 HNS。如果未提供配置,则会进行服务器调用以检查相同内容。

访问选项

配置 fs.azure.enable.check.access 需要设置为 true 才能启用 AzureBlobFileSystem.access()。

操作幂等性

由于服务器超时和网络故障而导致请求失败,系统将重试。PUT/POST 操作是幂等的,除了重命名和删除操作之外,不需要任何特定处理。

如果在重试时发现源路径不存在,则通过确保目标上的 LastModifiedTime 为最新来进行重命名幂等性检查。

如果目标在重试时不存在,则默认情况下删除被视为幂等的。

主用户组选项

如果将以下配置设置为 true,则作为 FileStatus 和 AclStatus 一部分的组名将与用户名相同 fs.azure.skipUserGroupMetadataDuringInitialization

IO 选项

以下配置与读写操作相关。

fs.azure.io.retry.max.retries:设置 IO 操作的重试次数。当前仅将其用于服务器调用重试逻辑。在 AbfsClient 类中用作 ExponentialRetryPolicy 的一部分。该值应大于或等于 0。

fs.azure.io.retry.min.backoff.interval:设置 IO 操作重试的最小退避间隔。当前仅将其用于服务器调用重试逻辑。在 AbfsClient 类中用作 ExponentialRetryPolicy 的一部分。此值表示在重试 IO 操作之前等待的最小间隔(以毫秒为单位)。默认值为 3000(3 秒)。

fs.azure.io.retry.max.backoff.interval:设置 IO 操作重试的最大退避间隔。当前仅将其用于服务器调用重试逻辑。在 AbfsClient 类中用作 ExponentialRetryPolicy 的一部分。此值表示在重试 IO 操作之前等待的最大间隔(以毫秒为单位)。默认值为 30000(30 秒)。

fs.azure.io.retry.backoff.interval:设置 IO 操作重试的默认退避间隔。当前仅将其用于服务器调用重试逻辑。在 AbfsClient 类中用作 ExponentialRetryPolicy 的一部分。此值用于计算指定值 80% 到 120% 之间的随机增量。然后将此随机增量乘以当前 IO 重试次数的指数(即,默认值乘以 2^(retryNum - 1)),然后将其限制在 [fs.azure.io.retry.min.backoff.interval, fs.azure.io.retry.max.backoff.interval] 范围内,以确定在下一次 IO 重试尝试之前等待的时间量。默认值为 3000(3 秒)。

fs.azure.write.request.size:设置写入缓冲区大小。以字节为单位指定值。该值应介于 16384 到 104857600 之间(含 16 KB 到 100 MB)。默认值为 8388608(8 MB)。

fs.azure.read.request.size:设置读取缓冲区大小。以字节为单位指定值。该值应介于 16384 到 104857600 之间(含 16 KB 到 100 MB)。默认值为 4194304(4 MB)。

fs.azure.read.alwaysReadBufferSize:仅当读取按顺序模式执行时,才会遵守 fs.azure.read.request.size 配置的读取请求大小。当检测到读取模式是随机时,读取大小将与调用进程提供的缓冲区长度相同。当此配置设置为 true 时,将强制随机读取也按与顺序读取相同的请求大小读取。这是与 ADLS Gen1 具有相同读取模式的一种方法,因为它不区分读取模式,并且始终按配置的读取请求大小读取。此配置的默认值为 false,其中在检测到随机读取模式时,将针对提供的缓冲区长度执行读取。

fs.azure.readaheadqueue.depth:设置 AbfsInputStream 中的预读队列深度。如果设置的值为负数,则预读队列深度将设置为 Runtime.getRuntime().availableProcessors()。默认情况下,该值为 2。要禁用预读,请将此值设置为 0。如果您的工作负载仅执行随机读取(非顺序读取)或您看到限制,则可以尝试将此值设置为 0。

fs.azure.read.readahead.blocksize:设置预读的读取缓冲区大小。以字节为单位指定值。该值应介于 16384 到 104857600 之间(含 16 KB 到 100 MB)。默认值为 4194304(4 MB)。

fs.azure.buffered.pread.disable:默认情况下,位置读取 API 将对输入流执行 seek 和读取。此读取将填充 AbfsInputStream 中的缓冲区高速缓存并更新游标位置。如果此优化为 true,它将跳过缓冲区的用法,并执行无锁 REST 调用以从 blob 中读取。对于 HBase 类型的共享 AbfsInputStream 实例上的短随机读取,此优化非常有用。注意:这不是可以在群集级别设置的配置。它可以用作 FutureDataInputStreamBuilder 上的一个选项。请参阅 FileSystem#openFile(Path path)

要在内存受限的情况下运行,请配置以下内容。尤其是在同一进程中有太多写入操作时。

fs.azure.write.max.concurrent.requests:设置 AbfsOutputStream 实例在任何时间点向服务器发出的最大并发写入请求。实际上,这将是 AbfsOutputStream 实例内的线程池大小。将值设置为 1 到 8(含)。

fs.azure.write.max.requests.to.queue:设置可以排队的最大写入请求。可以通过此配置调整 AbfsOutputStream 实例的内存消耗,因为每个排队的请求都持有缓冲区。将值设置为 s.azure.write.max.concurrent.requests 设置值的 3 或 4 倍。

fs.azure.analysis.period:在分析指标后重新计算休眠持续时间的时间。其默认值为 10 秒。

安全选项

fs.azure.always.use.https:当标志变为 true 时,强制使用 HTTPS 而不是 HTTP。无论标志如何,如果使用安全方案 (ABFSS) 或使用 OAuth 进行身份验证,AbfsClient 将使用 HTTPS。默认情况下,这将设置为 true。

fs.azure.ssl.channel.mode:使用指定的 SSL 通道模式初始化 DelegatingSSLSocketFactory。值应为枚举 DelegatingSSLSocketFactory.SSLChannelMode。默认值将为 DelegatingSSLSocketFactory.SSLChannelMode.Default。

服务器选项

当配置 fs.azure.io.read.tolerate.concurrent.append 变为 true 时,发送到服务器以进行读取调用的 If-Match 标头将设置为 *,否则将使用 ETag 设置。这基本上是一种处理乐观并发读取的机制。请参阅以下链接以获取更多信息。1. https://docs.microsoft.com/en-us/rest/api/storageservices/datalakestoragegen2/path/read 2. https://azure.microsoft.com/de-de/blog/managing-concurrency-in-microsoft-azure-storage-2/

listStatus API 以逐页方式从服务器获取 FileStatus 信息。配置 fs.azure.list.max.results 用于设置 maxResults URI 参数,该参数设置页面大小(每次调用的最大结果数)。该值应大于 0。默认情况下,这将为 5000。服务器对此参数的最大值为 5000。因此,即使配置高于 5000,响应也只会包含 5000 个条目。请参阅以下链接以获取更多信息。 https://docs.microsoft.com/en-us/rest/api/storageservices/datalakestoragegen2/path/list

限制选项

ABFS 驱动程序具有限制读写操作的能力,通过最大程度减少错误来实现最大吞吐量。当超出帐户流入或流出限制时,将发生错误,并且服务器端限制请求。服务器端限制导致使用重试策略,但重试策略会休眠很长时间,导致总流入或流出吞吐量比最佳值低多达 35%。重试策略也是事后的,因为它在请求失败后应用。另一方面,这里实现的客户端限制在发出请求之前发生,并且仅休眠足够的时间来最大程度减少错误,从而允许最佳流入和/或流出吞吐量。默认情况下,限制机制在驱动程序中启用。可以通过将配置 fs.azure.enable.autothrottling 设置为 false 来禁用它。

重命名选项

fs.azure.atomic.rename.key:支持原子重命名的目录可以以逗号分隔的形式在此配置中指定。如果重命名的源属于其中一个已配置的目录,则驱动程序会打印以下警告日志。“ABFS 方案不支持原子重命名功能;但是,如果为 Azure 存储帐户启用了命名空间,则重命名、创建和删除操作是原子的。”目录可以指定为逗号分隔的值。默认值为“/hbase”

无限租期选项

fs.azure.infinite-lease.directories:支持无限租期的目录可以以逗号分隔的形式在此配置中指定。默认情况下,多个客户端将能够同时写入同一文件。在写入此配置中指定的目录中包含的文件时,客户端将获得对文件的租期,该租期将阻止任何其他客户端写入该文件。当输出流关闭时,租期将被释放。要撤销客户端对文件的写访问权限,可以调用 AzureBlobFilesystem breakLease 方法。如果客户端在文件关闭和租期释放之前死亡,则需要在其他客户端能够写入文件之前调用 breakLease。

fs.azure.lease.threads:这是将用于无限租期目录的租期操作的线程池的大小。默认值为 0,因此必须将其至少设置为 1 才能支持无限租期目录。

性能选项

1. HTTP 请求跟踪选项

如果你将 fs.azure.abfs.latency.track 设置为 true,模块将开始跟踪 ABFS HTTP 流量的性能指标。要在你的机器或集群上获取这些数字,你还需要在你的 log4j 配置中为 AbfsPerfTracker 类启用调试日志记录。典型的性能日志行如下所示

h=KARMA t=2019-10-25T20:21:14.518Z a=abfstest01.dfs.core.windows.net
c=abfs-testcontainer-84828169-6488-4a62-a875-1e674275a29f cr=delete ce=deletePath
r=Succeeded l=32 ls=32 lc=1 s=200 e= ci=95121dae-70a8-4187-b067-614091034558
ri=97effdcf-201f-0097-2d71-8bae00000000 ct=0 st=0 rt=0 bs=0 br=0 m=DELETE
u=https%3A%2F%2Fabfstest01.dfs.core.windows.net%2Ftestcontainer%2Ftest%3Ftimeout%3D90%26recursive%3Dtrue

字段具有以下定义

h:主机名 t:记录此请求的时间 a:Azure 存储帐户名 c:容器名 cr:调用方方法的名称 ce:被调用方方法的名称 r:结果(成功/失败) l:延迟(在被调用方中花费的时间) ls:延迟总和(在调用方中花费的总时间;在有多个被调用方时记录;与最后一个被调用方一起记录) lc:延迟计数(被调用方的数量;在有多个被调用方时记录;与最后一个被调用方一起记录) s:HTTP 状态代码 e:错误代码 ci:客户端请求 ID ri:服务器请求 ID ct:连接时间(以毫秒为单位) st:发送时间(以毫秒为单位) rt:接收时间(以毫秒为单位) bs:已发送字节数 br:已接收字节数 m:HTTP 方法(GET、PUT 等) u:编码的 HTTP URL

请注意,这些性能数字还会在后续请求中以 x-ms-abfs-client-latency HTTP 标头发送回 ADLS Gen 2 API 端点。Azure 使用这些设置来跟踪其端到端延迟。

故障排除

通常,与连接器相关的问题按顺序归结为

  1. 类路径。
  2. 网络设置(代理等)。
  3. 身份验证和授权。
  4. 其他任何内容。

如果您在 DEBUG 中记录 org.apache.hadoop.fs.azurebfs.services,那么您将看到有关任何失败请求的更多详细信息。

用于调试连接的一个有用工具是 cloudstore storediag 实用程序

这将验证类路径、设置,然后尝试使用文件系统。

bin/hadoop jar cloudstore-0.1-SNAPSHOT.jar storediag abfs://[email protected]/
  1. 如果 storediag 命令无法使用 abfs 存储,则其他任何方法都可能无法使用。
  2. 如果 storediag 存储确实成功运行,这并不能保证群集其余部分上的类路径或配置也能正常运行,尤其是在分布式应用程序中。但这至少是一个开始。

ClassNotFoundException: org.apache.hadoop.fs.azurebfs.AzureBlobFileSystem

hadoop-azure JAR 不在类路径上。

java.lang.RuntimeException: java.lang.ClassNotFoundException:
    Class org.apache.hadoop.fs.azurebfs.AzureBlobFileSystem not found
  at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2625)
  at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:3290)
  at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3322)
  at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:136)
  at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:3373)
  at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:3341)
  at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:491)
  at org.apache.hadoop.fs.Path.getFileSystem(Path.java:361)
Caused by: java.lang.ClassNotFoundException:
    Class org.apache.hadoop.fs.azurebfs.AzureBlobFileSystem not found
  at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:2529)
  at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2623)
  ... 16 more

提示:如果这种情况发生在命令行上,您可以打开 hadoop 脚本的调试日志记录

export HADOOP_SHELL_SCRIPT_DEBUG=true

如果群集内正在运行的应用程序中发生这种情况,则意味着群集(以某种方式)需要进行配置,以便将 hadoop-azure 模块和依赖项放在已部署应用程序的类路径中。

ClassNotFoundException: com.microsoft.azure.storage.StorageErrorCode

azure-storage JAR 不在类路径中。

服务器未能对请求进行身份验证

在使用默认共享密钥身份验证机制时,未对请求进行身份验证。

Operation failed: "Server failed to authenticate the request.
 Make sure the value of Authorization header is formed correctly including the signature.",
 403, HEAD, https://account.dfs.core.windows.net/container2?resource=filesystem&timeout=90
  at org.apache.hadoop.fs.azurebfs.services.AbfsRestOperation.execute(AbfsRestOperation.java:135)
  at org.apache.hadoop.fs.azurebfs.services.AbfsClient.getFilesystemProperties(AbfsClient.java:209)
  at org.apache.hadoop.fs.azurebfs.AzureBlobFileSystemStore.getFilesystemProperties(AzureBlobFileSystemStore.java:259)
  at org.apache.hadoop.fs.azurebfs.AzureBlobFileSystem.fileSystemExists(AzureBlobFileSystem.java:859)
  at org.apache.hadoop.fs.azurebfs.AzureBlobFileSystem.initialize(AzureBlobFileSystem.java:110)

原因包括

  • 您的凭据不正确。
  • 您的共享密钥已过期。在 Azure 中,此操作会自动发生
  • 您的共享密钥已被撤销。
  • 主机/VM 时钟漂移意味着您的客户端时钟与 Azure 服务器不同步——该调用被拒绝,因为它已过时(被视为重放)或来自未来。修复:检查时钟等。

找不到配置属性 _something_.dfs.core.windows.net

群集配置中没有 fs.azure.account.key. 条目声明特定帐户的访问密钥,或者您使用了错误的 URL

$ hadoop fs -ls abfs://[email protected]/

ls: Configuration property abfswales2.dfs.core.windows.net not found.
  • 确保 URL 正确
  • 添加缺少的帐户密钥。

尝试列出容器时,没有此类文件或目录

没有给定名称的容器。它已被输入错误,或者需要创建容器。

$ hadoop fs -ls abfs://[email protected]/

ls: `abfs://[email protected]/': No such file or directory
  • 确保 URL 正确
  • 根据需要创建容器

“与 https://login.microsoftonline.com/something 的 HTTP 连接因从 AzureAD 获取令牌而失败。HTTP 响应:200 OK”

  • 它的内容类型为 text/htmltext/plainapplication/xml

OAuth 身份验证页面未因 HTTP 错误代码而失败,但它也没有返回 JSON

$ bin/hadoop fs -ls abfs://[email protected]/

 ...

ls: HTTP Error 200;
  url='https://login.microsoftonline.com/02a07549-0a5f-4c91-9d76-53d172a638a2/oauth2/authorize'
  AADToken: HTTP connection to
  https://login.microsoftonline.com/02a07549-0a5f-4c91-9d76-53d172a638a2/oauth2/authorize
  failed for getting token from AzureAD.
  Unexpected response.
  Check configuration, URLs and proxy settings.
  proxies=none;
  requestId='dd9d526c-8b3d-4b3f-a193-0cf021938600';
  contentType='text/html; charset=utf-8';

可能的原因是配置和网络

  1. 身份验证失败,呼叫方被提供用于人类的 Azure Active Directory 登录页面,即使它是由机器呼叫的。
  2. URL 错误——它指向与 OAuth2.0 无关的网页
  3. 有一个代理服务器试图返回有用的说明。

java.io.IOException: 临时目录 /tmp/hadoop-yarn/staging/user1/.staging 的所有权与预期不同。它归 <principal_id> 所有。该目录必须归提交者 user1 或 user1 所有

在使用 Azure 托管标识 时,ADLS Gen2 中的文件/目录默认由服务主体对象 ID(即主体 ID)所有,并且以本地操作系统用户“user1”提交作业会导致出现上述异常。

解决方法是通过将以下属性添加到 core-site.xml 来模仿本地操作系统用户的拥有权。

<property>
  <name>fs.azure.identity.transformer.service.principal.id</name>
  <value>service principal object id</value>
  <description>
  An Azure Active Directory object ID (oid) used as the replacement for names contained
  in the list specified by “fs.azure.identity.transformer.service.principal.substitution.list”.
  Notice that instead of setting oid, you can also set $superuser here.
  </description>
</property>
<property>
  <name>fs.azure.identity.transformer.service.principal.substitution.list</name>
  <value>user1</value>
  <description>
  A comma separated list of names to be replaced with the service principal ID specified by
  “fs.azure.identity.transformer.service.principal.id”.  This substitution occurs
  when setOwner, setAcl, modifyAclEntries, or removeAclEntries are invoked with identities
  contained in the substitution list. Notice that when in non-secure cluster, asterisk symbol *
  can be used to match all user/group.
  </description>
</property>

配置上述属性后,hdfs dfs -ls abfs://[email protected]/ 显示 ADLS Gen2 文件/目录现在归“user1”所有。

测试 ABFS

请参阅 测试 Azure 中的相关部分。