문제 해결 FAQ - AWS SDK for Java 2.x

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

문제 해결 FAQ

애플리케이션에서 AWS SDK for Java 2.x를 사용할 때 이 주제에 나열된 런타임 오류가 발생할 수 있습니다. 여기에서 제안 사항을 사용하면 근본 원인을 파악하고 오류를 해결하는 데 도움이 됩니다.

java.net.SocketException: 연결 재설정’ 또는 ‘서버가 응답을 완료하지 못함’ 오류 해결 방법

연결 재설정 오류는 호스트, AWS 서비스 또는 중개자(예: NAT 게이트웨이, 프록시, 로드 밸런서)가 요청이 완료되기 전에 연결을 종료했음을 나타냅니다. 원인에는 여러 가지가 있으므로 솔루션을 찾으려면 연결이 종료되는 이유를 알아야 합니다. 다음 항목으로 인해 일반적으로 연결이 종료됩니다.

  • 연결이 비활성 상태입니다. 이는 스트리밍 작업에서 데이터가 일정 기간 동안 유선에 기록되지 않아 중개자가 연결이 멈춘 것으로 감지하여 종료되는 경우에 흔히 발생합니다. 이를 방지하려면 애플리케이션에서 데이터를 적극적으로 다운로드하거나 업로드해야 합니다.

  • HTTP 또는 SDK 클라이언트를 종료했습니다. 사용 중인 리소스는 종료하지 않아야 합니다.

  • 잘못 구성된 프록시입니다. 문제가 해결되었는지 확인하기 위해 구성한 프록시를 우회해 봅니다. 이렇게 해서 문제가 해결되면 어떤 이유로든 프록시는 연결을 종료합니다. 특정 프록시를 조사하여 연결을 닫는 이유를 확인합니다.

문제를 파악할 수 없는 경우 네트워크의 클라이언트 엣지에서 영향을 받는 연결에 대해 TCP 덤프를 실행합니다(예: 제어하는 프록시 이후).

AWS 엔드포인트가 TCP RST를 전송(재설정)하는 경우 영향을 받는 서비스에 문의하여 재설정이 발생하는 이유를 확인할 수 있는지 알아봅니다. 문제가 발생한 때의 요청 ID와 타임스탬프를 제공할 준비를 합니다. 또한 AWS 지원 팀은 애플리케이션이 전송 및 수신하는 바이트와 시기를 정확하게 보여주는 유선 로그의 이점을 누릴 수 있습니다.

‘연결 제한 시간’을 수정하는 방법

연결 제한 시간 오류는 호스트, AWS 서비스 또는 중개자(예: NAT 게이트웨이, 프록시, 로드 밸런서)가 구성된 연결 제한 시간 내에 서버와 새 연결을 설정하지 못했음을 나타냅니다. 다음 항목에서는 이 문제의 일반적인 원인을 설명합니다.

  • 구성된 연결 제한 시간이 너무 짧습니다. 기본적으로 연결 제한 시간은 AWS SDK for Java 2.x에서 2초입니다. 연결 제한 시간을 너무 작게 설정하면 이 오류가 발생할 수 있습니다. 권장 연결 제한 시간은 리전 내 호출만 수행하는 경우 1초, 크로스 리전 요청을 수행하는 경우 3초입니다.

  • 잘못 구성된 프록시입니다. 문제 해결 여부를 보려면 구성한 프록시를 우회해 봅니다. 이렇게 해서 문제가 해결되면 연결 제한 시간의 원인은 프록시입니다. 특정 프록시를 조사하여 이 문제가 발생하는 이유를 확인합니다.

문제를 파악할 수 없는 경우 네트워크의 클라이언트 엣지에서 영향을 받는 연결에 대해 TCP 덤프를 실행하여(예: 제어하는 프록시 이후) 네트워크 문제를 조사합니다.

java.net.SocketTimeoutException: 읽기 제한 시간’을 수정하는 방법

