Hadoop 文档

General

Common

HDFS

MapReduce

MapReduce REST APIs

YARN

YARN REST APIs

YARN Service

Submarine

Hadoop Compatible File Systems

Auth

Tools

Reference

Configuration

注意:Hadoop的s3:s3n:连接器已被删除。请使用s3a:作为通过Apache Hadoop在S3中托管的数据的连接器。

请查阅s3n文档以获取迁移说明。

也可以看看:

总览

Apache Hadoop的hadoop-aws模块提供了对AWS集成的支持。应用程序轻松使用此支持。

要将S3A客户端包括在Apache Hadoop的默认类路径中:

  1. 确保hadoop-env.sh中的HADOOP_OPTIONAL_TOOLS在其要添加到类路径中的可选模块列表中包括hadoop-aws

  2. 对于客户端交互,可以声明必须在〜/ .hadooprc文件中加载相关的JAR :

    hadoop_add_to_classpath_tools hadoop-aws
    

该文件中的设置不会传播到已部署的应用程序,但是它将适用于本地客户端,例如hadoop fs命令。

Hadoop S3A客户端简介。

Hadoop的“ S3A”客户端针对Amazon S3对象存储和兼容的实现提供了高性能IO。

  • 直接读取和写入S3对象。
  • 与标准S3客户端兼容。
  • 与旧版s3n://客户端和Amazon EMR的s3://客户端创建的文件兼容。
  • 支持多GB对象的分区上传。
  • 提供高性能的随机IO模式,用于处理诸如Apache ORC和Apache Parquet文件之类的列数据。
  • 使用Amazon的Java S3 SDK并支持最新的S3功能和身份验证方案。
  • 支持通过以下方式进行身份验证:环境变量,Hadoop配置属性,Hadoop密钥管理存储和IAM角色。
  • 支持每桶配置。
  • 使用S3Guard,可以添加高性能和一致的元数据/目录读取操作。这提供了一致性和速度。
  • 支持S3“服务器端加密”以进行读写:SSE-S3,SSE-KMS和SSE-C
  • 配备Hadoop指标。
  • 由开源社区积极维护。

其他S3连接器

S3还有其他Hadoop连接器。Hadoop项目本身仅主动维护S3A。

  1. Apache的Hadoop原始s3://客户端。Hadoop中不再包含此功能。
  2. Amazon EMR的s3://客户端。这来自积极维护它的Amazon EMR团队。
  3. Apache的Hadoop的s3n:文件系统客户端。该连接器不再可用:用户必须迁移到较新的s3a:客户端。

入门

S3A依赖于两个JAR,以及hadoop-common及其依赖项。

  • hadoop-aws JAR。
  • aws-java-sdk-bundle JAR。

的版本Hadoop的共同Hadoop的AWS必须相同。

要将库导入到Maven构建中,请在构建依赖项中添加hadoop-aws JAR;它将引入兼容的aws-sdk JAR。

Hadoop的AWS JAR 声明比依赖独特的它,AWS的SDK JAR其它任何依赖关系。这简化了在下游应用程序中排除/调整Hadoop依赖关系JAR的过程。在Hadoop的客户端Hadoop的共同依赖必须申报

<属性>
 <!-您的确切Hadoop版本在这里->
  <hadoop.version> 3.0.0 </hadoop.version>
</ properties>

<依赖项>
  <依赖性>
    <groupId> org.apache.hadoop </ groupId>
    <artifactId> hadoop-client </ artifactId>
    <version> $ {hadoop.version} </ version>
  </ dependency>
  <依赖性>
    <groupId> org.apache.hadoop </ groupId>
    <artifactId> hadoop-aws </ artifactId>
    <version> $ {hadoop.version} </ version>
  </ dependency>
</ dependencies>

警告事项

Amazon S3是“对象存储”的示例。为了实现可伸缩性和特别高的可用性,S3(与许多其他云对象存储一样)放松了经典“ POSIX”文件系统所承诺的一些约束。

S3Guard功能试图解决其中的一些,但它不能这样做完全。请务必阅读这些警告并考虑其适用方式。

有关这些主题的更多讨论,请查阅Hadoop FileSystem API定义

警告1:S3一致性模型

Amazon S3是“对象存储”的示例。为了实现可伸缩性和特别高的可用性,S3(与许多其他云对象存储一样)放松了经典“ POSIX”文件系统所承诺的一些约束。

特别

  1. 从Hadoop Filesystem API新创建的文件可能不会立即显示。
  2. 文件删除和更新操作可能不会立即传播。文件的旧副本可能存在不确定的时间段。
  3. 目录操作:delete()rename()通过逐个文件的递归操作实现。它们所花费的时间至少与文件的数量成正比,在此期间可能会看到部分更新。如果操作被中断,文件系统将处于中间状态。

警告2:模仿目录

S3A客户端通过以下方式模仿目录:

  1. mkdirs调用之后创建一个存根条目,将文件添加到其下的任何位置时将其删除
  2. 列出目录时,搜索其路径以目录路径开头的所有对象,并将其作为列表返回。
  3. 重命名目录时,请列出清单并要求S3将单个对象复制到具有目标文件名的新对象。
  4. 删除目录时,请列出目录并批量删除条目。
  5. 重命名或删除目录时,请列出目录并处理各个文件。

以下是一些后果:

  • 目录可能缺少修改时间。依赖于此的部分Hadoop可能会有意想不到的行为。例如,YARN 的AggregatedLogDeletionService将不会删除相应的日志文件。
  • 目录列表可能很慢。尽可能将listFiles(path,recursive)用于高性能递归列表。
  • 如果调用者努力尝试,则可以在文件下创建文件。
  • 重命名目录的时间与该目录(目录或间接目录)下文件的数量和文件大小成正比。(复制是在S3存储内部执行的,因此时间与从客户端到S3的带宽无关)。
  • 目录重命名不是原子重命名:它们可能会途中失败,并且调用者不能安全地依赖原子重命名作为提交算法的一部分。
  • 目录删除不是原子的,可能会失败。

与HDFS或其他“实际”文件系统相反,使用S3作为直接工作目标时,最后三个问题浮出水面。

S3A提交者是保存输出的查询直接进入S3对象存储通过文件系统S3A可用安全的唯一机制。

警告3:对象存储区具有不同的授权模型

S3的对象授权模型与HDFS和传统文件系统的文件授权模型有很大不同。S3A客户端仅报告可查询此元数据的API的存根信息:

  • 文件所有者被报告为当前用户。
  • 文件组也被报告为当前用户。在Apache Hadoop 2.8.0之前,文件组被报告为空(未关联任何组),这对于执行外壳输出的位置解析的脚本脚本以及希望找到定义明确的组的其他客户端来说是潜在的不兼容问题。
  • 目录权限报告为777。
  • 文件权限报告为666。

S3A并未真正对这些存根权限执行任何授权检查。用户使用AWS凭证向S3存储桶进行身份验证。可能已经定义了对象ACL以在S3端强制执行授权,但这完全发生在S3服务中,而不是在S3A实现中。

警告4:您的AWS凭证非常非常有价值

您的AWS凭证不仅为服务付费,而且还提供对数据的读写访问权限。拥有凭据的任何人都不仅可以读取您的数据集,还可以删除它们。

不要无意间通过以下方式共享这些凭据:

  1. 将所有包含机密的配置文件签入SCM。
  2. 将它们记录到控制台,因为它们总是最终被看到。
  3. 在错误报告中包括秘密。
  4. 记录AWS_环境变量。

如果您执行以下任何一项操作:请立即更改您的凭据!

使用S3进行身份验证

除了与公共S3存储桶进行交互时,S3A客户端需要与存储桶进行交互所需的凭据。

客户端支持多种身份验证机制,并且可以配置为使用哪种机制及其使用顺序。也可以使用com.amazonaws.auth.AWSCredentialsProvider的自定义实现。

