1

我试图将 spring-cloud-starter-aws 用于一个目的 - 以便我的 ec2 实例可以使用逻辑名称而不是物理名称访问其 elasticache 节点。我的问题是我想在没有 AWS 的本地上下文中运行这个二进制文件(不使用 elasticache 节点),但我无法禁用。我得到一个异常:连接到服务端点时发生 IOException http://169.254.169.254/latest/dynamic/instance-identity/document:。例外是:

Error creating bean with name 'org.springframework.cloud.aws.context.support.io.ResourceLoaderBeanPostProcessor#0': 
Cannot resolve reference to bean 'amazonS3'.

我认为这是因为 aws sdk 正在调用我没有在本地上下文中运行的实例端点。我怎样才能禁用它?

4

2 回答 2

1

感谢@Martian先前的回答,应用程序已被修改为

首先在应用程序类中禁用与AWS相关的自动配置bean

@SpringBootApplication(exclude = {
org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.context.ContextCredentialsAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.context.ContextResourceLoaderAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.mail.MailSenderAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.cache.ElastiCacheAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.messaging.MessagingAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.jdbc.AmazonRdsDatabaseAutoConfiguration.class,
org.springframework.cloud.aws.autoconfigure.metrics.CloudWatchExportAutoConfiguration.class
})

然后使用适当的代码设置创建 AWS 专用的 Spring Boot 配置

    /**
     * Only enable AWS related auto config when we run in AWS Cloud
     */
    @ConditionalOnAwsCloudEnvironment
    @Import({
        org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.context.ContextCredentialsAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.context.ContextResourceLoaderAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.mail.MailSenderAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.cache.ElastiCacheAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.messaging.MessagingAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.jdbc.AmazonRdsDatabaseAutoConfiguration.class,
        org.springframework.cloud.aws.autoconfigure.metrics.CloudWatchExportAutoConfiguration.class
    })
    public class AwsConfig {
    }
于 2019-12-11T16:47:13.073 回答
0

spring-cloud-starter-aws 使用 spring-cloud-aws-autoconfigure 提供以下 AWS 相关配置:

org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration
org.springframework.cloud.aws.autoconfigure.context.ContextCredentialsAutoConfiguration
org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration
org.springframework.cloud.aws.autoconfigure.context.ContextResourceLoaderAutoConfiguration
org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration
org.springframework.cloud.aws.autoconfigure.mail.MailSenderAutoConfiguration
org.springframework.cloud.aws.autoconfigure.cache.ElastiCacheAutoConfiguration
org.springframework.cloud.aws.autoconfigure.messaging.MessagingAutoConfiguration
org.springframework.cloud.aws.autoconfigure.jdbc.AmazonRdsDatabaseAutoConfiguration
org.springframework.cloud.aws.autoconfigure.metrics.CloudWatchExportAutoConfiguration

所有这些都是由 EnableAutoConfiguration 触发的。如果您可以在没有 EnableAutoConfiguration 的情况下生活,那么您的问题就解决了。但是,由于您使用的是 spring-cloud-starter-aws,因此我不希望会出现这种情况。

不幸的是,只有 ContextInstanceDataAutoConfiguration 和 ContextInstanceDataAutoConfiguration 使用了@ConditionalOnAwsCloudEnvironment,其余的配置不管环境如何都会启动。它们中的大多数仅使用类似于以下内容的条件(此示例来自 ContextCredentialsAutoConfiguration):

@ConditionalOnClass(name = {"com.amazonaws.auth.AWSCredentialsProvider"})

要不启动此类配置,您需要从类路径中删除 com.amazonaws.auth.AWSCredentialsProvider 类。这可以通过 maven 配置文件或花哨的模块化来完成,但我认为这通常是一个次优的解决方案,因为这种项目重组有很大的副作用。

我认为最简单的解决方案是从项目依赖项中删除 spring-cloud-aws-autoconfigure 并编写自己的配置类版本。这是对我有用的 ContextCredentialsAutoConfiguration 版本:

import mu.KLogging
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.cloud.aws.context.config.annotation.ContextDefaultConfigurationRegistrar
import org.springframework.cloud.aws.context.config.support.ContextConfigurationUtils
import org.springframework.context.EnvironmentAware
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar
import org.springframework.context.annotation.Profile
import org.springframework.core.env.Environment
import org.springframework.core.type.AnnotationMetadata

@Configuration
@Import(ContextDefaultConfigurationRegistrar::class, AwsContextCredentialsAutoConfiguration.Registrar::class)
@ConditionalOnClass(name = ["com.amazonaws.auth.AWSCredentialsProvider"])
@Profile("!it")
class AwsContextCredentialsAutoConfiguration {

    class Registrar : ImportBeanDefinitionRegistrar, EnvironmentAware {
        companion object: KLogging()
        private var environment: Environment? = null

        override fun setEnvironment(environment: Environment) {
            this.environment = environment
        }

        override fun registerBeanDefinitions(importingClassMetadata: AnnotationMetadata, registry: BeanDefinitionRegistry) {
            val useDefaultCredentialsChain = this.environment!!.getProperty("cloud.aws.credentials.useDefaultAwsCredentialsChain", Boolean::class.java, false)
            if (useDefaultCredentialsChain) {
                logger.debug("Using default AWS credentials provider")
                ContextConfigurationUtils.registerDefaultAWSCredentialsProvider(registry)
            } else {
                logger.debug("Using custom credentials provider (based on environment properties)")
                ContextConfigurationUtils.registerCredentialsProvider(
                        registry,
                        this.environment!!.getProperty("cloud.aws.credentials.accessKey"),
                        this.environment!!.getProperty("cloud.aws.credentials.secretKey"),
                        this.environment!!.getProperty("cloud.aws.credentials.instanceProfile", Boolean::class.java, true) as Boolean && !this.environment!!.containsProperty("cloud.aws.credentials.accessKey"),
                        this.environment!!.getProperty("cloud.aws.credentials.profileName", "default"),
                        this.environment!!.getProperty("cloud.aws.credentials.profilePath"))
            }

        }
    }
}

请注意 @Profile("!it") 注释,它是为集成测试启用的配置文件。因此,在集成测试期间会忽略配置,但您可以将其替换为您用于本地上下文的配置文件。

于 2018-05-09T07:00:24.233 回答