읽기 제한 시간 오류는 JVM이 기본 운영 체제에서 데이터를 읽으려고 시도했지만 SDK를 통해 구성된 시간 내에 데이터가 반환되지 않았음을 나타냅니다. 이 오류는 운영 체제, AWS 서비스 또는 중개자(예: NAT 게이트웨이, 프록시, 로드 밸런서)가 JVM에서 예상한 시간 내에 데이터를 전송하지 못하는 경우에 발생할 수 있습니다. 원인에는 여러 가지가 있으므로 솔루션을 찾으려면 데이터가 반환되지 않는 이유를 알아야 합니다.

네트워크의 클라이언트 엣지에서 영향을 받는 연결에 대해 TCP 덤프를 실행해 봅니다(예: 제어하는 프록시 이후).

AWS 엔드포인트가 TCP RST(재설정)를 전송하고 있는 경우 영향을 받는 서비스에 문의하세요. 문제가 발생한 때의 요청 ID와 타임스탬프를 제공할 준비를 합니다. 또한 AWS 지원 팀은 애플리케이션이 전송 및 수신하는 바이트와 시기를 정확하게 보여주는 유선 로그의 이점을 누릴 수 있습니다.

‘HTTP 요청을 실행할 수 없음: 풀에서 연결을 기다리는 제한 시간’ 오류를 해결하는 방법

이 오류는 요청이 지정된 최대 시간 내에 풀에서 연결을 가져올 수 없음을 나타냅니다. 문제를 해결하려면 SDK 클라이언트 측 지표를 사용하여 Amazon CloudWatch에 지표를 게시하는 것이 좋습니다. HTTP 지표는 근본 원인의 범위를 좁히는 데 도움이 될 수 있습니다. 다음 항목에서는 이 오류의 일반적인 원인을 설명합니다.

  • 연결 누수입니다. LeasedConcurrency , AvailableConcurrencyMaxConcurrency 지표를 확인하여 이를 조사할 수 있습니다. LeasedConcurrencyMaxConcurrency에 도달할 때까지 증가하지만 감소하지 않으면 연결 누수가 발생할 수 있습니다. 누수의 일반적인 원인은 S3 getObject 메서드 등의 스트리밍 작업이 종료되지 않기 때문입니다. 애플리케이션은 가능한 한 빨리 입력 스트림에서 모든 데이터를 읽고 나중에 입력 스트림을 종료하는 것이 좋습니다. 다음 차트는 연결 누수에 대한 SDK 지표를 보여줍니다.

    연결 누수 가능성을 보여주는 CloudWatch 지표의 스크린샷입니다.
  • 연결 풀 결핍입니다. 이는 요청 속도가 너무 높고 구성된 연결 풀 크기가 요청 수요를 충족할 수 없는 경우에 발생할 수 있습니다. 기본 연결 풀 크기는 50이며 풀의 연결이 최대에 도달하면 HTTP 클라이언트는 연결을 사용할 수 있을 때까지 수신 요청을 대기열에 넣습니다. 다음 차트는 연결 풀 결핍에 대한 SDK 지표의 모습을 보여줍니다.

    연결 풀 결핍의 모습을 보여주는 CloudWatch 지표의 스크린샷입니다.

    이 문제를 완화하려면 다음 작업 중 하나를 수행하는 것이 좋습니다.

    • 연결 풀 크기를 늘립니다.

    • 획득 제한 시간을 늘립니다.

    • 요청 속도를 늦춥니다.

    최대 연결 수를 늘리면 클라이언트 처리량이 증가할 수 있습니다(네트워크 인터페이스가 이미 완전히 활용되지 않은 경우). 그러나 결국 프로세스에서 사용하는 파일 설명자 수에 대한 운영 체제 제한에 도달할 수 있습니다. 이미 네트워크 인터페이스를 완전히 사용하고 있거나 연결 수를 더 이상 늘릴 수 없는 경우 획득 제한 시간을 늘립니다. 값이 늘면 제한 시간을 초과하기 전에 요청을 통해 연결을 획득할 수 있는 추가 시간을 확보할 수 있습니다. 연결 시간이 확보되지 않으면 후속 요청 역시 제한 시간을 초과합니다.

    처음 두 메커니즘을 사용하여 문제를 해결할 수 없는 경우 다음 옵션을 시도하여 요청 속도를 늦춥니다.

    • 대규모 트래픽 버스트가 클라이언트에 과부하를 주지 않도록 요청을 완화합니다.

    • AWS 서비스에 대한 호출을 더 효율적으로 수행할 수 있습니다.

    • 요청을 보내는 호스트 수를 늘립니다.

  • I/O 스레드가 사용 중입니다. 이는 NettyNioAsyncHttpClient에서 비동기식 SDK 클라이언트를 사용하는 경우에만 적용됩니다. 풀에서 연결을 사용할 수 있고 AvailableConcurrency 지표가 낮지 않지만 ConcurrencyAcquireDuration이 높으면 I/O 스레드가 요청을 처리할 수 없기 때문일 수 있습니다. 이는 I/O 스레드를 차단할 수 있으므로 Runnable:run향후 완료 실행자로 전달하고 향후 응답 완료 체인에서 시간이 많이 걸리는 작업을 수행하지 않아야 합니다. 그렇지 않은 경우 eventLoopGroupBuilder 메서드를 사용하여 I/O 스레드 수를 늘리는 것이 좋습니다. 참조용으로 NettyNioAsyncHttpClient 인스턴스의 기본 I/O 스레드 수는 호스트의 CPU 코어 수의 2배입니다.

  • TLS 핸드셰이크 지연 시간이 높습니다. AvailableConcurrency 지표가 거의 0이고 LeasedConcurrencyMaxConcurrency보다 낮은 경우 TLS 핸드셰이크 지연 시간이 높기 때문일 수 있습니다. 다음 차트는 높은 TLS 핸드셰이크 지연 시간에 대한 SDK 지표의 모습을 보여줍니다.

    높은 TLS 핸드셰이크 지연 시간을 나타낼 수 있는 CloudWatch 지표의 스크린샷입니다.

    CRT를 기반으로 하지 않는 Java SDK에서 제공하는 HTTP 클라이언트의 경우 TLS 로그를 사용하여 TLS 문제를 해결해 봅니다. AWS CRT 기반 HTTP 클라이언트의 경우 AWS CRT 로그를 사용해 봅니다. AWS 엔드포인트가 TLS 핸드셰이크를 수행하는 데 시간이 오래 걸리는 것으로 보이면 영향을 받는 서비스에 문의해야 합니다.

