Spring Cloud в Nutshell
Одной из многих преимуществ запуска приложения в облаке является высокая доступность различных сервисов. Вместо того, чтобы настраивать железо, устанавливать, обслуживать и др., вы просто создаете и устанавливаете сервис одним кликом мыши или командой.
Как получить доступ к приложениям этих сервисов? К примеру, если ваше приложение работает с реляционной базой данных, вам нужно создать объект DataSource этого сервиса. Вот где Spring Cloud помогает вам. Она берет на себя всю работу по настройке доступа и соединения и позволяет сфокусироваться на использовании этих сервисов. Она также предоставляет информацию о приложении(адрес хоста, порт, имя и др.).
Spring Cloud делает это все независимо от вида облака через Cloud Connector. На данный момент предоставляется реализация для Cloud Foundry и Heroku, однако мы можете расширить для своих типов облаков, реализовав интерфейс или используя часть существующего функционала библиотеки. Затем просто добавьте вашу библиотеку расширения в classpath вашего приложения, чтобы не пересобирать Spring Cloud.
Spring Cloud также признает, что невозможна реализация для каждого сервиса каждого облака. Поэтому, пока поддерживаются наиболее используемые сервисы «из коробки», вы можете сами расширить функциональность для своих сервисов. Просто, как обычное расширение облака, вы добавляете jar-файл расширения вашего сервиса в classpath вашего приложения.
В итоге, поддержка Spring(включая Spring Boot) приложениями в Java и XML конфигурациях осуществляется на уровне добавления свойств, т.к. Spring Cloud является сам модулем, основанным на Spring. Другие фреймворки осуществляют поддержку библиотеки подобным образом.
Рассмотрим Spring Cloud в действии.
Spring Cloud в действии
Мы начнем с простого приложения(исходный код), основанном на Spring Boot(обычное Spring MVC приложение также работало бы хорошо, но с немного большим количеством кода). Приложение состоит из бина, который взаимодействует с сервисом, и страницы, на которой отображается информация, полученная от сервиса.
@Controller public class HomeController < @Autowired(required = false) DataSource dataSource; @Autowired(required = false) RedisConnectionFactory redisConnectionFactory; @Autowired(required = false) MongoDbFactory mongoDbFactory; @Autowired(required = false) ConnectionFactory rabbitConnectionFactory; @Autowired ApplicationInstanceInfo instanceInfo; @RequestMapping("/") public String home(Model model) < Map, String> services = new LinkedHashMap, String>(); services.put(dataSource.getClass(), toString(dataSource)); services.put(mongoDbFactory.getClass(), toString(mongoDbFactory)); services.put(redisConnectionFactory.getClass(), toString(redisConnectionFactory)); services.put(rabbitConnectionFactory.getClass(), toString(rabbitConnectionFactory)); model.addAttribute("services", services.entrySet()); model.addAttribute("instanceInfo", instanceInfo); return "home"; > // . различные toString() методы для каждого сервиса >
HomeController имеет четыре переменные для конкретного сервиса, чтобы можно было бы связать с приложением, и ещё одну переменную ApplicationInstanceInfo . «/» добавлено как строковое представление адреса каждого сервиса вместе с его моделью классов. В обобщенном виде отображается вся эта информация.
В конфигурацию мы добавим CloudConfig , как показано ниже:
@Configuration @ServiceScan @Profile("cloud") public class CloudConfig extends AbstractCloudConfig < @Bean public ApplicationInstanceInfo applicationInfo() < return cloud().getApplicationInstanceInfo(); >>
Класс наследуется от AbstractCloudConfig , именно таким является подход к написанию Java-конфигураций в Spring Cloud. Мы установили @Profile(«cloud») , чтобы конфигурация загружалась только в облаке. Аннотация @ServiceScan сканирует все связанные сервисы и создает для каждого из них бин(который будет добавляться в HomeController ). Вы можете задаться вопросом, в чем же разница между @ComponentScan и @ServiceScan и будете правы. В то время, как первый сканирует классы на кандидаты в бины, второй сканирует на связанные сервисы. Мы также создаем бин, содержащий информацию об экземпляре приложения.
Установка приложения в Cloud Foundry
Мы подключили следующий manifest.yml , который связывает все сервисы, которые нам нужны в данном примере(вам нужно создать сервисы, используя команду cf create-service ):
--- applications: - name: hello-spring-cloud memory: 512M instances: 1 host: hello-spring-cloud-$ domain: cfapps.io path: target/hello-spring-cloud-0.0.1-SNAPSHOT.jar services: - postgres-service - amqp-service - mongodb-service - redis-service env: SPRING_PROFILES_DEFAULT: cloud
Теперь нужно собрать и установить:
$ mvn package $ cf push

