Spring Cloud AWS SQS fails to connect to service endpoint locally

Carven picture Carven · Dec 29, 2019 · Viewed 10k times · Source

I'm trying to use Spring Cloud's AWS SQS in a project I'm working on. At this time, I'm only running the application locally on my dev machine. Thus, what I want is to connect to the SQS on AWS without having to deploy my app to an EC2 instance.

However, it seems like the AWS SDK used in Spring Cloud's AWS package will attempt to authenticate through metadata and wants to resolve 169.254.169.254/latest/meta-data/instance-id. Since I'm still the running the app locally, the endpoint cannot be resolved and an error is thrown:

2019-12-29 16:38:27.420  WARN 22462 --- [  restartedMain] com.amazonaws.util.EC2MetadataUtils      : Unable to retrieve the requested metadata (/latest/meta-data/instance-id). 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.699.jar:na]
    at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:70) ~[aws-java-sdk-core-1.11.699.jar:na]
    at com.amazonaws.internal.InstanceMetadataServiceResourceFetcher.readResource(InstanceMetadataServiceResourceFetcher.java:75) ~[aws-java-sdk-core-1.11.699.jar:na]
    at com.amazonaws.internal.EC2ResourceFetcher.readResource(EC2ResourceFetcher.java:62) ~[aws-java-sdk-core-1.11.699.jar:na]
    at com.amazonaws.util.EC2MetadataUtils.getItems(EC2MetadataUtils.java:400) ~[aws-java-sdk-core-1.11.699.jar:na]
    at com.amazonaws.util.EC2MetadataUtils.getData(EC2MetadataUtils.java:369) ~[aws-java-sdk-core-1.11.699.jar:na]
    at org.springframework.cloud.aws.context.support.env.AwsCloudEnvironmentCheckUtils.isRunningOnCloudEnvironment(AwsCloudEnvironmentCheckUtils.java:38) ~[spring-cloud-aws-context-2.2.1.RELEASE.jar:2.2.1.RELEASE]
    at org.springframework.cloud.aws.context.annotation.OnAwsCloudEnvironmentCondition.matches(OnAwsCloudEnvironmentCondition.java:37) ~[spring-cloud-aws-context-2.2.1.RELEASE.jar:2.2.1.RELEASE]
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:221) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:587) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
...

I've tried to explicitly supply an SQS endpoint in my bean, but it still attempts to connect to 169.254.169.254 resulting in the error above:

public AmazonSQSAsync sqsClient() {
   EndpointConfiguration endpointConfig = new AwsClientBuilder.EndpointConfiguration(
        "sqs.us-east-1.amazonaws.com",
        "us-east-1"
   );

   return AmazonSQSAsyncClientBuilder
                .standard()
                .withEndpointConfiguration(endpointConfig)
                .withCredentials(new AWSStaticCredentialsProvider(new DefaultAWSCredentialsProviderChain().getCredentials()))
                .build();
}

Although I'm not certain about this, I suspect that the error is occurring because I'm running the app locally on my dev machine and so it couldn't resolve to the endpoint. But I'm not entirely sure about this too because I'm running other AWS services in the same app using the AWS SDK and I don't have this error.

I've the following dependencies in my pom.xml and it appears that having any one of them will cause the error to occur. That's, I don't even have to create the beans to have that error. Adding these dependencies will immediately, for some reason, causes the SDK to attempt to resolve that endpoint and fail with that error.

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-aws</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-aws-messaging</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

What else should I do to fix the error that it failed to connect to service endpoint?

Answer

nickolay.laptev picture nickolay.laptev · Dec 29, 2019
  1. Set cloud.aws.region.auto property to false in Spring application properties (or via environment variables etc.).
  2. Define cloud.aws.region.static property.

This will tell Spring not to use automatic detection based EC2 meta data. Some details.

You may need to configure credentials similarly, you can find related info in the same doc.