重要说明:S3A连接器不再支持s3a:// key:secret @ bucket /形式的URL中的用户名和密码。停止记录这些机密几乎是不可能的,这就是为什么从Hadoop 2.8开始打印警告的原因。

身份验证属性

<属性>
  <name> fs.s3a.access.key </ name>
  <description> AWS访问密钥ID。
   省略基于IAM角色的身份验证或基于提供商的身份验证。</ description>
</ property>

<属性>
  <name> fs.s3a.secret.key </ name>
  <description> AWS密钥。
   省略基于IAM角色的身份验证或基于提供商的身份验证。</ description>
</ property>

<属性>
  <name> fs.s3a.aws.credentials.provider </ name>
  <说明>
    以逗号分隔的凭据提供程序类的类名称,这些类实现
    com.amazonaws.auth.AWSCredentialsProvider。

    依次加载和查询这些证书以获得一组有效的凭据。
    每个列出的类必须实现以下方法之一:
    构造,尝试按以下顺序进行:
    1.接受java.net.URI的公共构造函数,并且
        org.apache.hadoop.conf.Configuration,
    2.一个名为getInstance的公共静态方法,该方法不接受
       参数并返回的实例
       com.amazonaws.auth.AWSCredentialsProvider,或
    3.公共默认构造函数。

    指定org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider允许
    无需任何凭据即可匿名访问可公开访问的S3存储桶。
    请注意,允许匿名访问S3存储桶会危害
    安全性,因此不适用于大多数用例。很有用
    无需AWS凭证即可访问公共数据集。

    如果未指定,则为凭证提供者类别的默认列表,
    依次查询的是:
    1. org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider:
       使用fs.s3a.access.key和fs.s3a.secret.key的值。
    2. com.amazonaws.auth.EnvironmentVariableCredentialsProvider:支持
        在中配置AWS访问密钥ID和秘密访问密钥
        名为AWS_ACCESS_KEY_ID的环境变量和
        AWS_SECRET_ACCESS_KEY,如AWS开发工具包中所述。
    3. com.amazonaws.auth.InstanceProfileCredentialsProvider:支持使用
        如果在EC2 VM中运行,则实例配置文件凭据的数量。
  </ description>
</ property>

<属性>
  <name> fs.s3a.session.token </ name>
  <说明>
    使用org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider时的会话令牌
    作为提供者之一。
  </ description>
</ property>

通过AWS环境变量进行身份验证

S3A支持通过标准AWS环境变量进行配置。

核心环境变量用于访问密钥和关联的机密:

导出AWS_ACCESS_KEY_ID = my.aws.key
导出AWS_SECRET_ACCESS_KEY = my.secret.key

如果设置了环境变量AWS_SESSION_TOKEN,则启用使用“临时安全证书”的会话身份验证;必须将密钥ID和秘密密钥设置为该特定会话的凭据。

导出AWS_SESSION_TOKEN = SECRET-SESSION-TOKEN
导出AWS_ACCESS_KEY_ID = SESSION-ACCESS-KEY
导出AWS_SECRET_ACCESS_KEY = SESSION-SECRET-KEY

这些环境变量可用于设置身份验证凭据,而不是Hadoop配置中的属性。

重要说明:启动YARN应用程序时,通常不会将这些环境变量从客户端传播到服务器。也就是说:启动应用程序时设置AWS环境变量将不允许启动的应用程序访问S3资源。必须(以某种方式)在执行工作的主机/进程上设置环境变量。

更改身份验证提供程序

认证的标准方法是使用配置文件中的属性使用访问密钥和秘密密钥。

S3A客户端遵循以下身份验证链:

  1. fs.s3a.access.keyfs.s3a.secret.key正在寻找在Hadoop的XML配置。
  2. AWS的环境变量,然后寻找。
  3. 尝试查询Amazon EC2实例元数据服务以检索发布到EC2 VM的凭证。

可以将S3A配置为通过实现com.amazonaws.auth.AWSCredentialsProvider接口从与AWS开发工具包集成的类中获取客户端身份验证提供程序。这是通过在配置选项fs.s3a.aws.credentials.provider中按优先顺序列出实现类来完成的。

重要提示:AWS Credential Providers与Hadoop Credential Providers不同。如稍后将介绍的那样,Hadoop凭证提供程序允许密码和其他机密比XML配置文件更安全地存储和传输。AWS Credential Providers是类,Amazon AWS开发工具包可以使用这些类从系统中的其他来源获取AWS登录信息,包括环境变量,JVM属性和配置文件。

hadoop-aws JAR 内部有三个AWS Credential Providers :

班级名称 描述
org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider 会话凭证
org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider 简单的名称/秘密凭证
org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider 匿名登录

Amazon SDK中也有很多,特别是在身份验证链中自动设置的两个:

班级名称 描述
com.amazonaws.auth.InstanceProfileCredentialsProvider EC2元数据凭证
com.amazonaws.auth.EnvironmentVariableCredentialsProvider AWS环境变量

使用InstanceProfileCredentialsProvider进行 EC2 IAM元数据身份验证

在EC2中运行的应用程序可以将IAM角色与VM关联,并向EC2实例元数据服务查询用于访问S3的凭据。在AWS开发工具包中,此功能由InstanceProfileCredentialsProvider提供,该组件在内部强制执行单例实例以防止出现限制问题。

将会话凭证与TemporaryAWSCredentialsProvider一起使用

可以从Amazon Security Token Service获得临时安全凭证;这些由访问密钥,秘密密钥和会话令牌组成。

要验证这些身份:

  1. org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider声明为提供程序。
  2. 在属性fs.s3a.session.token中设置会话密钥,并将访问和密钥属性设置为此临时会话的属性。

例:

<属性>
  <name> fs.s3a.aws.credentials.provider </ name>
  <value> org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider </ value>
</ property>

<属性>
  <name> fs.s3a.access.key </ name>
  <value> SESSION-ACCESS-KEY </ value>
</ property>

<属性>
  <name> fs.s3a.secret.key </ name>
  <value> SESSION-SECRET-KEY </ value>
</ property>

<属性>
  <name> fs.s3a.session.token </ name>
  <value> SECRET-SESSION-TOKEN </ value>
</ property>

会话凭据的生存期在颁发凭据时是固定的;一旦它们过期,应用程序将不再能够向AWS进行身份验证。

匿名登录与AnonymousAWSCredentialsProvider

指定org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider允许匿名访问可公开访问的S3存储桶,而无需任何凭据。它对于不需要AWS凭证即可访问公共数据集很有用。

<属性>
  <name> fs.s3a.aws.credentials.provider </ name>
  <value> org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider </ value>
</ property>

完成此操作后,无需在Hadoop配置中或通过环境变量提供任何凭据。

此选项可用于验证对象存储不允许未经身份验证的访问:也就是说,如果尝试使用匿名凭据来列出存储桶,则该存储将失败—除非显式打开以进行更广泛的访问。

hadoop fs -ls \
 -D fs.s3a.aws.credentials.provider = org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider \
 s3a:// landsat-pds /
  1. 允许匿名访问S3存储桶会损害安全性,因此不适用于大多数用例。

  2. 如果在fs.s3a.aws.credentials.provider中提供了凭据提供者列表,则匿名凭据提供者必须排在最后。如果不是,它将忽略后面列出的凭据提供者。

使用SimpleAWSCredentialsProvider的简单名称/秘密凭证*

这是标准的凭据提供程序,它支持fs.s3a.access.key中的密钥和fs.s3a.secret.key值中的令牌。

<属性>
  <name> fs.s3a.aws.credentials.provider </ name>
  <value> org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider </ value>
</ property>

这是默认身份验证链中使用的基本身份验证器。

这意味着可以将默认的S3A身份验证链定义为

<属性>
  <name> fs.s3a.aws.credentials.provider </ name>
  <值>
  org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider,
  com.amazonaws.auth.EnvironmentVariableCredentialsProvider,
  com.amazonaws.auth.InstanceProfileCredentialsProvider
  </ value>
