将 Spring boot/cloud 与 Amazon AWS lambda 一起使用不会注入值

Using Spring boot/cloud with Amazon AWS lambda does not inject values

我有一个由 AWS 直接调用的 AWS lambda RequestHandler class。最终我需要让它与 Spring Boot 一起工作,因为我需要它能够从 Spring 云配置服务器检索数据。

问题是代码 如果我 运行 在本地 来自我自己的开发环境但 在部署时无法注入配置值AWS.

@Configuration
@EnableAutoConfiguration
@ComponentScan("my.package")
public class MyClass implements com.amazonaws.services.lambda.runtime.RequestHandler<I, O> {
   public O handleRequest(I input, Context context) {
        ApplicationContext applicationContext = new SpringApplicationBuilder()
                .main(getClass())
                .showBanner(false)
                .web(false)
                .sources(getClass())
                .addCommandLineProperties(false)
                .build()
                .run();

        log.info(applicationContext.getBean(SomeConfigClass.class).foo);
        // prints cloud-injected value when running from local dev env
        //
        // prints "${path.to.value}" literal when running from AWS 
        //    even though Spring Boot starts successfully without errors
   }
}

@Configuration
public class SomeConfigClass {
   @Value("${path.to.value}")
   public String foo;
}

src/main/resources/bootstrap.yml:
spring:
  application:
    name: my_service
cloud:
  config:
    uri: http://my.server
    failFast: true
    profile: localdev

我尝试了什么:

注意:AWS Lambda 支持环境变量,因此我不能设置任何类似 spring.application.name 的东西(既不是环境变量也不是 -D 参数).我也无法控制实际启动 MyClass 的底层 classes - 这对最终用户来说是完全透明的。我只是打包 jar 并提供入口点(class 名称),剩下的就处理好了。

有什么我可能错过的吗?有什么办法可以更好地调试它吗?

经过一些调试后,我确定问题出在使用 Maven Shade 插件上。 Spring Boot 在其自动配置 jar 中查找 META-INF/spring.factories jar see here for some information on this. In order to package a Spring Boot jar correctly you need to use the Spring Boot Maven Plugin 并在 maven 重新打包阶段将其设置为 运行。它在您的本地 IDE 工作的原因是因为您没有 运行 安装 Shade 打包的 jar。他们在他们的插件中做了一些特殊的魔术,以将 Shade 插件不知道的东西放在正确的位置。

我能够创建一些示例代码,这些代码最初没有注入值,但现在可以使用,因为我使用了正确的插件。请参阅 this GitHub repo 查看我所做的工作。

我没有将它与 Spring Cloud 连接,但现在 Spring 启动注入的其余部分正在工作,我认为它应该很简单。

正如我在评论中提到的,您可能只想考虑一个简单的 REST 调用来获取云配置并自行注入,以节省每个请求都加载 Spring 应用程序的开销。

更新:对于 Spring 启动 1。4.x 您必须在 Spring 启动插件中提供此配置:

            <configuration>
                <layout>MODULE</layout>
            </configuration>

如果你不这样做,那么默认情况下,插件的新行为是将所有 jar 放在 BOOT-INF 下,因为目的是让 jar 可执行并让 bootstrap 进程加载它.我在解决为此处遇到的情况添加警告时发现了这一点。请参阅 https://github.com/spring-projects/spring-boot/issues/5465 以供参考。