2016-03-18 71 views
13

我有一个由AWS直接调用的AWS lambda RequestHandler类。最终,我需要使用Spring Boot,因为我需要它能够从Spring Cloud配置服务器检索数据。在Amazon AWS中使用Spring引导/云lambda不会注入值

的问题是,代码作品,如果我从我自己的开发环境本地运行未能在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 

有什么我想:

  • 使用常规的Spring MVC,但这doesn't have integration with @Value injection/Spring cloud
  • 使用@PropertySource - 但发现它不支持.yml文件
  • 验证,以确保配置服务器服务请求到任何IP地址(没有IP地址过滤)
  • 运行curl保证值带回
  • 验证确保.jar实际上包含bootstrap.yml在jar根
  • 验证确保.jar实际上包含Spring Boot类。 FWIW我正在使用Maven shade插件,它将项目打包成具有所有依赖关系的fat .jar。

注:AWS LAMBDA 支持环境变量,因此,我不能设置像spring.application.name事情(既不是环境变量也不是-D参数)。我也无法控制实际启动的基础类MyClass - 这对最终用户来说是完全透明的。我只是打包jar并提供入口点(类名),休息是照顾。

有什么我可以错过?任何方式,我可以更好地调试这个?

+0

是你的配置服务器可从'外部'?我的意思是,你确定它没有隐藏在IP保护或类似的东西后面吗? – freakman

+0

@freakman好点,但没有 - 只是检查,配置请求是从任何主机提供。 – mindas

+0

我假设你已经看过这个:http://cloud.spring.io/spring-cloud-aws/spring-cloud-aws.html#_spring_boot_auto_configuration,它不适合你?我对AWS Lambda了解不多,但看到这篇文章:https://github.com/cagataygurturk/aws-lambda-java-boilerplate。也许你已经检查过这些但想确认。 –

回答

21

经过一些调试后,我确定问题在于使用Maven Shade插件。有关这方面的一些信息,Spring Boot会在其自动配置jar中查找META-INF/spring.factories jar see here。为了正确地打包一个Spring Boot jar,你需要使用Spring Boot Maven Plugin并将其设置为在maven重新打包阶段运行。它在您的本地IDE中工作的原因是因为您没有运行Shade打包的jar。他们在插件中做了一些特殊的魔术,让Shade插件没有意识到的正确点。

我能够创建一些示例代码,最初没有注入值,但现在工作,我使用了正确的插件。看this GitHub repo看看我做了什么。

我没有将它与Spring Cloud连接,但现在剩下的Spring Boot注入工作了,我认为它应该是直截了当的。

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

更新:对于Spring Boot 1.4。如果你不那么默认

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

插件的新的行为是把所有的罐子下BOOT-INF的意图是JAR:X,你必须在春季启动插件提供此配置是可执行的并且引导进程加载它。我在解决这里遇到的情况时添加警告时发现了这一点。请参阅https://github.com/spring-projects/spring-boot/issues/5465以供参考。

+0

'Spring Boot Maven Plugin'是缺少的元素。我不得不调整一些设置,但整个组合都起作用了。有趣的是,bootstrap根据日志需要10秒(!) - 这绝对是阻碍在AWS环境中使用Spring Boot的一个因素。尽管如此,感谢您的辛勤工作,非常感谢! – mindas

+0

@mindas是的我认为Spring Boot在其容器环境中可能更有意义,而不是Lambda。当发生这种情况时,我也会看到有关提出某种警告的请求,因为它肯定不明显,并且可能在其他情况下发生。 –

+1

好消息是,亚马逊在丢弃它之前将Lambda实例保留一段时间(未定义?),因此可以使用同一实例来处理下一个请求。这意味着代码应该检查应用程序上下文是否已经被初始化,如果有,就跳过它。也就是说,对于频繁的请求,开销问题是无关紧要的。 – mindas

相关问题