</ property>

保护AWS凭证

切勿共享或泄露您的AWS凭证至关重要。凭据丢失可能会泄漏/丢失所有数据,增加账单,并严重破坏组织。

  1. 永远不要分享你的秘密。

  2. 切勿将您的秘密提交到SCM存储库中。该git的秘密可以帮助在这里。

  3. 避免使用在URL中包含密钥和机密的s3a URL。这很危险,因为机密会泄漏到日志中。

  4. 切勿在错误报告,附加到它们的文件或类似文件中包含AWS凭证。

  5. 如果使用AWS_环境变量,环境变量列表同样敏感。

  6. 切勿使用根凭证。使用IAM用户帐户,每个用户/应用程序都有其自己的凭据集。

  7. 使用IAM权限可以限制单个用户和应用程序所具有的权限。最好通过角色而不是配置单个用户来完成。

  8. 避免在命令行上将机密传递给Hadoop应用程序/命令。任何已启动程序的命令行对Unix系统上的所有用户都是可见的(通过ps),并保留在命令历史记录中。

  9. 探索使用IAM假定角色进行基于角色的权限管理:可以使用与主要用户帐户不同的假定角色和权限来建立特定的S3A连接。

  10. 考虑一个工作流,在该工作流中向用户和应用程序颁发了短暂的会话凭据,并将S3A配置为通过TemporaryAWSCredentialsProvider使用它们。

  11. 有一个安全的过程来取消和重新发布用户和应用程序的凭据。通过使用它刷新凭据来定期对其进行测试。

在EC2中运行时,IAM EC2实例凭据提供程序将自动以部署EC2 VM的角色获取访问AWS服务所需的凭据。默认情况下,此凭据提供程序已在S3A中启用。

在Hadoop中将AWS登录密钥保密的最安全方法是使用Hadoop凭证。

使用Hadoop凭证提供者存储机密

Hadoop凭证提供程序框架允许安全的“凭证提供程序”将秘密保存在Hadoop配置文件之外,将其存储在本地或Hadoop文件系统中的加密文件中,并将其包括在请求中。

带有敏感数据的S3A配置选项(fs.s3a.secret.keyfs.s3a.access.keyfs.s3a.session.tokenfs.s3a.server-side-encryption.key)可以将其数据保存到存储的二进制文件,当使用S3A文件系统URL进行数据访问时,将读取这些值。然后,在hadoop配置中声明对该凭据提供程序的引用。

有关Hadoop Credential Provider API的更多信息,请参阅:Credential Provider API

以下配置选项可以存储在Hadoop凭据提供程序存储中。

fs.s3a.access.key
fs.s3a.secret.key
fs.s3a.session.token
fs.s3a.server-side-encryption.key
fs.s3a。服务器端加密算法

前三个用于身份验证;第二个用于身份验证。最后两个用于加密。在后者中,仅加密密钥可以被认为是“敏感的”。但是,能够在凭据中包括该算法,从而允许JCECKS文件包含加密写入S3的新数据所需的所有选项。

步骤1:建立凭证档案

凭证文件可以在任何Hadoop文件系统上创建;在HDFS或Unix文件系统上创建目录时,会自动设置权限,以使文件对读取器私有-尽管未触及目录权限,但用户应验证包含文件的目录仅可由当前用户读取。

hadoop凭证创建fs.s3a.access.key -value 123 \
    -提供者jceks://hdfs@nn1.example.com:9001 / user / backup / s3.jceks

hadoop凭证创建fs.s3a.secret.key -value 456 \
    -提供者jceks://hdfs@nn1.example.com:9001 / user / backup / s3.jceks

可以列出凭证文件,以查看其中包含哪些条目

hadoop凭据列表-provider jceks://hdfs@nn1.example.com:9001 / user / backup / s3.jceks

列出CredentialProvider的别名:jceks://hdfs@nn1.example.com:9001 / user / backup / s3.jceks
fs.s3a.secret.key
fs.s3a.access.key

此时,凭据已准备就绪,可以使用。

步骤2:配置hadoop.security.credential.provider.path属性

提供程序的URL必须在命令行或XML配置文件中的配置属性hadoop.security.credential.provider.path中设置。

<属性>
  <name> hadoop.security.credential.provider.path </ name>
  <value> jceks://hdfs@nn1.example.com:9001 / user / backup / s3.jceks </ value>
  <description>用于询问受保护凭据的路径。</ description>
</ property>

因为此属性仅提供机密文件的路径,所以配置选项本身不再是敏感项目。

属性hadoop.security.credential.provider.path是所有文件系统和机密的全局属性。还有另一个属性fs.s3a.security.credential.provider.path,该属性仅列出S3A文件系统的凭据提供程序。这两个属性组合在一起,其中提供程序的列表位于fs.s3a中。属性优先于hadoop.security列表的属性(即,它们优先于公共列表)。

<属性>
  <name> fs.s3a.security.credential.provider.path </ name>
  <值/>
  <说明>
    可选的逗号分隔的凭据提供者列表,一个列表
    在hadoop.security.credential.provider.path中的设置之前
  </ description>
</ property>

添加此功能是为了支持在每个存储桶的基础上绑定不同的凭据提供程序,而无需在凭据列表中添加其他机密。但是,某些应用程序(例如Hive)会阻止凭据提供者列表被用户动态更新。由于现在支持按存储桶的机密,因此最好在JCEKS文件和其他凭证来源中包括按存储桶的密钥。

使用凭证提供者的机密

在Hadoop配置中设置了提供程序后,hadoop命令的工作原理就如同机密信息在XML文件中一样。

hadoop distcp \
    hdfs://nn1.example.com:9001 / user / backup / 007020615 s3a:// glacier1 /

hadoop fs -ls s3a:// glacier1 /

提供程序的路径也可以在命令行上设置:

hadoop distcp \
    -D hadoop.security.credential.provider.path = jceks://hdfs@nn1.example.com:9001 / user / backup / s3.jceks \
    hdfs://nn1.example.com:9001 / user / backup / 007020615 s3a:// glacier1 /

hadoop fs \
  -D fs.s3a.security.credential.provider.path = jceks://hdfs@nn1.example.com:9001 / user / backup / s3.jceks \
  -ls s3a:// glacier1 /

因为提供者路径本身不是敏感机密,所以将其声明放在命令行中没有任何风险。

常规S3A客户端配置

所有S3A客户端选项都配置了带有前缀fs.s3a的选项

客户端支持每桶配置,以允许不同的桶覆盖共享设置。这通常用于更改存储桶的端点,加密和身份验证机制。S3Guard选项,各种次要选项。

这是用于生产的S3A属性。S3Guard选项记录在S3Guard文档中;一些测试相关的选项将在测试

<属性>
  <name> fs.s3a.connection.maximum </ name>
  <value> 15 </ value>
  <description>控制到S3的最大同时连接数。</ description>
</ property>

<属性>
  <name> fs.s3a.connection.ssl.enabled </ name>
  <value> true </ value>
  <description>启用或禁用与S3的SSL连接。</ description>
</ property>

<属性>
  <name> fs.s3a.endpoint </ name>
  <description>要连接的AWS S3端点。最新列表是
    AWS文档中提供的内容:区域和端点。没有这个
    属性,则使用标准区域(s3.amazonaws.com)。
  </ description>
</ property>

<属性>
  <name> fs.s3a.path.style.access </ name>
  <value> false </ value>
  <description>启用S3路径样式访问,即禁用默认的虚拟主机行为。
    对于符合S3A要求的存储提供商很有用,因为它无需为虚拟主机设置DNS。
  </ description>
</ property>

<属性>
  <name> fs.s3a.proxy.host </ name>
  <description>用于S3连接的(可选)代理服务器的主机名。</ description>
</ property>

<属性>
  <name> fs.s3a.proxy.port </ name>
  <description>代理服务器端口。如果未设置此属性
    但使用fs.s3a.proxy.host,则假定使用端口80或443(与
    fs.s3a.connection.ssl.enabled的值。)</ description>
