我正在使用 AmazonS3Client 将数据读取/写入 S3 对象存储。在我的代码中,我每次执行读取、列出存储桶、上传、重命名、删除等操作时都会创建一个新连接。将应用程序部署到生产环境后,我遇到了一些性能问题。在浏览了几篇博客后,建议使用单个 amazonS3 客户端连接。我的代码如下 -> 对于下面的每个 CRUD 操作,如果您看到我正在创建一个新连接,然后通过使用 block 来处理它。我计划拥有单个连接并使用它,而不在每次调用时使用块。维持单一连接是一个好的选择吗?我有大约 400 个用户同时访问应用程序。
public ObjectFileInfo(string path)
{
StorageClient = ObjectFileManager.GetClient();
objectFileInfo = ObjectFileManager.getFileInfo(StorageClient, path);
}
public class ObjectFileManager
{
public static Amazon.S3.AmazonS3Client GetClient()
{
AmazonS3Config Config = new AmazonS3Config();
AmazonS3Client StorageClient;
Config.RegionEndpoint = null;
Config.ServiceURL = ConfigurationManager.NGDMSobjECSEndPoint;
Config.AllowAutoRedirect = true;
Config.ForcePathStyle = true;
Config.Timeout = TimeSpan.FromMinutes(30);
StorageClient = new AmazonS3Client(ConfigurationManager.NGDMSobjECSUser, ConfigurationManager.NGDMSobjECSKey, Config);
return StorageClient;
}
public static string[] ListBuckets()
{
ListBucketsResponse Response;
//Creating AmazonS3Client and disposing it in using
using (AmazonS3Client StorageClient = GetClient())
{
Response = StorageClient.ListBuckets();
}
var BucketNames = from Bucket in Response.Buckets select Bucket.BucketName;
return BucketNames.ToArray();
}
public static bool DeleteFile(string keyName)
{
var delRequest = new DeleteObjectRequest
{
BucketName = bucketName,
Key = keyName
};
//Creating AmazonS3Client and disposing it in using
using (AmazonS3Client StorageClient = GetClient())
{
StorageClient.DeleteObject(delRequest);
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
计划如下使用 Singleton 并删除 using 块 ->
class S3ObjectStorageClient
{
/// <summary>
/// Singleton implementation of Object Storage Client
/// </summary>
private S3ObjectStorageClient()
{
}
public static AmazonS3Client Client
{
get
{
return S3Client.clientInstance;
}
}
/// <summary>
/// Nested private class to ensure Singleton
/// </summary>
private class S3Client
{
static S3Client()
{
}
internal static readonly AmazonS3Client clientInstance = ObjectFileManager.GetClient();
}
}
public ObjectFileInfo(string path)
{
StorageClient = S3ObjectStorageClient.Client; //Singleton
objectFileInfo = ObjectFileManager.getFileInfo(StorageClient, path);
}
public static string[] ListBuckets()
{
ListBucketsResponse Response;
//Singleton and removed using block
AmazonS3Client StorageClient = S3ObjectStorageClient.Client;
Response = StorageClient.ListBuckets();
var BucketNames = from Bucket in Response.Buckets select Bucket.BucketName;
return BucketNames.ToArray();
}
public static bool DeleteFile(string keyName)
{
var delRequest = new DeleteObjectRequest
{
BucketName = bucketName,
Key = keyName
};
//Singleton and removed using block
AmazonS3Client StorageClient = S3ObjectStorageClient.Client;
StorageClient.DeleteObject(delRequest);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 10
作为 AWS .NET SDK 的作者之一,我可以提供更多背景信息。在底层,AmazonS3Client 以及 SDK 中的所有其他服务客户端管理着一个 HttpClient 池,这些对象的创建成本很高。因此,当您创建新的 AmazonS3Client 时,SDK 会重用 SDK 管理的池中的 HttpClient。
如果您使用具有代理凭据的代理,则每次创建服务客户端时,SDK 都必须创建一个新的 HttpClient。
创建服务客户端时始终可能存在潜在性能问题的一个领域是,当 AWSCredentials 对象未传递到构造函数时,确定要使用的 AWS 凭证。这意味着每个服务客户端都必须解析凭据,如果您使用假设角色配置文件,可能会导致大量额外的调用来执行假设角色。从实例元数据获取凭证经过优化,以便每个进程只有一个线程刷新这些凭证。
实际上,您可以安全地重用它,根据文档,创建和重用客户端并不是一个坏主意。但创建一个新客户端并不是很昂贵:
\n\n\n适用于 .NET 的 AWS 开发工具包最著名的方面是可用于与 AWS 交互的各种服务客户端。客户端对象是线程安全的、一次性的并且可以重用。(客户端对象很便宜,因此构建多个实例不会产生大量开销,但创建和重用客户端\xe2\x80\x99并不是一个坏主意。)
\n
因此,根据这一点,性能优势可能不会那么大。但由于创建新客户端的成本很小,我总是会重用该客户端。也就是说,根据您的代码的文档
\n using (AmazonS3Client StorageClient = GetClient())\n {\n Response = StorageClient.ListBuckets();\n }\nRun Code Online (Sandbox Code Playgroud)\n并不是很糟糕,但只是比使用单例效率低一点。如果您认为这会显着损害您的性能,最好的办法是衡量它,看看它是否确实是使用单例重构的原因。
\n