AmazonS3Client Single connection Vs new connection for each call C#

给你一囗甜甜゛ 提交于 2021-01-05 07:50:07

问题


I am using AmazonS3Client to Read/Write data to S3 Object Storage. In my code i am creating a new connection everytime while doing operations like Read,List Buckets, Upload, Rename, Delete etc. After deploying my application to production i encountered some performance issues. After going throughh few blogs it was recommended to use single amazonS3 client connection. My code below -> For every below CRUD operations if you see i am creating a new connection and then disposing it by using block. I am planning to have single connection and use it without using block on every call. Does maintaining a single connection good choice ? I have ~400 users accessing application at the same time.

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;
        }
}

Planning to use Singleton as below and removing using block ->

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;
        }
}

回答1:


Actually you can safely reuse it, according to the docs it is not a bad idea to create and reuse a client. But creating a new client is not very expensive:

The best-known aspect of the AWS SDK for .NET are the various service clients that you can use to interact with AWS. Client objects are thread safe, disposable, and can be reused. (Client objects are inexpensive, so you are not incurring a large overhead by constructing multiple instances, but it’s not a bad idea to create and reuse a client.)

Thus, according to this the performance benefits are probably not that huge. But since there is a small cost to creating a new client I would always reuse the client. That said, according to the docs your code

            using (AmazonS3Client StorageClient = GetClient())
            {
                Response = StorageClient.ListBuckets();
            }

is not really bad, but just a bit less efficient than using a singleton. If you think it hurts your performance in a noticable way, best bet is to measure it and if it is really the cause refactor to using a singleton.




回答2:


As one of the authors of the AWS .NET SDK I can give a little more context. Under the cover the AmazonS3Client along with all of the other service clients in the SDK it manages a pool of HttpClients which are the expensive object to create. So when you are creating a new AmazonS3Client the SDK is reusing an HttpClient from a pool the SDK is managing.

If you are using a proxy with proxy credentials then the SDK does have to create a new HttpClient each time a service client is created.

An area where there could be potential performance issues with creating service clients all the time is determining the AWS credentials to use when an AWSCredentials object is not passed into the constructor. That means each service client will have to resolve the credentials which if you are using an assume role profile that could cause a lot of extra calls to perform the assume role. Getting credentials from instance metadata is optimized so that only one thread is refreshing those credentials per process.




回答3:


Both are valid approach but you'll certainly gain code efficiency using a singleton.

Moreover, dependency injection is promoted by AWS as the right pattern when it comes to using clients. For example, new AWS service CodeGuru profiler highlights multiple client instances as a source of optimization.

See also : https://aws.amazon.com/fr/blogs/developer/working-with-dependency-injection-in-net-standard-inject-your-aws-clients-part-1/



来源:https://stackoverflow.com/questions/64145548/amazons3client-single-connection-vs-new-connection-for-each-call-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!