</ property>

<属性>
  <name> fs.s3a.proxy.username </ name>
  <description>用于与代理服务器进行身份验证的用户名。</ description>
</ property>

<属性>
  <name> fs.s3a.proxy.password </ name>
  <description>用于与代理服务器进行身份验证的密码。</ description>
</ property>

<属性>
  <name> fs.s3a.proxy.domain </ name>
  <description>用于通过代理服务器进行身份验证的域。</ description>
</ property>

<属性>
  <name> fs.s3a.proxy.workstation </ name>
  <description>用于通过代理服务器进行身份验证的工作站。</ description>
</ property>

<属性>
  <name> fs.s3a.attempts.maximum </ name>
  <value> 20 </ value>
  <description>我们应该对临时错误重试几次。</ description>
</ property>

<属性>
  <名称> fs.s3a。连接。建立。超时</名称>
  <value> 5000 </ value>
  <description>套接字连接建立超时(以毫秒为单位)。</ description>
</ property>

<属性>
  <name> fs.s3a.connection.timeout </ name>
  <value> 200000 </ value>
  <description>套接字连接超时(以毫秒为单位)。</ description>
</ property>

<属性>
  <name> fs.s3a.paging.maximum </ name>
  <value> 5000 </ value>
  <description>执行操作时需要从S3请求多少个键
     一次列出目录。</ description>
</ property>

<属性>
  <name> fs.s3a.threads.max </ name>
  <value> 10 </ value>
  <description>并发活动(部分)上载的最大数量,
  每个都使用线程池中的线程。</ description>
</ property>

<属性>
  <name> fs.s3a.socket.send.buffer </ name>
  <value> 8192 </ value>
  <description>套接字将缓冲区提示发送到亚马逊连接器。以字节为单位。</ description>
</ property>

<属性>
  <名称> fs.s3a.socket.recv.buffer </名称>
  <value> 8192 </ value>
  <description>套接字接收到亚马逊连接器的缓冲区提示。以字节为单位。</ description>
</ property>

<属性>
  <name> fs.s3a.threads.keepalivetime </ name>
  <value> 60 </ value>
  <description>线程在空闲之前可以空闲的秒数
    终止。</ description>
</ property>

<属性>
  <name> fs.s3a.max.total.tasks </ name>
  <value> 5 </ value>
  <description>之前允许进入队列的(部分)上传次数
  阻止其他上传。</ description>
</ property>

<属性>
  <name> fs.s3a.multipart.size </ name>
  <value> 100M </ value>
  <description>将上传或复制操作分成多少(以字节为单位)。
    集合{K,M,G,T,P}中的后缀可用于缩放数值。
  </ description>
</ property>

<属性>
  <name> fs.s3a.multipart.threshold </ name>
  <value> 2147483647 </ value>
  <description>将上传或复制操作分成多少(以字节为单位)。
    这也控制了重命名文件中的分区大小,因为rename()涉及
    复制源文件。
    集合{K,M,G,T,P}中的后缀可用于缩放数值。
  </ description>
</ property>

<属性>
  <name> fs.s3a.multiobjectdelete.enable </ name>
  <value> true </ value>
  <description>启用后,多个单对象删除请求将替换为
    单个“删除多个对象”请求,从而减少了请求数量。
    注意:与S3兼容的旧对象存储可能不支持此请求。
  </ description>
</ property>

<属性>
  <name> fs.s3a.acl.default </ name>
  <description>为新创建和复制的对象设置一个罐头ACL。价值可能是私人的,
    PublicRead,PublicReadWrite,AuthenticatedRead,LogDeliveryWrite,BucketOwnerRead,
    或BucketOwnerFullControl。</ description>
</ property>

<属性>
  <name> fs.s3a.multipart.purge </ name>
  <value> false </ value>
  <description>如果要清除可能尚未清除的现有分段上传,则为真
     正确完成/中止</ description>
</ property>

<属性>
  <name> fs.s3a.multipart.purge.age </ name>
  <value> 86400 </ value>
  <description>要清除的分段上传的最小年龄(秒)</ description>
</ property>

<属性>
  <name> fs.s3a.signing-algorithm </ name>
  <description>覆盖默认的签名算法
    实现仍可以使用</ description>
</ property>

<属性>
  <name> fs.s3a.server-side-encryption-algorithm </ name>
  <description>指定s3a的服务器端加密算法:文件系统。
    默认情况下未设置。它支持以下值:“ AES256”(对于SSE-S3),“ SSE-KMS”
     和“ SSE-C”
  </ description>
</ property>

<属性>
    <name> fs.s3a.server-side-encryption.key </ name>
    <说明>如果fs.s3a.server-side-encryption-algorithm使用的特定加密密钥
    已设置为“ SSE-KMS”或“ SSE-C”。对于SSE-C,此属性的值
    应该是Base64编码的密钥。如果您使用的是SSE-KMS,并且将此属性留空,
    您将使用默认的S3 KMS密钥,否则应将此属性设置为
    特定的KMS密钥ID。</ description>
</ property>

<属性>
  <名称> fs.s3a.buffer.dir </名称>
  <value> $ {hadoop.tmp.dir} / s3a </ value>
  <description>用逗号分隔的目录列表,将用于缓冲文件
    上传到。</ description>
</ property>

<属性>
  <name> fs.s3a.block.size </ name>
  <value> 32M </ value>
  <description>使用s3a:文件系统读取文件时使用的块大小。
  </ description>
</ property>

<属性>
  <name> fs.s3a.user.agent.prefix </ name>
  <value> </ value>
  <说明>
    设置一个自定义值,该值将预先添加到发送的User-Agent标头中
    S3AFileSystem向S3后端发送HTTP请求。User-Agent标头
    始终包含Hadoop版本号,后跟由生成的字符串
    AWS开发工具包。一个示例是“ User-Agent:Hadoop 2.8.0,aws-sdk-java / 1.10.6”。
    如果设置了此可选属性,则将其值放在前面以创建一个
    定制的用户代理。例如,如果设置了此配置属性
    到“ MyApp”,则生成的User-Agent的示例将是
    “用户代理:MyApp,Hadoop 2.8.0,aws-sdk-java / 1.10.6”。
  </ description>
</ property>

<属性>
  <name> fs.s3a.impl </ name>
  <value> org.apache.hadoop.fs.s3a.S3AFileSystem </ value>
  <description> S3A文件系统的实现类</ description>
</ property>

<属性>
  <name> fs.AbstractFileSystem.s3a.impl </ name>
  <value> org.apache.hadoop.fs.s3a.S3A </ value>
  <description> S3A AbstractFileSystem的实现类。</ description>
</ property>

<属性>
  <name> fs.s3a.readahead.range </ name>
  <value> 64K </ value>
  <description>在关闭之前,在seek()期间要预读的字节
  重新打开S3 HTTP连接。如果此选项将被覆盖
  对setReadahead()的任何调用都是对开放流进行的。</ description>
</ property>

<属性>
  <name> fs.s3a.list.version </ name>
  <value> 2 </ value>
  <description>选择要使用的S3 SDK的List Objects API版本。
  当前支持2(默认)和1(旧API)。</ description>
</ property>

重试和恢复

S3A客户端会尽最大努力从网络故障中恢复;本节将详细介绍其功能。

S3A将AWS开发工具包返回的异常分为不同类别,并根据其类型以及失败的操作是否等幂选择不同的重试策略。

无法恢复的问题:快速失败

  • 没有对象/存储桶:FileNotFoundException
  • 无访问权限:AccessDeniedException
  • 认为不可恢复的网络错误(UnknownHostExceptionNoRouteToHostExceptionAWSRedirectException)。
  • 中断:InterruptedIOExceptionInterruptedException
  • 拒绝的HTTP请求:InvalidRequestException

这些都被认为是不可恢复的:S3A不会尝试从它们中恢复。