Теперь, если мы откроем страницу, то увидим информацию об этих четырех сервисах:
В реальном приложении, вы вероятнее всего включите эти сервисы в служебные бины и включите более полезную информацию о соединении! Пожалуйста, посмотрите Spring Cloud и взгляните на список примеров приложений, которые делают более интересные вещи. Собственно говоря, сам spring.io использует Spring Cloud.
Установка приложения в Heroku
Вы можете установить то же приложение и на Heroku. Вам нужно только добавить пару файлов(ни один из них не относятся к Spring Cloud): system.properties позволяет Heroku использовать Java 7, Procfile — выполняет правильные команды для запуска приложения и активизирует cloud профиль. Мы установим приложение на Heroku следующим образом:
$ heroku apps:create $ heroku addons:add mongolab $ heroku addons:add rediscloud $ heroku addons:add cloudamqp $ heroku config:set SPRING_CLOUD_APP_NAME=hello-spring-cloud $ git push heroku master

Мы создаем дополнения(похожие на сервисы Cloud Foundry) для MongoDb, Redis и AMQP. Heroku автоматически предоставляет Postgres сервис, поэтому мы его не добавляли. Рабочее окружение приложений Heroku, в отличие от Cloud Foundry, не раскрывает имени приложения, поэтому мы использовали heroku config:set для явного указания(иначе Spring Cloud установит ). Есть ещё несколько отличий в том, как Spring Cloud адаптируется между этими двумя облаками; мы рассмотрим их с следующих статьях.
Это все, что нужно сделать. Когда мы откроем страницу нашего приложения, то увидим информацию обо всех сервисах почти такую же, какую видели в Cloud Foundry.
Немного по управляем
Использование @ServiceScan делает легким захват всех сервисов и возможность их использования. Но на практике часто нужно делать большее, чем создание соединения, например установка параметров пула. В этом случае вы можете использовать Java или XML-конфигурацию. Внесем изменения в класс CloudConfig :
@Profile("cloud") public class CloudConfig extends AbstractCloudConfig < @Bean public ConnectionFactory rabbitConnectionFactory() < return connectionFactory().rabbitConnectionFactory(); >@Bean public DataSource dataSource() < return connectionFactory().dataSource(); >@Bean public MongoDbFactory mongoDb() < return connectionFactory().mongoDbFactory(); >@Bean public RedisConnectionFactory redisConnectionFactory() < return connectionFactory().redisConnectionFactory(); >@Bean public ApplicationInstanceInfo applicationInfo() < return cloud().getApplicationInstanceInfo(); >>
Если сравнить с первым вариантом, то вы увидите, что мы удалили аннотацию @ServiceScan . Вместо неё мы использовали API наследуемого AbstractCloudConfig класса, чтобы создать бин для каждого из сервисов.Теперь бины создаются так же, как и с @ServiceScan , но теперь у нас есть возможность для их настройки. Например, если мы захотим связать DataSource с конкретным сервисом и инициализировать его с конкретной конфигурацией, мы просто внесем изменения, как показано ниже:
@Bean public DataSource dataSource()
DataSource , созданная таким образом, имеет максимальный размер пула — 20, максимальное время ожидания — 200 миллисекунд, а также определенные параметры соединения.
Итог
Spring Cloud абстрагирует соединение к облачному сервису и дает возможность устанавливать одни и те же приложения на разных облачных платформах с минимальным количеством усилий. В этой статье мы слегка затронули то, что предлагает Spring Cloud. В следующей статье мы рассмотрим подробнее о Java и XML-конфигурации, а также как можно использовать основное API в не-Spring приложениях. В дальнейшем, мы будем рассматривать более подробно Spring Cloud.
Функция Spring Cloud в Azure
В этой статье описывается, как с помощью функций Spring Cloud разработать функцию Java и опубликовать ее в Функциях Azure. После выполнения действий, описанных в этой статье, код функции будет выполняться в Azure в Плане потребления и может запускаться с помощью HTTP-запроса.
Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начать работу.
Необходимые компоненты
Для разработки функций с помощью Java, должны быть установлены следующие компоненты:
- Java Developer Kit (JDK) версии 11.
- Apache Maven 3.0 или более поздней версии
- Azure CLI
- Функции Azure Core Tools версии 4
- Чтобы завершить работу с этим кратким руководством, необходимо задать JAVA_HOME переменную среды в расположении установки JDK.
- Убедитесь, что версия основных средств не менее 4.0.5455.
Что мы будем создавать
Мы создадим классическую функцию Hello, World, которая работает на Функции Azure и настроена с помощью функции Spring Cloud.
Функция получает User объект JSON, содержащий имя пользователя, и отправляет Greeting объект обратно, содержащий приветственное сообщение пользователю.
Проект доступен в примере функции Spring Cloud в Azure из репозитория azure-function-java-worker на сайте GitHub. Этот пример можно использовать непосредственно, если вы хотите просмотреть окончательную работу, описанную в этом кратком руководстве.
Создание нового проекта Maven
Мы создадим пустой проект Maven и настроим его с помощью Spring Cloud Function и Функций Azure.
В пустой папке создайте файл pom.xml, а затем скопируйте и содержимое из нашего примера проекта и вставьте его в файл pom.xml.
В этом файле используются зависимости Maven от Spring Boot и функции Spring Cloud, а также настраиваются плагины Maven для Spring Boot и Функций Azure.
Необходимо настроить несколько свойств для приложения:
- — это имя функции Azure.
- — это имя региона Azure, в котором развернута функция.
- — имя используемой группы ресурсов Azure.
Эти свойства можно изменить прямо в файле pom.xml, в самом его начале, как показано в следующем примере:
11 com.example.DemoApplication 1.29.0 my-spring-function-resource-group my-spring-function-service-plan my-spring-function Y1 eastus
Создание файлов конфигурации в Azure
Создайте папку src/main/resources и добавьте в нее следующие Функции Azure файлы конфигурации.
< "version": "2.0", "extensionBundle": < "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.2.0)" >, "functionTimeout": "00:10:00" >
Создание объектов домена
Функции Azure могут получать и отправлять объекты в формате JSON. Сейчас мы создадим объекты User и Greeting , которые представляют модель предметной области. Вы можете создать более сложные объекты с дополнительными свойствами, если хотите настроить пример из этого руководства и сделать его более интересным.
Создайте папку src/main/java/com/example/model и добавьте в нее следующие два файла.
package com.example.model; public class User < private String name; public User() < >public User(String name) < this.name = name; >public String getName() < return name; >public void setName(String name) < this.name = name; >>
package com.example.model; public class Greeting < private String message; public Greeting() < >public Greeting(String message) < this.message = message; >public String getMessage() < return message; >public void setMessage(String message) < this.message = message; >>
Создание приложения Spring Boot
Это приложение управляет всей бизнес-логикой и имеет доступ к полной экосистеме Spring Boot. Эта возможность предоставляет два основных преимущества по сравнению с использованием стандартной Функции Azure.
- Отсутствует зависимость от API Функций Azure, что позволяет легко перенести функцию в другие системы. Например, ее можно использовать в обычном приложении Spring Boot.
- Вы можете использовать любые аннотации @Enable из Spring Boot, чтобы добавлять новые возможности.
В папке src/main/java/com/example создайте следующий файл, который представляет собой обычное приложение Spring Boot.
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication < public static void main(String[] args) throws Exception < SpringApplication.run(DemoApplication.class, args); >>
Теперь создайте следующий файл в папке src/main/java/com/example/hello . Этот код содержит компонент Spring Boot, представляющий функцию, которую мы хотим запустить:
package com.example.hello; import com.example.model.*; import org.springframework.stereotype.Component; import java.util.function.Function; @Component public class Hello implements Function < @Override public Greeting apply(User user) < return new Greeting("Hello, " + user.getName() + "!\n"); >>
Функция Hello довольно специфична:
- Это java.util.function.Function . Она содержит бизнес-логику и использует стандартный API Java для преобразования одного объекта в другой.
- Так как у этой функции есть аннотация @Component , она представляет собой компонент Spring Bean и по умолчанию ее имя будет совпадать с именем класса, но начинаться с символа в нижнем регистре ( hello ). Соблюдение этого соглашения об именовании очень важно, если вы будете создавать в приложении другие функции. Это имя должно совпадать с именем Функций Azure, которые мы создадим в следующем разделе.
Создание функции Azure
Чтобы воспользоваться полным Функции Azure API, теперь мы кодируем функцию Azure, которая делегирует выполнение функции Spring Cloud, созданной на предыдущем шаге.
В папке src/main/java/com/example/hello создайте следующий файл класса функций Azure:
package com.example.hello; import com.microsoft.azure.functions.*; import com.microsoft.azure.functions.annotation.AuthorizationLevel; import com.microsoft.azure.functions.annotation.FunctionName; import com.microsoft.azure.functions.annotation.HttpTrigger; import com.example.model.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Optional; @Component public class HelloHandler < @Autowired private Hello hello; @FunctionName("hello") public HttpResponseMessage execute( @HttpTrigger(name = "request", methods = , authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request, ExecutionContext context) < User user = request.getBody() .filter(u ->u.getName() != null) .orElseGet(() -> new User(request.getQueryParameters().getOrDefault("name", "world"))); context.getLogger().info("Greeting user name: " + user.getName()); return request.createResponseBuilder(HttpStatus.OK) .body(hello.apply(user)) .header("Content-Type", "application/json") .build(); > >
Этот класс Java представляет собой Функцию Azure со следующими интересными возможностями:
- Класс имеет заметку @Component , поэтому это Spring Bean.
- Имя функции (определенное аннотацией @FunctionName(«hello») ) — hello .
- Класс реализует реальную функцию Azure, поэтому здесь можно использовать полный Функции Azure API.
Добавить модульные тесты
Этот шаг является необязательным, но мы рекомендуем выполнить его для проверки правильности работы приложения.
Создайте папку src/test/java/com/example и добавьте в нее следующие модульные тесты JUnit:
package com.example; import com.example.hello.Hello; import com.example.model.Greeting; import com.example.model.User; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; public class HelloTest < @Test public void test() < Greeting result = new Hello().apply(new User("foo")); assertThat(result.getMessage()).isEqualTo("Hello, foo!\n"); >>
Теперь можно протестировать функцию Azure с помощью Maven:
mvn clean test
Локальное выполнение функции
Прежде чем развертывать приложение в Функции Azure, протестируйте его локально.
Сначала упакуйте приложение в JAR-файл:
mvn package
Теперь, когда приложение упаковано, вы можете запустить его с помощью подключаемого модуля Maven azure-functions :
mvn azure-functions:run
Функция Azure должна быть доступна на локальном узле, использующем порт 7071. Чтобы протестировать функцию, можете отправить ей запрос POST с объектом User в формате JSON. Например, это можно сделать с помощью cURL:
curl -X POST http://localhost:7071/api/hello -d ""
Функция должна отправить ответ с объектом Greeting в том же формате JSON:
Ниже приведен снимок экрана, в верхней части которого показан запрос cURL, а в нижней — локальная Функция Azure:

Локальная отладка Функции
В следующих разделах описывается процесс отладки функции.
Отладка с использованием IntelliJ IDEA
Откройте проект в IntelliJ IDEA и создайте конфигурацию выполнения Удаленная отладка виртуальной машины Java для подключения. Дополнительные сведения см. в руководстве по удаленной отладке.

Запустите приложение, выполнив следующую команду:
mvn azure-functions:run -DenableDebug
При запуске приложения вы увидите следующие выходные данные:
Worker process started and initialized. Listening for transport dt_socket at address: 5005
Запустите отладку проекта в IntelliJ IDEA. Вы увидите такой результат:
Connected to the target VM, address: 'localhost:5005', transport: 'socket'
Отметьте точки останова, которые вы хотите отладить. Intellij IDEA войдет в режим отладки после отправки запроса.
Отладка с помощью Visual Studio Code
Откройте проект в Visual Studio Code и поместите следующее содержимое в файл launch.json:
Запустите приложение, выполнив следующую команду:
mvn azure-functions:run -DenableDebug
При запуске приложения вы увидите следующие выходные данные:
Worker process started and initialized. Listening for transport dt_socket at address: 5005
Запустите отладку проекта в Visual Studio Code и установите точки останова, которые вы хотите отладить. Visual Studio Code войдет в режим отладки после отправки запроса. Дополнительные сведения см. на странице, посвященной выполнению и отладке Java.
Развертывание Функции в Функциях Azure
Теперь вы собираетесь опубликовать функцию Azure в рабочей среде. Помните, что для настройки функции используются свойства, определенные в файле pom.xml.
Подключаемый модуль Maven должен пройти проверку подлинности в Azure. Если у вас установлен интерфейс командной строки Azure, выполните az login , прежде чем продолжать. Другие варианты проверки подлинности вы найдете в разделе Authentication (Аутентификация) репозитория azure-maven-plugins.
Запустите Maven, чтобы автоматически развернуть функцию:
mvn azure-functions:deploy
Теперь перейдите на портал Azure, чтобы найти созданный объект Function App .
- В общих сведениях о функции обратите внимание на ее URL-адрес.
- Чтобы проверка запущенной функции, выберите потоковую передачу журналов в меню навигации.
Теперь, как и в предыдущем разделе, с помощью cURL создайте запрос к запущенной функции, как показано в следующем примере. Не забудьте заменить значение your-function-name именем реальной функции.
curl https://your-function-name.azurewebsites.net/api/hello -d ""
Как и в предыдущем разделе, Функция должна отправить ответ с объектом Greeting в том же формате JSON:
Поздравляем! У вас есть функция Spring Cloud, выполняемая в Функциях Azure. Дополнительные сведения и примеры функций Spring Cloud см. в следующих ресурсах:
- Блог о функции Spring Cloud
- Справочные документы о функциях Spring Cloud
- Примеры функций Spring Cloud
Следующие шаги
Дополнительные сведения о Spring и Azure см. в центре документации об использовании Spring в Azure.
Бессерверные функции с функцией Spring Cloud
В этом уроке мы узнаем, как использовать функцию Spring Cloud.
Мы создадим и запустим простую облачную функцию Spring локально, а затем развернем ее на AWS.
2. Настройка функции Spring Cloud
Для начала реализуем с нуля и протестируем простой проект с двумя функциями, используя разные подходы:
- Реверс String с использованием простого метода
- И приветствующий, использующий специальный класс
2.1. Зависимости Maven
Первое, что нам нужно сделать, это включить зависимость spring-cloud-starter-function-web . Это будет действовать как наш локальный адаптер и вводит необходимые зависимости для локального запуска нашей функции:
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-starter-function-webartifactId> version>1.0.1.RELEASEversion> dependency>
Оставайтесь с нами, так как мы немного изменим это при развертывании на AWS.
2.2. Написание функции Spring Cloud
С помощью Spring Cloud Function мы можем выставлять @Bean типа Function , Consumer или Supplier как отдельные методы :
@SpringBootApplication public class CloudFunctionApplication public static void main(String[] args) SpringApplication.run(CloudFunctionApplication.class, args); > @Bean public FunctionString, String> reverseString() return value -> new StringBuilder(value).reverse().toString(); > >
Как и в этом коде, мы можем предоставить функцию обратной строки как функцию , которую может вызывать наша целевая функциональная платформа.
2.3. Локальное тестирование функции обратной строки
Spring -cloud-starter-function-web предоставляет функцию как конечную точку HTTP. После того, как мы запустим CloudFunctionApplication , мы можем свернуть нашу цель, чтобы протестировать ее локально:
curl localhost:8080/reverseString -H "Content-Type: text/plain" -d "ForEach User"
Обратите внимание, что конечной точкой является имя компонента.
И, как и ожидалось, на выходе мы получаем перевернутую строку:
resU gnudleaB
2.4. Сканирование функции Spring Cloud в пакетах
Помимо предоставления нашего метода как @Bean, мы также могли бы написать наше программное обеспечение как классы, реализующие функциональный интерфейс Function :
public class Greeter implements FunctionString, String> @Override public String apply(String s) return "Hello " + s + ", and welcome to Spring Cloud Function. "; > >
Затем мы можем указать пакеты для сканирования соответствующих bean-компонентов в application.properties :
spring.cloud.function.scan.packages=com.foreach.spring.cloudfunction.functions
2.5. Локальное тестирование функции приветствия
Опять же, мы можем запустить приложение и использовать curl для тестирования функции Greeter :
curl localhost:8080/greeter -H "Content-Type: text/plain" -d "World"
Обратите внимание, что конечная точка — это имя класса, реализующего функциональный интерфейс.
И, неудивительно, мы получаем ожидаемое приветствие в ответ:
Hello World, and welcome to Spring Cloud function.
3. Функция Spring Cloud на AWS
Что делает Spring Cloud Function настолько мощным, так это то, что мы можем создавать функции с поддержкой Spring, которые не зависят от облака. Самой функции не нужно знать, как она была вызвана или в какой среде она развернута. Например, мы можем легко развернуть это приветствие на платформе AWS, Azure или Google Cloud без изменения какой-либо бизнес-логики.
Поскольку AWS Lambda — одно из популярных бессерверных решений, давайте сосредоточимся на том, как развернуть в нем наше приложение.
Итак, давайте не будем больше ждать и развернем нашу функцию в облаке!
3.1. Зависимости Maven
Помните зависимость spring-cloud-starter-function-web , которую мы добавили изначально. Теперь пришло время изменить это.
Видите ли, в зависимости от того, где мы собираемся запускать функцию Spring Cloud, нам нужно добавить соответствующую зависимость.
dependency> groupId>org.springframework.cloudgroupId> artifactId>spring-cloud-function-adapter-awsartifactId> dependency>
Далее добавим необходимые зависимости AWS для обработки событий Lambda:
dependency> groupId>com.amazonawsgroupId> artifactId>aws-lambda-java-eventsartifactId> version>2.0.2version> scope>providedscope> dependency> dependency> groupId>com.amazonawsgroupId> artifactId>aws-lambda-java-coreartifactId> version>1.1.0version> scope>providedscope> dependency>
Наконец, поскольку мы собираемся загрузить артефакт, сгенерированный сборкой maven, в AWS Lambda, нам нужно создать затененный артефакт, то есть в нем все зависимости представлены в виде отдельных файлов классов, а не jar-файлов.
Зависимость spring-boot-thin-layout помогает нам уменьшить размер артефакта, исключив некоторые ненужные зависимости:
build> plugins> plugin> groupId>org.apache.maven.pluginsgroupId> artifactId>maven-deploy-pluginartifactId> configuration> skip>trueskip> configuration> plugin> plugin> groupId>org.springframework.bootgroupId> artifactId>spring-boot-maven-pluginartifactId> dependencies> dependency> groupId>org.springframework.boot.experimentalgroupId> artifactId>spring-boot-thin-layoutartifactId> version>1.0.10.RELEASEversion> dependency> dependencies> plugin> plugin> groupId>org.apache.maven.pluginsgroupId> artifactId>maven-shade-pluginartifactId> configuration> createDependencyReducedPom>falsecreateDependencyReducedPom> shadedArtifactAttached>trueshadedArtifactAttached> shadedClassifierName>awsshadedClassifierName> configuration> plugin> plugins> build>
3.2. Обработчики AWS
Если мы хотим снова открыть наш реверсер строк через HTTP-запрос, то Spring Cloud Function AWS поставляется с SpringBootRequestHandler. Он реализует RequestHandler AWS и отвечает за отправку запроса AWS нашей функции.
public class MyStringHandlers extends SpringBootRequestHandlerString, String> >
Spring Cloud Function AWS также поставляется с SpringBootStreamHandler и FunctionInvokingS3EventHandler в качестве других примеров.
Теперь может показаться немного странным, что MyStringHandlers — это просто пустой класс, но он играет важную роль как в качестве точки входа функции Lambda, так и в определении ее входных и выходных типов.
Как видно на снимке экрана ниже, мы укажем полное имя этого класса в поле ввода Handler на странице конфигурации AWS Lambda.
3.3. Как AWS узнает, какую облачную функцию вызывать?
Как оказалось, даже если в нашем приложении есть более одной функции Spring Cloud, AWS может вызвать только одну из них.
В следующем разделе мы укажем имя облачной функции в переменной среды FUNCTION_NAME на консоли AWS.
4. Загрузите функцию в AWS и протестируйте
Наконец, давайте создадим нашу банку с помощью maven, а затем загрузим ее через пользовательский интерфейс консоли AWS.
4.1. Создайте лямбда-функцию в консоли AWS и настройте ее
На странице консоли AWS Lambda в разделе «Код функции» мы можем выбрать среду выполнения Java 8 и просто нажать « Загрузить » .
После этого нам нужно указать в поле Handler полное имя класса, реализующего SpringBootRequestHandler , или функцию com.foreach.spring.cloud. MyStringHandlers в нашем случае:

А затем в переменных среды мы указываем, какой функциональный компонент Spring вызывать через переменную среды FUNCTION_NAME :

И после этого пришло время протестировать функцию Lambda, создав тестовое событие и предоставив образец строки:

4.2. Тестирование функции на AWS
Теперь мы сохраняем наш тест, затем нажимаем кнопку « Тест» .
И, как и ожидалось, мы получаем тот же результат, что и при локальном тестировании функции:

4.3. Тестирование другой функции
Помните, у нас есть еще одна функция в нашем приложении: Greeter . Давайте удостоверимся, что это тоже работает.
Мы изменим переменную окружения FUNCTION_NAME на Greeter :

Нажмите кнопку « Сохранить » и, наконец, снова кнопку « Тест» :

5. Вывод
Подводя итог, можно сказать, что хотя Spring Cloud Function находится на ранних стадиях, он является мощным инструментом для отделения бизнес-логики от какой-либо конкретной цели среды выполнения.
С его помощью один и тот же код может работать как веб-конечная точка, на облачной платформе или как часть потока. Он абстрагирует все транспортные детали и инфраструктуру, позволяя разработчику сохранить все знакомые инструменты и процессы и полностью сосредоточиться на бизнес-логике.
Как всегда, ознакомьтесь с исходным кодом этого руководства на GitHub .
- 1. Введение
- 2. Настройка функции Spring Cloud
- 2.1. Зависимости Maven
- 2.2. Написание функции Spring Cloud
- 2.3. Локальное тестирование функции обратной строки
- 2.4. Сканирование функции Spring Cloud в пакетах
- 2.5. Локальное тестирование функции приветствия
- 3.1. Зависимости Maven
- 3.2. Обработчики AWS
- 3.3. Как AWS узнает, какую облачную функцию вызывать?
- 4.1. Создайте лямбда-функцию в консоли AWS и настройте ее
- 4.2. Тестирование функции на AWS
- 4.3. Тестирование другой функции
Java и Serverless: Lambda — часть 2
Продолжение первой статьи про Serverless.
Теперь максимально простыми словами про лямбда-функции.
Что такое лямбда функция ?
Лямбда функции — являются строительным кирпичиком для бизнес-логики. Это сердце serverless технологий.
Это сервис, позволяющий запускать программный код без ваших таковых работающих серверов.
Ваш программный код запускается и бежит на компах “эластичной мощности” — т.е. сервис сам делает AutoScaling в зависимости от нагрузки.
Пример: у вас есть сервер который работает 24на7, даже если на него никто не заходит. Это плохо 🙁 Хотя сейчас большинство таких проектов, но это не есть хорошо. То, к чему мы стремимся — достичь макисмального комфорта и автоматизации!
С помощью лямбд функций можно написать код, который будет запускаться только при определенных условиях (например когда кто-то зашел на сервер по FTP или по какому-то определенному urlвашего приложения (например www.my-site.com), или например загрузил файл в S3 на AWS и т.д.).
Когда это “что-то” произошло, запустился ваш код без всякого сервера и начинает выполняться какая-то логика (например показать страничку пользователю), вместо того чтобы она работала беспрерывна 24на7.
Лямбда функции пишутся на: Node.JS, Java8, C#, Python.
В данном контексте рассмотрим лямбда функции на AWS. для других провайдеров стравнение будет чуть ниже.
Запуск лямбда функций производится через:
1) AWS Management Console
2) AWS CLI
3) API Gateway (он создает ссылку на каждую лямбда функцию и открыв ее в любом браузере запускаем нашу функцию). Также можно навесить на нее API Key чтобы защитить допуск к API Gateway URL, чтобы никто не смог взять и просто так запустить нашу функция, а только тот, у кого есть ключ к ней!
4) Какие-то события (S3 bucket data change, DynamoDB update, …)
Создаем лямбда:
1) AWS Management Console
Вначале создаем роли (permissions) для будущей лямбды:
идем в IAM->create new role.
Затем идем в Lambda ->create ->Role (выбираем созданную роль). Все!
Слева указаны тригеры на функцию (как ее можно запустить).
Снизу пишем логику: handler ->название нашей лямбда функции которая запускается.
Справа вверху Test — можно протестить нашу лямбда функцию (увидим ее результат и все пар-ры: id, сколько RAM использовалось на том сервере где она запустилась, время выполнения и т.д.), задав ей имя и присвоив разные параметры, если они есть в самой функции.
Снизу можно настроить параметры, как время выполнения функции (timeout), networking, debugging, role и т.д.
2) AWS CLI
В консольке напишите
aws lambda invoke — function-name=MyLambdaName — region=us-west-2 output.txt
Запускаем функцию с именем “MyLambdaName” которая находится в регионе “us-west-2” (вверху в url в браузере написано) и в какой файл сохранить результат, который вернет наша функция.
Тест (команды для линукса 🙂
3) API Gateway
Позволяет создать “Front Door” для ваших программ, чтобы получить доступ к вашим ресурсам на AWS. Другими словами он позволяет как-бы открыть дверь к вашей функции.
Как использовать ?
Идем на API Gateway -> Get Started -> выбираем New API -> придумываем имя, description, endpoint type (edge optimized). API готов, но он еще пока пустой.
Actions -> create method (например GET или POST) -> Lambda Functions -> выбираем регион (смотрим в каком регионе указана наша лямбда) -> название нашей функции -> Save.
Здесь мы видим как он будет работать: гейтвей запустится -> дернет лямбду -> лямбда что-то сделает и вернет нам какой-то результат и гейтвей вернет его нам (HTTP status).
Здесь же можно и протестировать.
В гейтвее слева есть API Keys ->Actions -> Create API Key.
Далее этот ключ надо пересылать вместе с нашим запросом URL в хедере.
Пример: в консоли
Снова идем в созданный запрос ->жмем на Method Request -> меняем API Key Required на true (по умолчанию стоит false). Теперь это говорит о том, что для запроса нам требуется наш API Key.
Чтобы получить заветную ссылку идем в Actions ->Deploy API -> выбираем stage, для которого хотим сделать ссылку. Все, ссылочка готова.
Теперь если вы просто вставите ссылку в браузер то увидите сообщение “Forbidden”. Наша лямбда функция не выполнилась, потому что не хватает ключа.
Теперь давайте ключ приконнектим к гейтвею: слева в меню Usage Plans-> пишем имя, Rate (сколько запросов в секунду)-> можно указать 1–2 для примера, enable quota (сколько запросов в месяц) можно выключить -> Next -> выбираем какую лямбда функцию используют и на каком stage ->Next -> добавляем ключ ->Save.
Тест запроса в командной строке:
Смотрите, насущная проблема
Бизнес аналитик что-то придумал, developer не так это понял и не так реализовал.
Некоторые облачные провайдеры предоставляют крутые инструменты для реализации бизнес-логики.
AWS Step Functions.
Azure Logic Apps: это визуальный конструктор, который позволяет описать бизнес процесс используя элементы ваших функций, как строительные блоки, и обрабатывать их возвращаемые значения.
Бизнес аналитик может посмотреть на реализацию бизнес-процесса и сказать например что так а что не так работает.
GCP: пока нету такого (хотя может уже и появился, не уверен, чтоыб не обмануть).
Когда вы строите облачные функции, у вас появляется возможность не страдать от того что где-то что-то не так происходит, а обрабатывать это все например в облачном конструкторе (создавать функции которые вызывают другие функции которые выполняют какую-то логику, добавляются в очереди и т.д.) + также мониторить работу на облачном дашборде. Это реально круто.
Другими словами: вы строите кирпичики (функции), а сама логика строится уже высокоуровневово.
Итоги AWS Lambda
При выборе обращаем внимание на:
2) Размер: максимальный используемый RAM, время (max время выполнения), объем временного хранилища (все что мы делаем пишется в RAM).
Минусы
Относительно долгий холодный старт — если функцией долго не пользовались, то запуск функции будет достаточно долгим (около 10 сек). Можно написать функции которые будут дергать эти функции, чтобы они не засыпали, но это уже костыльный костыль, не наш метод 🙂
Аналоги
Azure: Functions
Плюсы: достаточно быстрое облако, отзывчивое, гибкое.
GCP: Firebase Functions
1) самый лучший developer experience, т.к. когда вы разрабатываете функции, вы не будете их девелопить в облаке. В Гугле очень приятный эмулятор для этого, по сравнению с другими. У них есть поддержка shell, в котором можно просто дергать наши написанные функции обычной js-функцией, как вариант.
2) Хорошая поддержка дебаггинга (это больше для фронта).
Заметки
Цель — реализовать lambda с помощью JPA/Hibernate.
В случае AWS lambda есть много ограничений при использовании с JPA/Hibernate: возможно использовать JPA только в синхронной среде lambda или редко используемой.
Разработчики настоятельно рекомендуют или даже предупреждают нас ограничить себя синхронными писателями функций, поскольку это ограничит количество экземпляров Lambda и, следовательно, количество пулов JDBC, подключенных к вашей базе данных. (Это может стать серьезной проблемой на стороне DB, которая обычно принимает только несколько десятков или сотен соединений, но каждый пул JDBC будет = как бы это сказать, много соединений. А это доп нагрузка на вашу базюку.)
Вспомогательные инструменты
1) Kubeless
Позволяет вам деплоить ваши функции и реализовывать HTTP функции, функции по расписанию и т.д.
Минусы: на каждую функцию он создает контейнер (это очень дорого) -> проблемы с масштабированием.
Плюсы: это повышает надежность (падение одной функции никак не затронет другие функции).
2) Fission
Он берет ваш кластер (на котором например x-машин) и на каждой запускает fission node и уже внутри этой node запускает ваши функции.
Одно неосторожное движение может завалить всю VM.
Он также как и Kubeless может объединять несколько функций в один и тот же поток.
Плюсы: запуск функций быстрее, функции потребляют гораздо меньше ресурсов, функции гораздо отзывчивей.
Голопам по Европам, мы закнчили 🙂
Если вы нашли неточности в описании данной статьи, вы можете написать мне на email и я с радостью вам отвечу.
Kirill Sereda