Проблемы с производительностью AWS S3 Java SDK - PullRequest
0 голосов
/ 27 апреля 2020

Мы использовали AWS Java SDK S3 API для загрузки и загрузки вложений. В последнее время наблюдается снижение производительности при сохранении и получении файлов из корзины S3. В дампах потоков, связанных с компонентом EC2CredentialsFetcher клиентского SDK S3, периодически возникала проблема с высокой нагрузкой. Мы заметили, что SDK блокирует / занимает значительное время при поиске учетных данных из экземпляра EC2.

Мы используем AWS Java SDK версию - 1.11.731 и ниже приведен фрагмент кода для создания экземпляра клиента AmazonS3 при запуске приложения и повторного использования в течение срока службы приложения.

AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
    AmazonS3 client = builder
                .withClientConfiguration( clientConfigurationInstance )
                .withRegion( getRegion() )
                .withForceGlobalBucketAccessEnabled( true )
                .build();

Пример трассировки стека, приведенной в дампе потока, показан ниже:

"http-apr-8080-exec-82" Id=103100 in BLOCKED on lock=com.amazonaws.auth.EC2CredentialsFetcher@34fe4624
     owned by http-apr-8080-exec-32 Id=20565 BlockedCount : 343, BlockedTime : -1, WaitedCount : 42536, WaitedTime : -1
    at com.amazonaws.auth.EC2CredentialsFetcher.fetchCredentials(EC2CredentialsFetcher.java:112)
    at com.amazonaws.auth.EC2CredentialsFetcher.getCredentials(EC2CredentialsFetcher.java:82)
    at com.amazonaws.auth.InstanceProfileCredentialsProvider.getCredentials(InstanceProfileCredentialsProvider.java:141)
    at com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper.getCredentials(EC2ContainerCredentialsProviderWrapper.java:51)
    at com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials(AWSCredentialsProviderChain.java:110)
    at com.amazonaws.services.s3.S3CredentialsProviderChain.getCredentials(S3CredentialsProviderChain.java:35)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1119)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:759)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:723)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:716)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:699)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:667)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:649)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:513)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4221) 
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4168)
    at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:1249)
    at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:1224)

Как предложено командой поддержки AWS и здесь https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html#refresh -credentials , мы модифицированный код создания клиента для использования асинхронного механизма IMDS: refre sh учетных данных, как показано ниже:

AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
    builder.setCredentials( InstanceProfileCredentialsProvider.createAsyncRefreshingProvider(true) );
    AmazonS3 client = builder
                .withClientConfiguration( clientConfigurationInstance )
                .withRegion( getRegion() )
                .withForceGlobalBucketAccessEnabled( true )
                .build();

Идея состоит в том, чтобы обновить sh учетные данные в потоке демона, чтобы пользователь API загрузки / выгрузки файлов загружал потоки не пострадают при обновлении учетных данных и, следовательно, надеются, что конечные пользователи не заметят каких-либо проблем с производительностью.

Это изменение не привело к каким-либо преимуществам в производительности, а привело к появлению других проблем в системе с интеграцией S3 , Мы наблюдаем приведенное ниже исключение из потока демонов imds-credentials-refre sh периодически при высокой нагрузке:

    2020-04-24 01:34:59,466 [-credentials-refresh] [          ] [                    ] [                    ] (anceProfileCredentialsProvider) ERROR   - Failed to connect to service endpoint: 
    com.amazonaws.SdkClientException: Failed to connect to service endpoint: 
        at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:100) ~[aws-java-sdk-core-1.11.731.jar:?]
        at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:70) ~[aws-java-sdk-core-1.11.731.jar:?]
        at com.amazonaws.internal.InstanceMetadataServiceResourceFetcher.readResource(InstanceMetadataServiceResourceFetcher.java:75) ~[aws-java-sdk-core-1.11.731.jar:?]
        at com.amazonaws.internal.EC2ResourceFetcher.readResource(EC2ResourceFetcher.java:66) ~[aws-java-sdk-core-1.11.731.jar:?]
        at com.amazonaws.auth.InstanceMetadataServiceCredentialsFetcher.getCredentialsResponse(InstanceMetadataServiceCredentialsFetcher.java:47) ~[aws-java-sdk-core-1.11.731.jar:?]
        at com.amazonaws.auth.BaseCredentialsFetcher.fetchCredentials(BaseCredentialsFetcher.java:112) ~[aws-java-sdk-core-1.11.731.jar:?]
        at com.amazonaws.auth.BaseCredentialsFetcher.getCredentials(BaseCredentialsFetcher.java:68) ~[aws-java-sdk-core-1.11.731.jar:?]
        at com.amazonaws.auth.InstanceProfileCredentialsProvider$2.run(InstanceProfileCredentialsProvider.java:118) ~[aws-java-sdk-core-1.11.731.jar:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_171]
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) ~[?:1.8.0_171]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_171]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[?:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_171]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
    Caused by: java.net.SocketTimeoutException: Read timed out
        at java.net.SocketInputStream.socketRead0(Native Method) ~[?:1.8.0_171]
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[?:1.8.0_171]
        at java.net.SocketInputStream.read(SocketInputStream.java:171) ~[?:1.8.0_171]
        at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[?:1.8.0_171]
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) ~[?:1.8.0_171]
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:286) ~[?:1.8.0_171]
        at java.io.BufferedInputStream.read(BufferedInputStream.java:345) ~[?:1.8.0_171]
        at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735) ~[?:1.8.0_171]
        at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678) ~[?:1.8.0_171]
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587) ~[?:1.8.0_171]
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492) ~[?:1.8.0_171]
        at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) ~[?:1.8.0_171]
        at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:82) ~[aws-java-sdk-core-1.11.731.jar:?]
        ... 14 more