可能可恢复的问题:重试

  • 连接超时:ConnectTimeoutException。建立与S3端点(或代理)的连接之前超时。
  • HTTP响应状态码400,“错误请求”

状态码为400的错误请求通常表示该请求不可恢复;这是通用的“否”响应。它很少能恢复,这就是为什么它属于此类,而不是不可恢复的故障。

这些失败将通过fs.s3a.retry.interval中设置的固定睡眠间隔重试,直至达到fs.s3a.retry.limit中设置的限制。

仅在幂等操作上可重试

如果某些网络故障发生在幂等操作上,则认为它们是可重试的;没有办法知道它们在S3处理完请求后是否发生了。

  • SocketTimeoutException:常规网络故障。
  • EOFException:读取数据时连接断开
  • “服务器无响应”(443,444)HTTP响应。
  • 任何其他AWS客户端,服务或S3异常。

这些失败将通过fs.s3a.retry.interval中设置的固定睡眠间隔重试,直至达到fs.s3a.retry.limit中设置的限制。

重要说明:DELETE被认为是幂等的,因此:FileSystem.delete()FileSystem.rename()将在其中任何一种失败时重试其删除请求。

删除是否应幂等的问题一直是Hadoop历史争议的根源。

  1. 在对象存储没有任何其他更改的情况下,重复的DELETE请求最终将导致命名对象被删除。如果重新处理,则是无人操作。确实是Filesystem.delete()
  2. 如果另一个客户端在该路径下创建文件,则该文件将被删除。
  3. 任何支持原子FileSystem.create(path,overwrite = false)操作以拒绝文件创建(如果路径存在)的文件系统都不得认为delete是幂等的,因为create(path,false)操作仅在第一个delete()成功时才能成功通话已成功。
  4. 第二个重试的delete()调用可以删除新数据。

由于S3最终是一致的并且不支持原子的创建无覆盖操作,因此选择更加含糊。

当前,S3A认为delete是幂等的,因为它对于许多工作流程(包括提交协议)都很方便。请注意,在出现瞬时故障的情况下,可能会删除比预期更多的东西。(对于任何认为这是错误决定的人:将常量S3AFileSystem.DELETE_CONSIDERED_IDEMPOTENT设置为false来重建hadoop-aws模块)。

来自S3和Dynamo DB的限制请求

当S3A或Dynamo DB返回表明正在限制来自调用方的请求的响应时,将以初始间隔和最大请求​​数进行指数回退。

<属性>
  <name> fs.s3a.retry.throttle.limit </ name>
  <value> $ {fs.s3a.attempts.maximum} </ value>
  <说明>
    重试任何限制请求的次数。
  </ description>
</ property>

<属性>
  <名称> fs.s3a.retry.throttle.interval </名称>
  <value> 1000ms </ value>
  <说明>
    限制请求重试尝试之间的间隔。
  </ description>
</ property>

笔记

  1. AWS开发工具包内部也正在节流。这由值fs.s3a.attempts.maximum管理。
  2. 在S3A文件系统指标和统计信息中跟踪节流事件。
  3. Amazon KMS可能会根据所有用户帐户和应用程序中KMS的总使用率来限制客户。

限制S3请求太普遍了。这是由于太多的客户端尝试访问S3 Storage的同一分片引起的。如果读取过多,通常会发生这种情况,这是Hadoop应用程序中最常见的读取。Hive在存储数据时使用的分区策略(例如按年然后按月进行分区)加剧了这个问题。这导致路径在开始时几乎没有变化,最终导致所有数据存储在相同的分片中。

这是一些昂贵的操作;发生在S3铲斗的一部分上的事件越多,它承受的负载就越大。*许多客户端试图列出目录或在路径上调用getFileStatus(分别为LIST和HEAD请求)*读取数据时发出的GET请求。*读取列数据(ORC,Parquet)时使用的随机IO意味着与简单的每个文件读取一次相比,GET请求要多得多。*对S3存储桶的该部分的活动写入次数。

一种特殊情况是,当足够的数据已写入S3存储桶的一部分时,S3决定将数据拆分到一个以上的分片中:这被认为是通过某些复制操作来完成的,而复制操作可能会花费一些时间。在此过程中,S3客户端在这些路径下访问数据的速度将比平常受到更多的限制。

缓解策略

  1. 将单独的存储桶用于中间数据/不同的应用程序/角色。
  2. 对同一存储桶中的不同数据集使用明显不同的路径。
  3. 增加fs.s3a.retry.throttle.interval的值可提供两次尝试之间的更长延迟。
  4. 减少查询的并行性。尝试并行访问数据的任务越多,负载就越大。
  5. 减少fs.s3a.threads.max以减少客户端执行的并行操作量。!也许:增加fs.s3a.readahead.range以增加每个GET请求中要求的最小数据量,以及在中止并创建新流之前在现有流中跳过多少数据。
  6. 如果要限制S3Guard使用的DynamoDB表,请通过hadoop s3guard设置容量增加容量(显然要多付一些)。
  7. KMS:“向AWS咨询有关增加容量的信息”。

处理读取期间覆盖

Read-during-overwrite是这样一种情况,即写者覆盖文件,而阅读器在文件上有打开的输入流。根据配置的不同,S3AFileSystem可能会检测到此情况,并在读取器的输入流可能会以静默方式从读取文件原始版本的字节切换为读取新版本的字节的情况下引发RemoteFileChangedException

控制此行为的配置项目为:

<属性>
  <name> fs.s3a.change.detection.source </ name>
  <value> etag </ value>
  <说明>
    选择要用于更改检测的S3对象属性。
    当前支持S3对象eTag的'etag'和'S3对象的'versionid'
    S3对象版本ID。使用版本ID要求对对象进行版本控制
    为每个使用的S3存储桶启用。对象版本控制在禁用
    默认情况下存储桶。使用版本ID时,使用的存储桶应
    在写入任何数据之前已启用版本控制。
  </ description>
</ property>

<属性>
  <名称> fs.s3a.change.detection.mode </名称>
  <值>服务器</值>
  <说明>
    确定如何将更改检测应用于向S3对象发出警报
    被读取时重写。值“服务器”指示应用属性
    直接限制对S3的GetObject请求。重视“客户”是指
    客户端比较响应中返回的属性值。值
    “服务器”不适用于不兼容的第三方S3实现
    在GetObject上支持这些约束。值“服务器”和“客户端”生成
    检测到不匹配时的RemoteObjectChangedException。重视“警告”作品
    类似于“客户”,但仅生成警告。值“无”将忽略更改
    完全检测。
  </ description>
</ property>

<属性>
  <name> fs.s3a.change.detection.version.required </ name>
  <value> true </ value>
  <说明>
    确定S3对象版本属性是否由
    fs.s3.change.detection.source应该按要求处理。如果为真,则
    被引用的属性在S3 GetObject响应中不可用,
    引发NoVersionAttributeException。鼓励设置为“ true”
    避免潜在的与第三方S3实现不一致的读取,或者
    针对已禁用对象版本控制的S3存储桶。
  </ description>
</ property>

在默认配置中,S3对象eTag用于检测更改。当文件系统使用Get Object从S3检索文件时,它将捕获eTag并在每个后续请求中以“ If-Match”条件使用该eTag。如果并发编写器已覆盖文件,则“ If-Match”条件将失败,并且将引发RemoteFileChangedException。

即使在此默认配置中,新写入也可能不会在打开的读取器上触发此异常。例如,如果读取器仅向前读取文件,则仅发出单个S3“获取对象”请求,并且从单个响应流式传输文件的全部内容。带有已读取第一个字节的输入流的读取器根本看不到“获取对象”请求后文件的覆盖。另一方面,向后搜索会导致新的“获取对象”请求,从而触发RemoteFileChangedException

此外,由于S3在重写后读取的情况下最终保持一致性,因此新写入的可见性可能会延迟,从而避免了某些阅读器的RemoteFileChangedException。就是说,如果读者没有看到RemoteFileChangedException,他们至少将阅读该文件的单个版本(开始阅读时可用的版本)的一致视图。

