将 localstack 与 Spring Cloud AWS 2.3 结合使用时出现未知主机

rav*_*ant 10 spring-cloud-aws localstack

AWS S3 的“ResourceLoader”可以很好地处理这些属性:

\n
cloud:\n  aws:\n    s3:\n        endpoint: s3.amazonaws.com     <-- custom endpoint added in spring cloud aws 2.3\n    credentials:\n        accessKey: XXXXXX\n        secretKey: XXXXXX\n    region:\n        static: us-east-1\n    stack:\n        auto: false\n
Run Code Online (Sandbox Code Playgroud)\n

但是,当我在本地启动 localstack 容器并尝试将其与这些属性一起使用时(根据此发行文档:https ://spring.io/blog/2021/03/17/spring-cloud-aws-2-3 -现在可用):

\n
cloud:\n  aws:\n    s3:\n        endpoint: http://localhost:4566\n    credentials:\n        accessKey: test\n        secretKey: test\n    region:\n        static: us-east-1\n    stack:\n        auto: false\n
Run Code Online (Sandbox Code Playgroud)\n

我得到这个例外:

\n
\n

17:12:12.130 [reactor-http-nio-2] 错误 org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler - [23efd000-1] 500 HTTP GET“/getresource/test”\ncom 服务器错误.amazonaws.SdkClientException:无法执行 HTTP 请求:mybucket.localhost\nat com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleRetryableException(AmazonHttpClient.java:1207) ~[aws-java-sdk-core-1.11.951.jar: ?]\n抑制:reactor.core.publisher.FluxOnAssembly$OnAssemblyException:\n在以下站点观察到错误:\n|_ checkpoint \xe2\x87\xa2 org.springframework.boot.actuate.metrics.web .reactive.server.MetricsWebFilter [DefaultWebFilterChain]\n|_ 检查点 \xe2\x87\xa2 HTTP GET“/getresource/test”[ExceptionHandlingWebHandler]\n堆栈跟踪:\nat com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleRetryableException(AmazonHttpClient .java:1207) ~[aws-java-sdk-core-1.11.951.jar:?]

\n
\n
\n

引起原因:java.net.UnknownHostException:mybucket.localhost\nat java.net.InetAddress$CachedAddresses.get(InetAddress.java:797) ~[?:?]

\n
\n

我可以在 S3 浏览器中查看我的 localstack 存储桶文件,否则效果很好。

\n

这是我的 localstack 的 docker compose 配置:

\n
version: \'3.1\'\nservices:\nlocalstack:\n    image: localstack/localstack:latest\n    environment:\n        - AWS_DEFAULT_REGION=us-east-1\n        - AWS_ACCESS_KEY_ID=test\n        - AWS_SECRET_ACCESS_KEY=test\n        - EDGE_PORT=4566\n        - SERVICES=lambda,s3\n    ports:\n        - \'4566-4583:4566-4583\'\n    volumes:\n        - "${TEMPDIR:-/tmp/localstack}:/tmp/localstack"\n        - "/var/run/docker.sock:/var/run/docker.sock"          \n
Run Code Online (Sandbox Code Playgroud)\n

这是我读取文本文件的方式:

\n
public class ResourceTransferManager {\n\n@Autowired\nResourceLoader resourceLoader;\n\npublic void resourceLoadingMethod() throws IOException {\n    Resource resource = resourceLoader.getResource("s3://mybucket/index.txt");\n    InputStream inputStream = resource.getInputStream();\n    System.out.println("File content: " + IOUtils.toString(inputStream, StandardCharsets.UTF_8));\n}}\n\n  \n
Run Code Online (Sandbox Code Playgroud)\n

Par*_*dar 16

默认情况下,S3 客户端创建一个以存储桶名称作为子域的路径,这会导致问题。有几种方法可以解决这个问题:

  1. 在 localstack 的情况下,不要使用端点http://localhost:4566,使用标准的 formate 端点,即:http://s3.localhost.localstack.cloud:4566 ,这实际上会连接到 DNS 并在内部解析为本地主机 IP,因此这会正常工作。(仅对它进行空化,它使用公共 DNS 进行解析,因此它要么需要互联网连接,要么您需要在主机文件 put 中添加前缀存储桶名称的主机条目127.0.0.1 <yourexpectedbucketName>.s3.localhost.localstack.cloud)。或者,如果您使用 docker,那么您也可以为 localstack 容器创建网络别名,而不是创建主机条目,例如:<yourexpectedbucketName>.s3.localhost.localstack.cloud

  2. 另一种更好的方法是扩展第一种方法,但这里不是为每个存储桶使用别名(这可能并不总是可行),您可以启动本地dns 容器并在那里使用通配符 dns 配置。请参阅简化示例:https: //gist.github.com/paraspatidar/c29e4adb172a5afc92852a57e621323d (原始参考: https: //gist.github.com/NAR8789/92da076d0c35b434107fb4f4f198fd12

  • 我认为第一个选项应该有效。但是,属性 ForcePathStyleAccess 未在 spring-cloud-aws 中公开。 (2认同)