NoClassDefFoundError, NoSuchMethodError 또는 NoSuchFieldError를 수정하는 방법

NoClassDefFoundError는 런타임에 클래스를 로드할 수 없음을 나타냅니다. 이 오류의 가장 일반적인 2가지 원인은 다음과 같습니다.

  • JAR이 누락되었거나 잘못된 버전의 JAR이 클래스 경로에 있기 때문에 클래스가 클래스 경로에 존재하지 않습니다.

  • 정적 이니셜라이저가 예외를 발생시켜 클래스를 로드하지 못했습니다.

마찬가지로 NoSuchMethodErrorNoSuchFieldError는 일반적으로 JAR 버전이 일치하지 않아 발생합니다. 다음 단계를 수행하는 것을 권장합니다.

  1. 종속성을 확인하여 모든 SDK jar에서 동일한 버전을 사용하고 있는지 확인합니다. 클래스, 메서드 또는 필드를 찾을 수 없는 가장 일반적인 이유는 새 클라이언트 버전으로 업그레이드하지만 이전 ‘공유’ SDK 종속성 버전을 계속 사용하는 경우입니다. 새 클라이언트 버전은 최신 ‘공유’ SDK 종속성에만 있는 클래스를 사용하려고 할 수 있습니다. mvn dependency:tree 또는 gradle dependencies(Gradle용)를 실행하여 SDK 라이브러리 버전이 모두 일치하는지 확인합니다. 향후 이 문제 발생을 완전히 방지하려면 BOM(Bill of Materials)을 사용하여 SDK 모듈 버전을 관리하는 것이 좋습니다.

    다음 예제에서는 혼합 SDK 버전의 예를 보여줍니다.

    [INFO] +- software.amazon.awssdk:dynamodb:jar:2.20.00:compile [INFO] | +- software.amazon.awssdk:aws-core:jar:2.13.19:compile [INFO] +- software.amazon.awssdk:netty-nio-client:jar:2.20.00:compile

    dynamodb의 버전은 2.20.00이고 aws-core의 버전은 2.13.19입니다. aws-core 아티팩트 버전도 2.20.00이어야 합니다.

  2. 로그 초기에 문을 확인하여 정적 초기화 실패로 인해 클래스가 로드되지 않는지 확인합니다. 클래스가 처음 로드되지 않으면 클래스를 로드할 수 없는 이유를 지정하는 더 유용한 다른 예외가 발생할 수 있습니다. 이 잠재적으로 유용한 예외는 한 번만 발생하므로 이후 로그 문은 클래스를 찾을 수 없음을 보고합니다.

  3. 배포 프로세스를 확인하여 애플리케이션과 함께 필요한 JAR 파일을 실제로 배포하는지 확인합니다. 올바른 버전으로 구축하고 있지만 애플리케이션에 대한 클래스 경로를 만드는 프로세스가 필수 종속성을 제외하고 있는 경우일 수 있습니다.