使用S3版本更改检测。

可以切换为使用S3对象版本ID代替eTag作为更改检测机制。使用此选项要求在文件系统使用的任何S3存储桶上启用对象版本控制。使用版本ID代替eTag的好处是可以减少RemoteFileChangedException的频率。启用对象版本控制后,对象的旧版本在被覆盖后仍然可用。这意味着在并发编写器覆盖文件之后,打开的输入流仍将能够向后搜索。阅读器将保留他们从中读取第一个字节的文件版本的一致视图。由于在启用对象版本控制之前编写的对象的版本ID为空,因此,仅当S3存储桶从一开始就启用了对象版本控制时,才应使用此选项。

注意:重命名文件时,复制的文件可能具有不同的版本号。

更改检测模式。

下一个选项是可配置的更改检测模式。主要可以使用不同的模式来实现与可能不支持所有变更检测机制的第三方S3实现的兼容性。

  • server:通过向GET请求添加额外的标头,在服务器上执行版本/标记检查。这是默认值。
  • client:通过将重新打开的文件的eTag /版本ID与以前的版本进行比较来检查客户端。当实现不支持If-Match标头时,这很有用。
  • 警告:检查客户端,但仅警告不匹配,而不是失败。
  • 没有不检查。如果实现根本不提供eTag或版本ID支持,或者您希望保留以前的行为(阅读器的输入流以静默方式切换到新的对象版本(不推荐),则此行为很有用)。

最后一个选项(fs.s3a.change.detection.version.required)的存在主要是为了确保文件系统不会默默忽略配置为在未启用对象版本控制的存储桶上使用版本ID的条件。或者,将其配置为在不返回eTag的S3实现中使用eTag。

如果为true(默认),并且“获取对象”不返回eTag或版本ID(取决于配置的“源”),则将引发NoVersionAttributeException。如果为false且未返回eTag或版本ID,则可以读取流,但不进行任何版本检查。

通过按桶配置配置不同的S3存储桶

可以使用不同的S3A客户端配置访问不同的S3存储桶。这允许使用不同的端点,数据读取和写入策略以及登录详细信息。

  1. 除少数不可修改的值(当前为fs.s3a.impl)外,所有fs.s3a选项都可以在每个存储桶的基础上进行设置。
  2. 通过替换fs.s3a设置存储桶特定选项fs.s3a.bucket.BUCKETNAME选项的前缀,其中BUCKETNAME是存储桶的名称。
  3. 连接到存储桶时,所有明确设置的选项都将覆盖基础fs.s3a。价值观。

例如,配置可以具有基本配置,以使用在Amazon EC2中部署时可用的IAM角色信息。

<属性>
  <name> fs.s3a.aws.credentials.provider </ name>
  <value> com.amazonaws.auth.InstanceProfileCredentialsProvider </ value>
</ property>

这将成为S3A存储桶的默认身份验证机制。

然后可以为用于夜间数据的存储桶s3a:// nightly /提供会话密钥:

<属性>
  <name> fs.s3a.bucket.nightly.access.key </ name>
  <value> AKAACCESSKEY-2 </ value>
</ property>

<属性>
  <名称> fs.s3a.bucket.nightly.secret.key </名称>
  <value> SESSIONSECRETKEY </ value>
</ property>

<属性>
  <name> fs.s3a.bucket.nightly.session.token </ name>
  <value>短期会话令牌</ value>
</ property>

<属性>
  <名称> fs.s3a.bucket.nightly.aws.credentials.provider </名称>
  <value> org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider </ value>
</ property>

最后,可以匿名访问公共的s3a:// landsat-pds /存储桶:

<属性>
  <name> fs.s3a.bucket.landsat-pds.aws.credentials.provider </ name>
  <value> org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider </ value>
</ property>

定制凭证文件中保存的S3A机密

JCEKS文件中的秘密或其他Hadoop凭据提供者提供的秘密也可以按存储桶配置。S3A客户端将查找每个存储桶的机密

考虑具有六个键的JCEKS文件:

fs.s3a.access.key
fs.s3a.secret.key
fs.s3a。服务器端加密算法
fs.s3a.bucket.nightly.access.key
fs.s3a.bucket.nightly.secret.key
fs.s3a.bucket.nightly.session.token
fs.s3a.bucket.nightly。服务器端加密密钥
fs.s3a.bucket.nightly。服务器端加密算法

当访问存储桶s3a:// nightly /时,将使用该存储桶的每个存储桶配置选项,此处为访问密钥和令牌,包括加密算法和密钥。

使用每个存储桶配置来访问世界各地的数据

S3存储桶托管在不同的“区域”中,默认为“美国东部”。默认情况下,S3A客户端与该区域对话,向服务器s3.amazonaws.com发出HTTP请求。

S3A可以与来自任何区域的存储桶一起使用。每个区域都有自己的S3终端节点,由Amazon记录

  1. 在EC2基础架构中运行的应用程序无需为往返于本地S3存储桶的 IO付费。他们将被收取访问远程存储桶的费用。尽可能使用本地存储区和数据的本地副本。
  2. 使用V1请求签名协议时,默认的S3端点可以支持任何存储区的数据IO。
  3. 使用V4签名协议时,AWS要求使用显式区域终端节点—因此必须将S3A配置为使用特定终端节点。这是在配置选项fs.s3a.endpoint中完成的
  4. 除默认端点外,所有端点仅支持与该S3实例本地的存储桶进行交互。

尽管使用默认端点通常更简单,但使用仅V4签名区域(法兰克福,首尔)需要标识端点。期望直接连接会有更好的性能-traceroute将为您提供一些见识。

如果使用了错误的端点,则请求可能会失败。这可能被报告为301 /重定向错误或400错误请求:以这些为线索来检查存储桶的端点设置。

以下是定义所有AWS S3区域的属性的列表,截至2017年6月为当前状态:

<!-
 这是默认端点,可用于交互
 任何v2区域。
 ->
<属性>
  <name> central.endpoint </ name>
  <value> s3.amazonaws.com </ value>
</ property>

<属性>
  <name> canada.endpoint </ name>
  <value> s3.ca-central-1.amazonaws.com </ value>
</ property>

<属性>
  <name> frankfurt.endpoint </ name>
  <value> s3.eu-central-1.amazonaws.com </ value>
</ property>

<属性>
  <name> ireland.endpoint </ name>
  <value> s3-eu-west-1.amazonaws.com </ value>
</ property>

<属性>
  <name> london.endpoint </ name>
  <value> s3.eu-west-2.amazonaws.com </ value>
</ property>

<属性>
  <name> mumbai.endpoint </ name>
  <value> s3.ap-south-1.amazonaws.com </ value>
</ property>

<属性>
  <name> ohio.endpoint </ name>
  <value> s3.us-east-2.amazonaws.com </ value>
</ property>

<属性>
  <name> oregon.endpoint </ name>
  <value> s3-us-west-2.amazonaws.com </ value>
</ property>

<属性>
  <name> sao-paolo.endpoint </ name>
  <value> s3-sa-east-1.amazonaws.com </ value>
</ property>

<属性>
  <name> seoul.endpoint </ name>
  <value> s3.ap-northeast-2.amazonaws.com </ value>
</ property>

<属性>
  <name> singapore.endpoint </ name>
  <value> s3-ap-southeast-1.amazonaws.com </ value>
</ property>

<属性>
  <name> sydney.endpoint </ name>
  <value> s3-ap-southeast-2.amazonaws.com </ value>
</ property>

<属性>
  <name> tokyo.endpoint </ name>
  <value> s3-ap-northeast-1.amazonaws.com </ value>
</ property>

<属性>
  <name> virginia.endpoint </ name>
  <value> $ {central.endpoint} </ value>
</ property>

此列表可用于指定各个存储桶的端点,例如,用于中央和EU /爱尔兰端点的存储桶。

