From 920f07be5cf6e1dbd396d5a1e2599bfe6a9ebda5 Mon Sep 17 00:00:00 2001 From: yuyang733 Date: Wed, 9 Feb 2022 11:53:39 +0800 Subject: [PATCH] feat: add the maxSize limit for the IOThreadPool --- README.md | 59 ++++++++++--------- .../org/apache/hadoop/fs/CosFileSystem.java | 19 ++++-- .../org/apache/hadoop/fs/CosNConfigKeys.java | 3 + 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 64afdf20..6c4f24a6 100644 --- a/README.md +++ b/README.md @@ -198,35 +198,36 @@ done **配置项说明**: -| 属性键 | 说明 | 默认值 | 必填项 | -|:-----------------------------------:|:--------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---:| -|fs.defaultFS | 配置hadoop默认使用的底层文件系统,如果想使用cos作为hadoop默认文件系统,则此项应设置为cosn://bucket-appid,此时可以通过文件路径访问cos对象,如/hadoop/inputdata/test.dat。若不想把cos作为hadoop默认文件系统,则不需要修改此项,当需要访问cos上的对象时,则指定完整的uri即可,如cosn://testbucket-1252681927/hadoop/inputdata/test.dat来访问。| -|fs.cosn.credentials.provider |配置secret id和secret key的获取方式。当前已经支持八种获取方式:1.org.apache.hadoop.fs.auth.SessionCredentialProvider:从请求URI中获取secret id和secret key,其格式为:cosn://{secretId}:{secretKey}@examplebucket-1250000000000/; 2.org.apache.hadoop.fs.auth.SimpleCredentialProvider:从core-site.xml配置文件中读取fs.cosn.userinfo.secretId和fs.cosn.userinfo.secretKey来获取secret id和secret key; 3.org.apache.hadoop.fs.auth.EnvironmentVariableCredentialProvider:从系统环境变量COS_SECRET_ID和COS_SECRET_KEY中获取;4.org.apache.hadoop.fs.auth.SessionTokenCredentialProvider: 设置token;5.org.apache.hadoop.fs.auth.CVMInstanceCredentialsProvider:利用腾讯云云服务器(CVM)绑定的角色,获取访问 COS 的临时密钥; 6.org.apache.hadoop.fs.auth.CPMInstanceCredentialsProvider:利用腾讯云黑石物理机(CPM)绑定的角色,获取访问 COS 的临时密钥;7.org.apache.hadoop.fs.auth.EMRInstanceCredentialsProvider:利用腾讯云 EMR 实例绑定的角色,获取访问 COS 的临时密钥;8.org.apache.hadoop.fs.auth.RangerCredentialsProvider 使用 ranger 进行获取秘钥。 | 如果不指定改配置项,默认会按照以下顺序读取: 1.org.apache.hadoop.fs.auth.SessionCredentialProvider; 2.org.apache.hadoop.fs.auth.SimpleCredentialProvider; 3.org.apache.hadoop.fs.auth.EnvironmentVariableCredentialProvider; 4.org.apache.hadoop.fs.auth.SessionTokenCredentialProvider; 5.org.apache.hadoop.fs.auth.CVMInstanceCredentialsProvider; 6.org.apache.hadoop.fs.auth.CPMInstanceCredentialsProvider; 7.org.apache.hadoop.fs.auth.EMRInstanceCredentialsProvider; |否| -|fs.cosn.useHttps|配置是否使用https协议。| false |否| -|fs.cosn.bucket.endpoint_suffix|指定要连接的COS endpoint,该项为非必填项目。对于公有云COS用户而言,只需要正确填写上述的region配置即可。兼容原配置项:fs.cosn.userinfo.endpoint_suffix。| 无 |否| -|fs.cosn.userinfo.secretId/secretKey| 填写您账户的API 密钥信息。可通过 [云 API 密钥 控制台](https://console.cloud.tencent.com/capi) 查看。| 无 | 是| -|fs.cosn.impl | cosn对FileSystem的实现类,固定为 org.apache.hadoop.fs.CosFileSystem。| 无 |是| -|fs.AbstractFileSystem.cosn.impl | cosn对AbstractFileSy stem的实现类,固定为org.apache.hadoop.fs.CosN。| 无 |是| -|fs.cosn.bucket.region | 请填写您的地域信息,枚举值为 [可用地域](https://cloud.tencent.com/document/product/436/6224) 中的地域简称,如ap-beijing、ap-guangzhou等。 兼容原配置项:fs.cosn.userinfo.region。| 无 | 是| -|fs.cosn.tmp.dir | 请设置一个实际存在的本地目录,运行过程中产生的临时文件会暂时放于此处。| /tmp/hadoop_cos | 否| -|fs.cosn.block.size | CosN文件系统每个block的大小,默认为128MB | ‭134217728‬(128MB) | 否 | -|fs.cosn.upload.buffer | CosN文件系统上传时依赖的缓冲区类型。当前支持三种类型的缓冲区:非直接内存缓冲区(non_direct_memory),直接内存缓冲区(direct_memory),磁盘映射缓冲区(mapped_disk)。非直接内存缓冲区使用的是JVM堆内存,直接内存缓冲区使用的是堆外内存,而磁盘映射缓冲区则是基于内存文件映射得到的缓冲区。| mapped_disk | 否 | -|fs.cosn.upload.buffer.size | CosN文件系统上传时依赖的缓冲区大小,如果指定为-1,则表示不限制。若不限制缓冲区大小,则缓冲区类型必须为mapped_disk。如果指定大小大于0,则要求该值至少大于等于一个block的大小。兼容原配置项:fs.cosn.buffer.size。| 134217728(128MB) |否| -|fs.cosn.upload.part.size | 分块上传时每个part的大小。由于 COS 的分块上传最多只能支持10000块,因此需要预估最大可能使用到的单文件大小。例如,part size 为8MB时,最大能够支持78GB的单文件上传。 part size 最大可以支持到2GB,即单文件最大可支持19TB。| 8388608(8MB) | 否 | -|fs.cosn.upload_thread_pool | 文件流式上传到COS时,并发上传的线程数目 | 10 | 否| -|fs.cosn.copy_thread_pool | 目录拷贝操作时,可用于并发拷贝和删除文件的线程数目 | 3 | 否 | -|fs.cosn.read.ahead.block.size | 预读块的大小 | ‭1048576‬(1MB) | 否 | -|fs.cosn.read.ahead.queue.size | 预读队列的长度 | 8 | 否 | -|fs.cosn.maxRetries | 该配置主要针对读写CosN时候触发频控以及服务端抖动引发的错误进行重试 | 200 | 否 | -|fs.cosn.client.maxRetries | 该配置主要针对COS的客户端侧因为弱网络或DNS服务抖动引发的错误进行重试 | 5 | 否 | -|fs.cosn.retry.interval.seconds | 每次重试的时间间隔,主要针对服务端错误重试(fs.cosn.maxRetries) | 3 | 否 | -|fs.cosn.max.connection.num | 配置COS连接池中维持的最大连接数目,这个数目与单机读写COS的并发有关,建议至少大于或等于单机读写COS的并发数| 1024 | 否| -|fs.cosn.customer.domain | 配置COS的自定义域名,默认为空| 无 | 否| -|fs.cosn.server-side-encryption.algorithm | 配置COS服务端加密算法,支持SSE-C和SSE-COS,默认为空,不加密| 无 | 否| -|fs.cosn.server-side-encryption.key | 当开启COS的SSE-C服务端加密算法时,必须配置SSE-C的密钥,密钥格式为base64编码的AES-256密钥,默认为空,不加密| 无 | 否| -|fs.cosn.crc64.checksum.enabled | 是否开启CRC64校验。默认不开启,此时无法使用`hadoop fs -checksum`命令获取文件的CRC64校验值。| false | 否 | -|fs.cosn.crc32c.checksum.enabled | 是否开启CRC32c校验。默认不开启,此时无法使用hadoop fs -checksum命令获取文件的CRC32C校验值。只能开启一种校验方式| false | 否 | -|fs.cosn.traffic.limit | 上传下载带宽的控制选项,819200 ~ 838860800,单位为bits/s。默认值为-1,表示不限制。 | -1 | 否 | +| 属性键 | 说明 | 默认值 | 必填项 | +|:-----------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---:| +|fs.defaultFS | 配置hadoop默认使用的底层文件系统,如果想使用cos作为hadoop默认文件系统,则此项应设置为cosn://bucket-appid,此时可以通过文件路径访问cos对象,如/hadoop/inputdata/test.dat。若不想把cos作为hadoop默认文件系统,则不需要修改此项,当需要访问cos上的对象时,则指定完整的uri即可,如cosn://testbucket-1252681927/hadoop/inputdata/test.dat来访问。 | +|fs.cosn.credentials.provider | 配置secret id和secret key的获取方式。当前已经支持八种获取方式:1.org.apache.hadoop.fs.auth.SessionCredentialProvider:从请求URI中获取secret id和secret key,其格式为:cosn://{secretId}:{secretKey}@examplebucket-1250000000000/; 2.org.apache.hadoop.fs.auth.SimpleCredentialProvider:从core-site.xml配置文件中读取fs.cosn.userinfo.secretId和fs.cosn.userinfo.secretKey来获取secret id和secret key; 3.org.apache.hadoop.fs.auth.EnvironmentVariableCredentialProvider:从系统环境变量COS_SECRET_ID和COS_SECRET_KEY中获取;4.org.apache.hadoop.fs.auth.SessionTokenCredentialProvider: 设置token;5.org.apache.hadoop.fs.auth.CVMInstanceCredentialsProvider:利用腾讯云云服务器(CVM)绑定的角色,获取访问 COS 的临时密钥; 6.org.apache.hadoop.fs.auth.CPMInstanceCredentialsProvider:利用腾讯云黑石物理机(CPM)绑定的角色,获取访问 COS 的临时密钥;7.org.apache.hadoop.fs.auth.EMRInstanceCredentialsProvider:利用腾讯云 EMR 实例绑定的角色,获取访问 COS 的临时密钥;8.org.apache.hadoop.fs.auth.RangerCredentialsProvider 使用 ranger 进行获取秘钥。 | 如果不指定改配置项,默认会按照以下顺序读取: 1.org.apache.hadoop.fs.auth.SessionCredentialProvider; 2.org.apache.hadoop.fs.auth.SimpleCredentialProvider; 3.org.apache.hadoop.fs.auth.EnvironmentVariableCredentialProvider; 4.org.apache.hadoop.fs.auth.SessionTokenCredentialProvider; 5.org.apache.hadoop.fs.auth.CVMInstanceCredentialsProvider; 6.org.apache.hadoop.fs.auth.CPMInstanceCredentialsProvider; 7.org.apache.hadoop.fs.auth.EMRInstanceCredentialsProvider; |否| +|fs.cosn.useHttps| 配置是否使用https协议。 | false |否| +|fs.cosn.bucket.endpoint_suffix| 指定要连接的COS endpoint,该项为非必填项目。对于公有云COS用户而言,只需要正确填写上述的region配置即可。兼容原配置项:fs.cosn.userinfo.endpoint_suffix。 | 无 |否| +|fs.cosn.userinfo.secretId/secretKey| 填写您账户的API 密钥信息。可通过 [云 API 密钥 控制台](https://console.cloud.tencent.com/capi) 查看。 | 无 | 是| +|fs.cosn.impl | cosn对FileSystem的实现类,固定为 org.apache.hadoop.fs.CosFileSystem。 | 无 |是| +|fs.AbstractFileSystem.cosn.impl | cosn对AbstractFileSy stem的实现类,固定为org.apache.hadoop.fs.CosN。 | 无 |是| +|fs.cosn.bucket.region | 请填写您的地域信息,枚举值为 [可用地域](https://cloud.tencent.com/document/product/436/6224) 中的地域简称,如ap-beijing、ap-guangzhou等。 兼容原配置项:fs.cosn.userinfo.region。 | 无 | 是| +|fs.cosn.tmp.dir | 请设置一个实际存在的本地目录,运行过程中产生的临时文件会暂时放于此处。 | /tmp/hadoop_cos | 否| +|fs.cosn.block.size | CosN文件系统每个block的大小,默认为128MB | ‭134217728‬(128MB) | 否 | +|fs.cosn.upload.buffer | CosN文件系统上传时依赖的缓冲区类型。当前支持三种类型的缓冲区:非直接内存缓冲区(non_direct_memory),直接内存缓冲区(direct_memory),磁盘映射缓冲区(mapped_disk)。非直接内存缓冲区使用的是JVM堆内存,直接内存缓冲区使用的是堆外内存,而磁盘映射缓冲区则是基于内存文件映射得到的缓冲区。 | mapped_disk | 否 | +|fs.cosn.upload.buffer.size | CosN文件系统上传时依赖的缓冲区大小,如果指定为-1,则表示不限制。若不限制缓冲区大小,则缓冲区类型必须为mapped_disk。如果指定大小大于0,则要求该值至少大于等于一个block的大小。兼容原配置项:fs.cosn.buffer.size。 | 134217728(128MB) |否| +|fs.cosn.upload.part.size | 分块上传时每个part的大小。由于 COS 的分块上传最多只能支持10000块,因此需要预估最大可能使用到的单文件大小。例如,part size 为8MB时,最大能够支持78GB的单文件上传。 part size 最大可以支持到2GB,即单文件最大可支持19TB。 | 8388608(8MB) | 否 | +|fs.cosn.upload_thread_pool | 文件流式上传到COS时,并发上传的线程数目 | 10 | 否| +|fs.cosn.io_thread_pool.maxSize | 用于限制 IO 线程池的最大线程数 | 2 * CPU cores + 1 | 否 | +|fs.cosn.copy_thread_pool | 目录拷贝操作时,可用于并发拷贝和删除文件的线程数目 | 3 | 否 | +|fs.cosn.read.ahead.block.size | 预读块的大小 | ‭1048576‬(1MB) | 否 | +|fs.cosn.read.ahead.queue.size | 预读队列的长度 | 8 | 否 | +|fs.cosn.maxRetries | 该配置主要针对读写CosN时候触发频控以及服务端抖动引发的错误进行重试 | 200 | 否 | +|fs.cosn.client.maxRetries | 该配置主要针对COS的客户端侧因为弱网络或DNS服务抖动引发的错误进行重试 | 5 | 否 | +|fs.cosn.retry.interval.seconds | 每次重试的时间间隔,主要针对服务端错误重试(fs.cosn.maxRetries) | 3 | 否 | +|fs.cosn.max.connection.num | 配置COS连接池中维持的最大连接数目,这个数目与单机读写COS的并发有关,建议至少大于或等于单机读写COS的并发数 | 1024 | 否| +|fs.cosn.customer.domain | 配置COS的自定义域名,默认为空 | 无 | 否| +|fs.cosn.server-side-encryption.algorithm | 配置COS服务端加密算法,支持SSE-C和SSE-COS,默认为空,不加密 | 无 | 否| +|fs.cosn.server-side-encryption.key | 当开启COS的SSE-C服务端加密算法时,必须配置SSE-C的密钥,密钥格式为base64编码的AES-256密钥,默认为空,不加密 | 无 | 否| +|fs.cosn.crc64.checksum.enabled | 是否开启CRC64校验。默认不开启,此时无法使用`hadoop fs -checksum`命令获取文件的CRC64校验值。 | false | 否 | +|fs.cosn.crc32c.checksum.enabled | 是否开启CRC32c校验。默认不开启,此时无法使用hadoop fs -checksum命令获取文件的CRC32C校验值。只能开启一种校验方式 | false | 否 | +|fs.cosn.traffic.limit | 上传下载带宽的控制选项,819200 ~ 838860800,单位为bits/s。默认值为-1,表示不限制。 | -1 | 否 | ### 开始使用 diff --git a/src/main/java/org/apache/hadoop/fs/CosFileSystem.java b/src/main/java/org/apache/hadoop/fs/CosFileSystem.java index 35f7cf67..f1d13156 100644 --- a/src/main/java/org/apache/hadoop/fs/CosFileSystem.java +++ b/src/main/java/org/apache/hadoop/fs/CosFileSystem.java @@ -161,18 +161,27 @@ public void initialize(URI uri, Configuration conf) throws IOException { Preconditions.checkArgument(readAheadPoolSize > 0, String.format("The readAheadQueueSize[%d] should be positive.", readAheadPoolSize)); // 核心线程数取用户配置的为准,最大线程数结合用户配置和IO密集型任务的最优线程数来看 - int ioThreadPoolSize = uploadThreadPoolSize + readAheadPoolSize; + int ioCoreTaskSize = uploadThreadPoolSize + readAheadPoolSize; int ioMaxTaskSize = Math.max(uploadThreadPoolSize + readAheadPoolSize, Runtime.getRuntime().availableProcessors() * 2 + 1); + if (this.getConf().get(CosNConfigKeys.IO_THREAD_POOL_MAX_SIZE_KEY) != null) { + int ioThreadPoolMaxSize = this.getConf().getInt( + CosNConfigKeys.IO_THREAD_POOL_MAX_SIZE_KEY, CosNConfigKeys.DEFAULT_IO_THREAD_POOL_MAX_SIZE); + Preconditions.checkArgument(ioThreadPoolMaxSize > 0, + String.format("The ioThreadPoolMaxSize[%d] should be positive.", ioThreadPoolMaxSize)); + // 如果设置了 IO 线程池的最大限制,则整个线程池需要被限制住 + ioCoreTaskSize = Math.min(ioCoreTaskSize, ioThreadPoolMaxSize); + ioMaxTaskSize = ioThreadPoolMaxSize; + } long threadKeepAlive = this.getConf().getLong( CosNConfigKeys.THREAD_KEEP_ALIVE_TIME_KEY, CosNConfigKeys.DEFAULT_THREAD_KEEP_ALIVE_TIME); Preconditions.checkArgument(threadKeepAlive > 0, String.format("The threadKeepAlive [%d] should be positive.", threadKeepAlive)); this.boundedIOThreadPool = new ThreadPoolExecutor( - ioThreadPoolSize, ioMaxTaskSize, + ioCoreTaskSize, ioMaxTaskSize, threadKeepAlive, TimeUnit.SECONDS, - new LinkedBlockingQueue(ioThreadPoolSize), + new LinkedBlockingQueue(ioCoreTaskSize), new ThreadFactoryBuilder().setNameFormat("cos-transfer-shared-%d").setDaemon(true).build(), new RejectedExecutionHandler() { @Override @@ -201,10 +210,8 @@ public void rejectedExecution(Runnable r, ); Preconditions.checkArgument(copyThreadPoolSize > 0, String.format("The copyThreadPoolSize[%d] should be positive.", copyThreadPoolSize)); - int maxCopyTaskSize = Math.max(copyThreadPoolSize, - Runtime.getRuntime().availableProcessors() * 2 + 1); this.boundedCopyThreadPool = new ThreadPoolExecutor( - copyThreadPoolSize, maxCopyTaskSize, + copyThreadPoolSize, copyThreadPoolSize, threadKeepAlive, TimeUnit.SECONDS, new LinkedBlockingQueue(copyThreadPoolSize), new ThreadFactoryBuilder().setNameFormat("cos-copy-%d").setDaemon(true).build(), diff --git a/src/main/java/org/apache/hadoop/fs/CosNConfigKeys.java b/src/main/java/org/apache/hadoop/fs/CosNConfigKeys.java index be72d404..5533483b 100644 --- a/src/main/java/org/apache/hadoop/fs/CosNConfigKeys.java +++ b/src/main/java/org/apache/hadoop/fs/CosNConfigKeys.java @@ -67,6 +67,9 @@ public class CosNConfigKeys extends CommonConfigurationKeys { public static final String UPLOAD_THREAD_POOL_SIZE_KEY = "fs.cosn.upload_thread_pool"; public static final int DEFAULT_UPLOAD_THREAD_POOL_SIZE = 10; + public static final String IO_THREAD_POOL_MAX_SIZE_KEY = "fs.cosn.io_thread_pool.maxSize"; + public static final int DEFAULT_IO_THREAD_POOL_MAX_SIZE = 2 * Runtime.getRuntime().availableProcessors() + 1; + public static final String COPY_THREAD_POOL_SIZE_KEY = "fs.cosn.copy_thread_pool"; public static final int DEFAULT_COPY_THREAD_POOL_SIZE = 3;