SignatureDoesNotMatch’ 오류 또는 ‘계산한 요청 서명이 제공한 서명과 일치하지 않음’ 오류를 해결하는 방법

SignatureDoesNotMatch 오류는 AWS SDK for Java에서 생성된 서명과 AWS 서비스에서 생성된 서명이 일치하지 않음을 나타냅니다. 다음 항목에서는 잠재적 원인을 설명합니다.

  • 프록시 또는 중개자가 요청을 수정합니다. 예를 들어 프록시 또는 로드 밸런서는 SDK에서 서명한 헤더, 경로 또는 쿼리 문자열을 수정할 수 있습니다.

  • 서비스 및 SDK는 각각에서 서명할 문자열을 생성할 때 요청을 인코딩하는 방식이 다릅니다.

이 문제를 디버깅하려면 SDK에 대한 디버그 로깅을 사용하는 것이 좋습니다. 오류를 재현하고 SDK가 생성한 정식 요청을 찾습니다. 로그에서 정식 요청에는 레이블이 AWS4 String to sign: ...으로 지정되고 서명할 문자열에는 AWS4 Canonical Request: ... 레이블이 지정됩니다.

예를 들어 프로덕션 환경에서만 재현할 수 있기 때문에 디버깅을 사용할 수 없는 경우 오류가 발생하면 요청에 대한 정보를 로깅하는 로직을 애플리케이션에 추가합니다. 그런 다음 해당 정보를 사용하여 디버그 로깅이 사용된 통합 테스트 시 프로덕션 외부에서 오류를 복제할 수 있습니다.

서명할 정식 요청과 문자열을 수집한 후 AWS 서명 버전 4 사양과 비교하여 SDK가 서명할 문자열을 생성한 방식에 문제가 있는지 확인합니다. 문제가 있는 것 같으면 AWS SDK for Java에 대한 GitHub 버그 보고서를 만들 수 있습니다.

문제가 전혀 표시되지 않으면 서명할 SDK의 문자열을 문자열과 비교하여 일부 AWS 서비스가 실패 응답의 일부로 반환된다고 서명할 수 있습니다(예: Amazon S3). 사용할 수 없는 경우 영향을 받는 서비스에 문의하여 비교를 위해 생성한 정식 요청과 문자열을 확인해야 합니다. 이러한 비교는 서비스와 클라이언트 간의 요청 또는 인코딩 차이를 수정했을 수 있는 중개자를 식별하는 데 도움이 될 수 있습니다.

요청 서명에 대한 자세한 배경 정보는 AWS Identity and Access Management 사용 설명서의 AWS API 요청에 서명을 참조하세요.

