Подтвердить что ты не робот

Использование Spring boot/cloud с Amazon AWS лямбда не вводит значения

У меня есть класс AWMS лямбда RequestHandler, который вызывается непосредственно AWS. В конце концов мне нужно заставить его работать с Spring Boot, потому что мне нужно, чтобы он мог получать данные с сервера конфигурации Spring.

Проблема в том, что код работает, если я запускаю его локально из моей собственной среды dev, но не может вводить значения конфигурации при развертывании на 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, но этот не имеет интеграции с областью @Value injection/Spring.
  • с помощью @PropertySource - но выяснил, что он не поддерживает файлы .yml.
  • чтобы гарантировать, что сервер конфигурации обслуживает запросы на любой IP-адрес (нет фильтрации IP-адресов)
  • running curl, чтобы обеспечить возврат значения.
  • проверено, чтобы гарантировать, что .jar фактически содержит bootstrap.yml в jar root
  • проверено, чтобы гарантировать, что .jar действительно содержит классы Spring Boot. FWIW Я использую плагин Maven shade, который упаковывает проект в жирный .jar со всеми зависимостями.

Примечание: AWS Lambda не поддерживает переменные среды окружения, поэтому я не могу установить ничего подобного spring.application.name (ни как переменная среды, ни как параметр -D). Я также не могу контролировать базовые классы, которые фактически запускают MyClass - это полностью прозрачно для конечного пользователя. Я просто упаковываю банку и предоставляю точку входа (название класса), позаботится об отдыхе.

Есть ли что-нибудь, что я мог пропустить? В любом случае, я мог бы отладить это лучше?

4b9b3361

Ответ 1

После небольшой отладки я решил, что проблема связана с использованием плагина Maven Shade. Spring Загружается в свою автоконфигурирующую банку для метафайла META-INF/spring.factories см. здесь для получения некоторой информации об этом. Чтобы правильно упаковать ботовую банку Spring, вам нужно использовать Spring Boot Maven Plugin и настроить его для запуска во время maven фаза переупаковки. Причина, по которой он работает в вашей локальной среде IDE, заключается в том, что вы не используете упаковку Shade. Они делают некоторые специальные магии в своем плагине, чтобы получить вещи в правильном месте, что плагин Shade не знает.

Мне удалось создать образец кода, который первоначально не вводил значения, но теперь работает, когда я использовал правильный плагин. См. этот репозиторий GitHub, чтобы проверить, что я сделал.

Я не связывал его с Spring Cloud, но теперь, когда остальная часть Spring загрузочной инъекции работает, я думаю, что это должно быть просто.

Как я уже упоминал в комментариях, вам может потребоваться просто простой вызов REST, чтобы получить конфигурацию облака и внести ее самостоятельно, чтобы сохранить накладные расходы на загрузку приложения Spring с каждым запросом.

UPDATE: для Spring Boot 1.4.x вы должны указать эту конфигурацию в плагине загрузки Spring:

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

Если вы этого не сделаете, то по умолчанию новое поведение плагина состоит в том, чтобы поместить все ваши банки под BOOT-INF, поскольку цель состоит в том, чтобы jar был исполняемым и загрузил процесс загрузки. Я узнал об этом, обратив внимание на добавление предупреждения о ситуации, которая была встречена здесь. См. https://github.com/spring-projects/spring-boot/issues/5465 для справки.