“ResourceLoader”与 AWS S3 可以很好地配合这些属性:
cloud:
aws:
s3:
endpoint: s3.amazonaws.com <-- custom endpoint added in spring cloud aws 2.3
credentials:
accessKey: XXXXXX
secretKey: XXXXXX
region:
static: us-east-1
stack:
auto: false
但是,当我在本地启动 localstack 容器并尝试将其与这些属性一起使用时(根据此发行文档:https://spring.io/blog/2021/03/17/spring-cloud-aws-2 -3-现已可用):
cloud:
aws:
s3:
endpoint: http://localhost:4566
credentials:
accessKey: test
secretKey: test
region:
static: us-east-1
stack:
auto: false
我得到这个例外:
17:12:12.130 [reactor-http-nio-2] 错误 org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler - [23efd000-1] HTTP GET“/getresource/test”的 500 服务器错误 com.amazonaws.SdkClientException:无法执行 HTTP 请求:mybucket.localhost 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleRetryableException(AmazonHttpClient.java:1207) ~[aws-java-sdk-core-1.11.951.jar:?] 抑制:reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 在以下站点发现错误: |_ 检查点 ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain] |_ 检查点 ⇢ HTTP GET "/getresource/test" [ExceptionHandlingWebHandler] 堆栈跟踪: 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleRetryableException(AmazonHttpClient.java:1207) ~[aws-java-sdk-core-1.11.951.jar:?]
原因:java.net.UnknownHostException:mybucket.localhost 在 java.net.InetAddress$CachedAddresses.get(InetAddress.java:797) ~[?:?]
我可以在 S3 浏览器中查看本地堆栈存储桶文件,否则效果很好。
这是我的本地堆栈的 docker compose 配置:
version: '3.1'
services:
localstack:
image: localstack/localstack:latest
environment:
- AWS_DEFAULT_REGION=us-east-1
- AWS_ACCESS_KEY_ID=test
- AWS_SECRET_ACCESS_KEY=test
- EDGE_PORT=4566
- SERVICES=lambda,s3
ports:
- '4566-4583:4566-4583'
volumes:
- "${TEMPDIR:-/tmp/localstack}:/tmp/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
这是我读取文本文件的方式:
public class ResourceTransferManager {
@Autowired
ResourceLoader resourceLoader;
public void resourceLoadingMethod() throws IOException {
Resource resource = resourceLoader.getResource("s3://mybucket/index.txt");
InputStream inputStream = resource.getInputStream();
System.out.println("File content: " + IOUtils.toString(inputStream, StandardCharsets.UTF_8));
}}
默认情况下,S3 客户端创建一个以存储桶名称作为子域的路径,这会导致问题。 有几种方法可以解决这个问题:
在 localstack 的情况下,不要使用端点
http://localhost:4566
,使用标准的 formate 端点,即: http://s3.localhost.localstack.cloud:4566
,这实际上会连接到 DNS 并在内部解析为本地主机 IP,因此这会正常工作。 (仅对它进行空化,它使用公共 DNS 进行解析,因此它要么需要互联网连接,要么您需要在主机文件中添加前缀存储桶名称的主机条目127.0.0.1 <yourexpectedbucketName>.s3.localhost.localstack.cloud
)。
或者,如果您使用的是 docker,那么您也可以为 localstack 容器创建网络别名,而不是创建主机条目,例如:<yourexpectedbucketName>.s3.localhost.localstack.cloud
另一种更好的方法是扩展第一种方法,但这里不是为每个存储桶使用别名(这可能并不总是可行),您可以启动本地dns容器并在那里使用通配符dns配置。请参阅简化示例:https://gist.github.com/paraspatidar/c29e4adb172a5afc92852a57e621323d (原始参考:https://gist.github.com/NAR8789/92da076d0c35b434107fb4f4f198fd12)
我正在使用 Spring Boot 3 和 spring-cloud-aws-starter-s3 3.0.0 如果您使用相同的库来连接 s3,您可以将其添加到您的 application.properties
spring.cloud.aws.s3.path-style-access-enabled=true