예표준 요청
PUT /Example-Bucket/Example-Object partNumber=19&uploadId=string amz-sdk-invocation-id:f8c2799d-367c-f024-e8fa-6ad6d0a1afb9 amz-sdk-request:attempt=1; max=4 content-encoding:aws-chunked content-length:51 content-type:application/octet-stream host:xxxxx x-amz-content-sha256:STREAMING-UNSIGNED-PAYLOAD-TRAILER x-amz-date:20240308T034733Z x-amz-decoded-content-length:10 x-amz-sdk-checksum-algorithm:CRC32 x-amz-trailer:x-amz-checksum-crc32
예서명할 문자열
AWS4-HMAC-SHA256 20240308T034435Z 20240308/us-east-1/s3/aws4_request 5f20a7604b1ef65dd89c333fd66736fdef9578d11a4f5d22d289597c387dc713

java.lang.IllegalStateException: 연결 풀 종료’ 오류를 해결하는 방법

이 오류는 기본 Apache HTTP 연결 풀이 종료되었음을 나타냅니다. 다음 항목에서는 잠재적 원인을 설명합니다.

  • SDK 클라이언트가 조기에 종료되었습니다. SDK는 연결된 클라이언트가 종료될 때만 연결 풀을 종료합니다. 사용 중인 리소스는 종료하지 않아야 합니다.

  • java.lang.Error가 발생했습니다. OutOfMemoryError 등의 오류로 인해 Apache HTTP 연결 풀이 종료됩니다. 로그에서 오류 스택 추적을 검사합니다. 또한 코드를 검토하여 Throwable 또는 Error를 포착하지만 표시에서 오류를 방지하는 출력을 포함하는 위치를 찾습니다. 코드가 오류를 보고하지 않는 경우 정보가 로그되도록 코드를 다시 작성합니다. 로그된 정보는 오류의 근본 원인을 확인하는 데 도움이 됩니다.

  • 종료된 후 DefaultCredentialsProvider#create()에서 반환된 자격 증명 공급자를 사용하려고 했습니다. DefaultCredentialsProvider#create는 싱글톤 인스턴스를 반환하므로 종료되어 있고 코드가 resolveCredentials 메서드를 호출하면 캐시된 자격 증명(또는 토큰)이 만료된 후 예외가 발생합니다.

    다음 예제와 같이 DefaultCredentialsProvider가 종료된 위치가 있는지 코드를 확인합니다.

    • 싱글톤 인스턴스는 DefaultCredentialsProvider#close().를 호출하여 종료됩니다.

      DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create(); // Singleton instance returned. AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials(); // Make calls to AWS 서비스. defaultCredentialsProvider.close(); // Explicit close. // Make calls to AWS 서비스. // After the credentials expire, either of the following calls eventually results in a "Connection pool shut down" exception. credentials = defaultCredentialsProvider.resolveCredentials(); // Or credentials = DefaultCredentialsProvider.create().resolveCredentials();
    • try-with-resources 블록에서 DefaultCredentialsProvider#create()를 호출합니다.

      try (DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create()) { AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials(); // Make calls to AWS 서비스. } // After the try-with-resources block exits, the singleton DefaultCredentialsProvider is closed. // Make calls to AWS 서비스. DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create(); // The closed singleton instance is returned. // If the credentials (or token) has expired, the following call results in the error. AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();

    코드가 싱글톤 인스턴스를 종료하고 DefaultCredentialsProvider를 사용하여 자격 증명을 해결해야 하는 경우 DefaultCredentialsProvider.builder().build()를 호출하여 새로운 비싱글톤 인스턴스를 만듭니다.

‘AwsCredentialsProviderChain 체인의 공급자로부터 자격 증명을 로드할 수 없음’ 오류를 수정하는 방법

이 오류는 AWS SDK for Java 2.x가 기본 자격 증명 공급자 체인의 자격 증명 공급자를 통해 유효한 AWS 자격 증명을 찾을 수 없음을 나타냅니다. SDK는 특정 순서로 자격 증명을 자동으로 검색하며, 이 오류는 체인의 모든 공급자가 유효한 자격 증명을 제공하지 못할 때 발생합니다.

전체 오류 메시지는 일반적으로 다음과 같습니다(가독성을 높이기 위해 줄 끝 및 들여쓰기가 추가됨).

Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain( credentialsProviders=[ SystemPropertyCredentialsProvider(), EnvironmentVariableCredentialsProvider(), WebIdentityTokenCredentialsProvider(), ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])), ContainerCredentialsProvider(), InstanceProfileCredentialsProvider() ]) : [ SystemPropertyCredentialsProvider(): Unable to load credentials from system settings. Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) or system property (aws.accessKeyId)., EnvironmentVariableCredentialsProvider(): Unable to load credentials from system settings. Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) or system property (aws.accessKeyId)., WebIdentityTokenCredentialsProvider(): To use web identity tokens, the 'sts' service module must be on the class path., ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])): Profile file contained no credentials for profile 'default': ProfileFile(sections=[]), ContainerCredentialsProvider(): Cannot fetch credentials from container - neither AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variables are set., InstanceProfileCredentialsProvider(): Failed to load credentials from IMDS.]