<属性>
  <name> fs.s3a.bucket.landsat-pds.endpoint </ name>
  <value> $ {central.endpoint} </ value>
  <description> s3a:// landsat-pds URL的终结点</ description>
</ property>

<属性>
  <name> fs.s3a.bucket.eu-dataset.endpoint </ name>
  <value> $ {ireland.endpoint} </ value>
  <description> s3a:// eu-dataset URL的终结点</ description>
</ property>

为什么要显式声明绑定到中央端点的存储桶?它确保如果将默认终结点更改为新区域,则仍然可以访问US-east中的数据存储。

S3A如何将数据写入S3

原始的S3A客户端实现的文件写入是通过将所有数据写入到OutputStream时缓冲到磁盘上来进行的。只有在调用流的close()方法时,上传才会开始。

这使输出变慢,尤其是在较大的上载时,甚至可能会填满小(虚拟)磁盘的磁盘空间。

Hadoop 2.7添加了S3AFastOutputStream替代方案,Hadoop 2.8对其进行了扩展。现在,它被认为是稳定的,并且已经替换了原来的S3AOutputStream,后者不再在hadoop中提供。

“快速”输出流

  1. 将大文件作为块上传,其大小由fs.s3a.multipart.size设置。也就是说:分段上传的阈值和每次上传的大小都相同。
  2. 将块缓冲到磁盘(默认)或堆上或堆外内存中。
  3. 在后台线程中并行上传块。
  4. 一旦缓冲的数据超过此分区大小,即开始上载块。
  5. 将数据缓冲到磁盘时,请使用fs.s3a.buffer.dir中列出的目录。可以缓冲的数据大小限于可用磁盘空间。
  6. 生成输出统计信息作为文件系统上的指标,包括活动和未决块上传的统计信息。
  7. 可以通过要上传的剩余数据量(而不是文件的总大小)来设置close()的时间。

因为它在仍在写入数据的同时开始上载,所以当生成大量数据时,它具有明显的优势。当与S3端点相邻运行时,内存中缓冲机制还可以提高速度,因为磁盘不用于中间数据存储。

<属性>
  <name> fs.s3a.fast.upload.buffer </ name>
  <value>磁盘</ value>
  <说明>
    要使用的缓冲机制。
    值:磁盘,数组,字节缓冲区。

    “磁盘”将使用fs.s3a.buffer.dir中列出的目录作为
    上传之前要保存数据的位置。

    “数组”使用JVM堆中的数组

    “字节缓冲区”使用JVM中的堆外内存。

    “数组”和“字节缓冲区”都将在单个流中消耗内存,数量最多为
    设置的块数:

        fs.s3a.multipart.size * fs.s3a.fast.upload.active.blocks。

    如果使用这些机制中的任何一种,请将该值保持较低

    通过所有线程执行工作的线程总数由
    fs.s3a.threads.max,其中fs.s3a.max.total.tasks值设置排队的数量
    工作项目。
  </ description>
</ property>

<属性>
  <name> fs.s3a.multipart.size </ name>
  <value> 100M </ value>
  <description>将上传或复制操作分成多少(以字节为单位)。
    集合{K,M,G,T,P}中的后缀可用于缩放数值。
  </ description>
</ property>