Исключение происходило относительно часто, 1074 раза в 5 случаях за выходные. В # 1) Влияет ли это на загрузку / выгрузку файлов с помощью Java SDK клиента AmazonS3 (упомянутого выше)? Что может быть причиной root за этими тайм-аутами сокета? Какими должны быть наши дальнейшие шаги для ее решения? Это проблема с S3 SDK или с подключением EC2 и IMDS?

Кроме того, периодически при высокой нагрузке невозможно загрузить / загрузить файлы, и при попытке загрузить файл наблюдается следующее исключение:

java.io.IOException: Cannot find S3 object at /Production/prod1/filestorage/attachments/email-content-1587156640090_MM-6248348.html
        at com.myorg.internal.cloud.aws.s3.S3WrapperInputStream.startRead(S3WrapperInputStream.java:142)
        at com.myorg.internal.cloud.aws.s3.S3WrapperInputStream.read(S3WrapperInputStream.java:116)
        ...
        at java.lang.Thread.run(Thread.java:748)
    Caused by: com.amazonaws.SdkClientException: Failed to connect to service endpoint: 
        at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:100)
        at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:70)
        at com.amazonaws.internal.InstanceMetadataServiceResourceFetcher.readResource(InstanceMetadataServiceResourceFetcher.java:75)
        at com.amazonaws.internal.EC2ResourceFetcher.readResource(EC2ResourceFetcher.java:66)
        at com.amazonaws.auth.InstanceMetadataServiceCredentialsFetcher.getCredentialsResponse(InstanceMetadataServiceCredentialsFetcher.java:47)
        at com.amazonaws.auth.BaseCredentialsFetcher.fetchCredentials(BaseCredentialsFetcher.java:112)
        at com.amazonaws.auth.BaseCredentialsFetcher.getCredentials(BaseCredentialsFetcher.java:68)
        at com.amazonaws.auth.InstanceProfileCredentialsProvider.getCredentials(InstanceProfileCredentialsProvider.java:166)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1251)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1272)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1139)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:796)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:764)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:738)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:698)
        at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:680)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:544)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:524)
        at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:5052)
        at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4998)
        at com.amazonaws.services.s3.AmazonS3Client.getObject(AmazonS3Client.java:1486)
        at com.amazonaws.services.s3.AmazonS3Client.getObject(AmazonS3Client.java:1341)
        at com.myorg.internal.cloud.aws.s3.S3WrapperInputStream.startRead(S3WrapperInputStream.java:134)
        ... 198 more
    Caused by: java.net.SocketTimeoutException: Read timed out
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
        at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
        at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
        at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
        at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:82)
        ... 220 more

Q # 2) После включения асинхронного refre sh учетных данных IMDS каждый или любой из файловых / создаваемых файловых API-интерфейсов вызывает учетные данные поиска из IMDS? В # 3) Как избежать тайм-аутов и добиться относительно более быстрого согласования вызовов API? Q # 4) В соответствии с https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instancedata -throttling , служба метаданных экземпляра регулируется. Как этого избежать или решить связанные с этим проблемы?

Спасибо, Чандра

...