일반적인 원인 및 솔루션

자격 증명 구성 검토

기본 자격 증명 공급자를 사용하는 경우(자격 증명을 명시적으로 구성하지 않고 ServiceClient.create() 호출) SDK는 특정 순서로 자격 증명을 검색합니다. 기본 자격 증명 공급자 체인이 작동하는 방식을 검토하여 SDK가 확인하는 자격 증명과 순서를 파악합니다.

사용하려는 자격 증명 구성 메서드가 환경에 올바르게 설정되어 있는지 확인합니다.

Amazon EC2 인스턴스의 경우
  • IAM 역할 확인: IAM 역할이 인스턴스에 연결되어 있는지 확인합니다.

  • 간헐적 IMDS 장애: 간헐적 장애(일반적으로 수백 밀리초 지속)가 발생하는 경우 이는 일반적으로 인스턴스 메타데이터 서비스(IMDS)에 도달하는 일시적인 네트워크 문제를 나타냅니다.

    솔루션

    • 디버그 로깅을 사용하여 장애의 타이밍 및 빈도 분석

    • 자격 증명 관련 장애에 대해 애플리케이션에서 재시도 로직 구현 고려

    • 인스턴스와 IMDS 엔드포인트 간의 네트워크 연결 문제 확인

컨테이너 환경의 경우

작업 역할(Amazon ECS) 또는 서비스 계정(Amazon EKS)이 구성되어 있고 필요한 환경 변수가 설정되어 있는지 확인합니다.

로컬 개발의 경우

환경 변수, 자격 증명 파일 또는 IAM Identity Center 구성이 있는지 확인합니다.

웹 ID 페더레이션의 경우
  • 구성 확인: 웹 자격 증명 토큰 파일이 존재하고 필요한 환경 변수가 구성되어 있는지 확인합니다.

  • STS 모듈 종속성 누락: 오류(To use web identity tokens, the 'sts' service module must be on the class path)가 표시되면 STS 모듈을 종속성으로 추가해야 합니다. 이는 Amazon EKS Pod Identity 또는 기타 웹 자격 증명 토큰 인증을 사용할 때 흔히 발생합니다.

    솔루션: 프로젝트 종속성에 STS 모듈을 추가합니다.

    • <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>sts</artifactId> </dependency>

      일부 서비스의 경우 aws-query-protocol 종속성이 필요할 수 있습니다.

      <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>aws-query-protocol</artifactId> </dependency>

네트워크 또는 프록시 연결 문제

자격 증명 공급자 체인에 Connection refused 오류가 표시되는 경우 이는 일반적으로 SDK가 AWS 엔드포인트에 도달하려고 할 때의 네트워크 연결 문제를 나타냅니다.

솔루션

  • 프록시 서버를 사용하는 경우 프록시 구성 확인

  • 네트워크에서 AWS 엔드포인트에 대한 아웃바운드 HTTPS 연결을 허용하는지 확인

  • 디버그 로깅을 사용하여 자세한 연결 시도 확인

  • curl 등의 도구를 사용하여 AWS 엔드포인트에 대한 네트워크 액세스를 확인하는 연결 테스트