<属性>
  <name> fs.s3a.fast.upload.active.blocks </ name>
  <value> 8 </ value>
  <说明>
    单个输出流可以具有的最大块数
    活动(上载或排队到中央文件系统
    实例的排队操作池。

    这将阻止单个流使共享线程池超载。
  </ description>
</ property>

笔记

  • 如果写入流的数据量低于fs.s3a.multipart.size中设置的数据量,则上载将在OutputStream.close()操作中执行-与原始输出流一样。

  • 已发布的Hadoop指标监视器包括实时队列长度和上载操作计数,因此可以确定何时存在工作积压/数据生成速率与网络带宽之间的不匹配。还可以通过在当前流上调用toString()来记录每个流的统计信息。

  • close()调用中写入操作完成之前,正在写入的文件仍然不可见,该操作将阻塞直到上传完成。

在磁盘fs.s3a.fast.upload.buffer = disk上缓冲上传数据

fs.s3a.fast.upload.buffer设置为disk时,所有数据在上传之前都会缓冲到本地硬盘中。这样可以最大程度地减少消耗的内存量,并消除堆大小,这是排队上载的限制因素,与原始的“直接到磁盘”缓冲完全一样。

<属性>
  <name> fs.s3a.fast.upload.buffer </ name>
  <value>磁盘</ value>
</ property>

<属性>
  <名称> fs.s3a.buffer.dir </名称>
  <value> $ {hadoop.tmp.dir} / s3a </ value>
  <description>用逗号分隔的目录列表,将用于缓冲文件
    上传到。</ description>
</ property>

这是默认的缓冲机制。可以缓冲的数据量受可用磁盘空间量的限制。

在ByteBuffers中缓冲上传数据:fs.s3a.fast.upload.buffer = bytebuffer

fs.s3a.fast.upload.buffer设置为bytebuffer时,所有数据在上传之前都将在“直接” ByteBuffers中进行缓冲。这可能比缓存到磁盘要快,并且,如果磁盘空间很小(例如,很小的EC2 VM),则可能没有太多磁盘空间可缓存。

ByteBuffers是在JVM的内存中创建的,而不是在Java Heap本身中创建的。可以缓冲的数据量受Java运行时,操作系统的限制,对于YARN应用程序,每个容器请求的内存量也受到限制。

上载至S3的带宽越慢,内存不足的风险就越大-因此调整上载设置时需要格外小心。

<属性>
  <name> fs.s3a.fast.upload.buffer </ name>
  <value> bytebuffer </ value>
</ property>

将上传数据缓冲到字节数组中:fs.s3a.fast.upload.buffer = array

如果将fs.s3a.fast.upload.buffer设置为array,那么在上传之前,所有数据都将被缓存在JVM堆中的字节数组中。这可能比缓冲到磁盘更快。

可以缓冲的数据量受JVM堆堆的可用大小限制。S3的写带宽越慢,堆溢出的风险就越大。可以通过调整上传设置来减轻这种风险。

<属性>
  <name> fs.s3a.fast.upload.buffer </ name>
  <value>数组</ value>
</ property>

上传线程调整

两个阵列字节缓冲器缓冲机制可消耗非常大量的内存,分别在堆或堆外。在磁盘缓存机制不会使用太多的内存,但会消耗硬盘容量。

如果在单个进程中要写入许多输出流,则使用的内存或磁盘量是所有流的活动内存/磁盘使用量的倍数。

可能需要进行仔细的调整,以减少内存用尽的风险,尤其是在将数据缓冲在内存中的情况下。

有许多参数可以调整:

  1. 文件系统中可用于数据上载或任何其他排队的文件系统操作的线程总数。这是在fs.s3a.threads.max中设置的

  2. 可以排队等待执行的操作数:,正在等待线程fs.s3a.max.total.tasks

  3. 单个输出流可以处于活动状态的块数,即:由线程上载或在文件系统线程队列中排队:fs.s3a.fast.upload.active.blocks

  4. 空闲线程在退出之前可以在线程池中停留多长时间:fs.s3a.threads.keepalivetime

当达到单个流的活动块的最大允许数量时,在这些活动块的一个或多个上载完成之前,无法从该流上载更多的块。也就是说:一个write()调用将触发一个现在已满的数据块的上载,而将阻塞直到队列中有足够的容量。

这是怎么在一起的?

  • 由于fs.s3a.threads.max中设置的线程池是共享的(并打算在所有线程中使用),因此此处更大的数量可以允许更多并行操作。但是,由于上载需要网络带宽,因此添加更多线程并不能保证加速。

  • 线程池的额外任务队列(fs.s3a.max.total.tasks)涵盖了所有正在进行的后台S3A操作(未来计划包括:并行重命名操作,异步目录操作)。

  • 使用内存缓冲时,较小的fs.s3a.fast.upload.active.blocks限制每个流可以消耗的内存量。

  • 使用磁盘缓冲时,较大的fs.s3a.fast.upload.active.blocks值不会占用太多内存。但这可能导致大量的块与其他文件系统操作竞争。

我们建议使用较低的fs.s3a.fast.upload.active.blocks值;足以启动后台上传而又不会使系统的其他部分超负荷,然后进行试验,看看是否更高的值提供了更高的吞吐量(尤其是从EC2上运行的VM)。

<属性>
  <name> fs.s3a.fast.upload.active.blocks </ name>
  <value> 4 </ value>
  <说明>
    单个输出流可以具有的最大块数
    活动(上载或排队到中央文件系统
    实例的排队操作池。

    这将阻止单个流使共享线程池超载。
  </ description>
</ property>

<属性>
  <name> fs.s3a.threads.max </ name>
  <value> 10 </ value>
  <description>文件系统中可用于数据的线程总数
    上传*或任何其他排队的文件系统操作*。</ description>
</ property>

<属性>
  <name> fs.s3a.max.total.tasks </ name>
  <value> 5 </ value>
  <description>可以排队等待执行的操作数</ description>
</ property>

<属性>
  <name> fs.s3a.threads.keepalivetime </ name>
  <value> 60 </ value>
  <description>线程在空闲之前可以空闲的秒数
    终止。</ description>
</ property>

部分上传失败后清除

剩下的分段上传后,有两种清除机制:-Hadoop s3guard CLI命令,用于按使用期限列出和删除上传。记录在S3Guard部分。-下面介绍了配置参数fs.s3a.multipart.purge

如果大数据流写入操作被中断,则可能有中间分区上载到S3-数据将为此付费。

通过启用fs.s3a.multipart.purge并设置清除时间(以秒为单位),例如86400秒(24小时),可以减少这些费用。在清除时间大于零的情况下实例化S3A FileSystem实例时,它将在启动时删除所有早于此时间的未完成分区请求。

<属性>
  <name> fs.s3a.multipart.purge </ name>
  <value> true </ value>
  <description>如果要清除可能尚未清除的现有分段上传,则为真
     正确完成/中止</ description>
</ property>

<属性>
  <name> fs.s3a.multipart.purge.age </ name>
  <value> 86400 </ value>
  <description>要清除的分段上传的最小年龄(秒)</ description>
</ property>

如果使用fs.s3a.multipart.purge = true实例化了S3A客户端,它将删除整个存储桶中所有过时的上载。也就是说:它将影响从所有应用程序到该存储桶的所有分段上传。

fs.s3a.multipart.purge保留为默认值false意味着客户端将不会尝试任何尝试重置或更改分区速率。

使用此选项的最佳实践是在S3A的正常使用中禁用多部分清除,仅在手动/计划内务操作中启用。

S3A“ fadvise”输入策略支持

S3A Filesystem客户端支持输入策略的概念,类似于Posix fadvise() API调用的概念。这可以调整S3A客户端的行为,以针对不同的用例优化HTTP GET请求。

有关详细信息,请参见通过fadvise提高数据输入性能

指标

可以通过Hadoop的metrics2框架监视S3A指标。S3A创建自己的度量标准系统,称为s3a-file-system,客户端的每个实例将创建自己的度量标准源,以JVM唯一的数字ID命名。

作为一个简单的示例,可以将以下内容添加到hadoop-metrics2.properties中,以每10秒将所有S3A指标写入日志文件:

s3a-file-system.sink.my-metrics-config.class = org.apache.hadoop.metrics2.sink.FileSink
s3a-file-system.sink.my-metrics-config.filename = / var / log / hadoop-yarn / s3a-metrics.out
* .period = 10

该文件中的行的结构如下:

1511208770680 s3aFileSystem.s3aFileSystem:Context = s3aFileSystem,s3aFileSystemId = 892b02bb-7b30-4ffe-80ca-3a9935e1d96e,bucket = bucket,
主机名=主机名-1.hadoop.apache.com,files_created = 1,files_copied = 2,files_copied_bytes = 10000,files_deleted = 5,fake_directories_deleted = 3,
directorys_created = 3,directorys_deleted = 0,忽略错误= 0,op_copy_from_local_file = 0,op_exists = 0,op_get_file_status = 15,op_glob_status = 0,
op_is_directory = 0,op_is_file = 0,op_list_files = 0,op_list_located_status = 0,op_list_status = 3,op_mkdirs = 1,op_rename = 2,object_copy_requests = 0,
object_delete_requests = 6,object_list_requests = 23,object_continue_list_requests = 0,object_metadata_requests = 46,object_multipart_aborted = 0,
object_put_bytes = 0,object_put_requests = 4,object_put_requests_completed = 4,stream_write_failures = 0,stream_write_block_uploads = 0,
stream_write_block_uploads_committed = 0,stream_write_block_uploads_aborted = 0,stream_write_total_time = 0,stream_write_total_data = 0,
s3guard_metadatastore_put_path_request = 10,s3guard_metadatastore_initialization = 0,object_put_requests_active = 0,object_put_bytes_pending = 0,
stream_write_block_uploads_active = 0,stream_write_block_uploads_pending = 0,stream_write_block_uploads_data_pending = 0,
S3guard_metadatastore_put_path_latencyNumOps = 0,S3guard_metadatastore_put_path_latency50thPercentileLatency = 0,
S3guard_metadatastore_put_path_latency75thPercentileLatency = 0,S3guard_metadatastore_put_path_latency90thPercentileLatency = 0,
S3guard_metadatastore_put_path_latency95thPercentileLatency = 0,S3guard_metadatastore_put_path_latency99thPercentileLatency = 0

根据其他配置,也可能会记录来自其他系统,上下文等的指标,例如:

1511208770680metricssystem.MetricsSystem:上下文= metricssystem,主机名= s3a-metrics-4.gce.cloudera.com,NumActiveSources = 1,NumAllSources = 1,
NumActiveSinks = 1,NumAllSinks = 0,Sink_fileNumOps = 2,Sink_fileAvgTime = 1.0,Sink_fileDropped = 0,Sink_fileQsize = 0,SnapshotNumOps = 5,
SnapshotAvgTime = 0.0,PublishNumOps = 2,PublishAvgTime = 0.0,DroppedPubAll = 0

请注意,这些指标当前未包括来自AWS开发工具包本身的低级指标。

其他话题

用distcp复制数据

Hadoop的distcp工具通常用于在Hadoop集群和Amazon S3之间复制数据。有关特定于S3复制的详细信息,请参阅在集群和Amazon S3之间复制数据

DistCp使用更新命令试图做数据增量更新。当文件的长度不同时,验证文件何时不匹配是很容易的,但是当文件大小相同时,则不进行验证。

Distcp通过比较源文件系统和目标文件系统上的文件校验和来解决此问题,即使文件系统具有不兼容的校验和算法,Distcp也会尝试这样做。

S3A连接器可以将HTTP etag标头提供给调用方,作为上传文件的校验和。这样做会破坏hdfs和s3a之间的distcp操作。

因此,默认情况下禁用etag-as-checksum功能。

<属性>
  <name> fs.s3a.etag.checksum.enabled </ name>
  <value> false </ value>
  <说明>
    应该调用getFileChecksum()返回远程服务器的etag值
    宾语。
    警告:如果启用,除非在HDFS和S3之间进行distcp操作,否则它将失败
    -skipcrccheck已设置。
  </ description>
</ property>

如果启用,两个S3存储桶之间的distcp可以使用校验和比较对象。如果它们各自以单个文件PUT上载,或者以多部分PUT 形式上载,则它们的校验和应该相同,这些块大小由fs.s3a.multipart.size配置

要在distcp中禁用校验和验证,请使用-skipcrccheck选项:

hadoop distcp -update -skipcrccheck -numListstatusThreads 40 / user / alice / datasets s3a:// alice-backup / datasets