Ласточка в мире микросервисов

    Helidon – по гречески ласточка (Χελιδόνι), это такая маленькая птичка из отряда воробьиных с длинными острыми крыльями и характерным двойным хвостом. 

    Уверен, каждый из нас восхищается полетом и грацией этой птички, а то, как она живет в стаях, чем-то напоминает мир микросервисов.

    Helidon для нас, программистов, это набор библиотек прежде всего для разработки микросервисов, и является представителем семейства, назовем его, MicroProfile based средств разработки. Является полностью Open Source проектом, лежит на GitHub, и распространяется под лицензией Apache 2.0.


    Уверен, MicroProfile уже известен многим разработчикам, как набор спецификаций для создания микросервисов. Начав свое развитие в 2016м году всего с трех спецификаций - CDI, JAX-RS и JSON-P, да и то, взятых с Java EE, к концу 2020 году в версии 3.3 это уже 12 спецификаций целиком ориентированные на создание микросервисов:

    MicroProfile 3.3. В желтом с изменениями, в синем без.
    MicroProfile 3.3. В желтом с изменениями, в синем без.

    Major release версии MicroProfile происходит раз в год. Minor release-ы происходят раз в квартал. Как видно из иллюстрации, каждая из спецификаций может развиваться со своей скоростью. Некоторые спецификации могут не меняться от релиза к релизу.

    Существуют еще несколько спецификаций, не входящих в официальную версию MicroProfile, такие как, спецификации на поддержку GraphQL, Long Running Actions, Concurrency, Reactive Messaging, Event Data и Reactive DB Access.

    Сам себе MicroProfile существует под шапкой Eclipse Foundation и это не готовая реализация, а набор общепринятых интерфейсов и стандартов. Реализации этих интерфейсов создаются несколькими вендорами такими как Red Hat, IBM, Tomitribe, Payara и др. Первоначально имплементации стандартов были включены в крупные серверные продукты такие как OpenLiberty, TomEE и т.д. Но в последнее время с появлением концепции DevOps и общей идеи, что один сервер обслуживает одно приложение, и, более того, что сам сервер “упаковывается” в дистрибуцию продуктов, необходимость в полноценных серверных продуктах для реализации микросервисных архитектур постепенно исчезает. Сами платформы стремятся к своей миниатюризации.  Для многих, идейным вдохновителем стал Spring Boot. Небольшого количества кода и несколький аннотаций вполне достаточно, чтобы создавать fat-jar дистрибуций, которые потом так удобно упаковывать в docker контейнеры и деплоить в облака. MicroProfile дал солидную основу для развития этой идеи и ввел понятия стандартизация и портируемость для нее. Это значит, что код написанный в рамках этой спецификации будет работать на любой платформе, которае ее поддерживает. И конечный пользователь волен выбирать платформу не только в рамках технологий, но и по параметрам лицензии, коммерческой или некоммерческой поддержки, сертификации и законодательству в разных странах и т.д. И в случае изменений, портировать свой код с наименьшими потерями.    

    Heldon на данном этап своего развития  не стремится быть Full-Stack средством разработки как Spring Boot или Dropwizard, он ориентирован именно на микросервисы. Типичный микросервис на Helidon (под JVM) будет весить не более 20 Mb, что в несколько раз меньше чем, например, у Spring Boot. Ну а скомпилированный ahead-of-time в Native Image и того менее 10 Mb. 

    Что самое приятное,  API полностью в декларативном стиле и абсолютно портируемое в рамках стандартов MicroProfile.

    Как говорится - Talk is cheap, show me the code:

    @Path("hello")
    public class HelloWorld {
        @GET 
        public String hello() {
            return "Hello World";
        }
    }

    Буквально пара стандартных аннотаций - и можно уходить в продакшан!

    Helidon 2.1.0

    Так что же умеет “Ласточка” версии 2.1.0?

    Спецификации, поддерживаемые Helidon MP 2.1.1
    Спецификации, поддерживаемые Helidon MP 2.1.1

    А поддерживает Helidon все, что специфицированно в MicroProfile 3.3 плюс CORS и gRPC (Server + Client)

    Как же начать кодить? Есть два варианта - скачать CLI, запустить ее и ответить на пару вопросов (об этом далее), или просто в пустом Maven проекте добавить одну зависимость:

    <dependency>
      <groupId>io.helidon.microprofile.bundles</groupId>
      <artifactId>helidon-microprofile</artifactId>
    </dependency>

    Вышеупомянутая зависимость добавляет все функции, доступные в MicroProfile. Если вы хотите начать с меньшего основного набора функций, вы можете вместо этого использовать основной пакет. Этот пакет включает базовую функцию в MicroProfile (такую как JAX-RS, CDI, JSON-P / B и Config) и не включает некоторые дополнительные функции, такие как Metrics и Tracing. При желании вы можете добавить эти зависимости по отдельности.

    Зависимость только для базового набора фичей MicroProfile выглядит так:

    <dependency>
      <groupId>io.helidon.microprofile.bundles</groupId>
      <artifactId>helidon-microprofile-core</artifactId>
    </dependency>

    Давайте же сделаем небольшое Hello World JAX-RS приложение!

    Для этого нам нужен JAX-RS Resource Class:

    @Path("/")
    @RequestScoped
    public class HelloWorldResource {
        @GET
        @Produces(MediaType.TEXTPLAIN)
        public String message() {
            return "Hello World";
        }
    }

    Далее нам нужно создать JAX-RS Application:

    @ApplicationScoped
    @ApplicationPath("/")
    public class HelloWorldApplication extends Application {
    
        @Override
        public Set<Class<?>> getClasses() {
            return Set.of(
                    HelloWorldResource.class
            );
        }
    }

    Учитывая, что у нас CDI приложение, нам на данном этапе развития, все-таки нужно добавить пустой beans.xml в src/main/resources/META-INF

    <?xml version="1.0" encoding="UTF-8"?>
    <beans/>

    Далее просто в main запускаем наше приложение!

    public static void main(String[] args) {
        io.helidon.microprofile.server.Main.main(args);
    }

    Открываете вашу любимую консоль, в которой безусловно есть инструмент curl пишем:

    curl -X GET http://localhost:7001/

    и получаем! 

    {"message":"Hello World"}

    ТАДААААМ!! Все очень быстро и качественно! 

    Если нам не хочется такого низкоуровневого хардкора, уже есть готовый Maven Archetype, который мы просто вызываем:

    mvn -U archetype:generate -DinteractiveMode=false \
        -DarchetypeGroupId=io.helidon.archetypes \
        -DarchetypeArtifactId=helidon-quickstart-mp \
        -DarchetypeVersion=2.1.0 \
        -DgroupId=io.helidon.examples \
        -DartifactId=helidon-quickstart-mp \
        -Dpackage=io.helidon.examples.quickstart.mp

    Входим в созданную папку (или если вы изменили название - одноименную папку):

    cd helidon-quickstart-mp

    В ней у нас полность готовый maven проект, который мы можем сразу сбилдить!

    mvn package

    Проект создает jar-файл приложение для примера и сохраняет все runtime зависимости в каталоге target/libs. Это означает, что вы можете легко запустить приложение, запустив jar-ник:

    java -jar target/helidon-quickstart-mp.jar

    Пример - очень простой сервис «Hello World». Он поддерживает запросы GET для создания приветственного сообщения и запрос PUT для изменения самого приветствия. Ответ кодируется с помощью JSON. Например:

    curl -X GET http://localhost:8080/greet
    {"message":"Hello World!"}
    curl -X GET http://localhost:8080/greet/Joe
    {"message":"Hello Joe!"}
    curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Hola"}' http://localhost:8080/greet/greeting
    curl -X GET http://localhost:8080/greet/Jose
    {"message":"Hola Jose!"}

    Более того, прямо из коробочки нам доступны такие плюшки MicroProfile, как Здоровье (Health Check) и Метрики (Metrics):

    Про Здоровье можно узнать так:

    curl -s -X GET http://localhost:8080/health 

    … про Метрики в формате Prometheus:

    curl -s -X GET http://localhost:8080/metrics

    … но учитывая, что в таком формате никакой адекватный человек их прочитать не может, мы можем легко их получить в формате JSON:

    curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics

    В рамках этого артефакта генерируется и Docker файл, который позволяет нам легко сбилдить docker image:

    docker build -t helidon-quickstart-mp .

    … и сразу же его запустить:

    docker run --rm -p 8080:8080 helidon-quickstart-mp:latest

    Соответственно, все готово и к деплою в Kubernetes:

    kubectl create -f app.yaml

    kubectl get pods               # Wait for quickstart pod to be RUNNING

    Проверим как он там запустился:

    kubectl get service helidon-quickstart-mp

    В зависимости на каком порту все задеплоилось, можем проверить работает ли наш сервис:

    curl -X GET http://localhost:31431/greet

    Уверены, все работает как надо!

    Не забывайте за собой почистить мусор, как закончите:

    kubectl delete -f app.yaml

    Все очень здорово, работает очень быстро, и прямо из коробочки!!!

    Кстати, Helidon очень современный!

    Это значит, что он с самого начала живет в среде Java минимум версии 11. Это значит, что начиная JDK 9 нам доступна команд jlink, которая поддерживает сборку набора модулей и их зависимостей в custom runtime image. Плагин helidon-maven-plugin поддерживает простое создание такого runtime image для вашего приложения Helidon, что приводит к уменьшению размера и повышению производительности, выкинув все ненужное.

    Создать собственный образ среды выполнения можно двумя способами:

    • Локально, на рабочей машине

    • С использованием Docker

    Локально это делается безобразно просто, нужно просто использовать профиль jlink-image

    Данный профиль использует helidon-maven-plugin, который и создает наш кастомный образ. Кстати, при регенерации, плагин печатает много полезной информации, по тому как уменьшился размер образа.

    Каталог target/helidon-quickstart-mp это автономный пользовательский образ нашего приложения. Он содержит ваше приложение, его зависимости и модули JDK, от которых оно зависит. Вы можете запустить свое приложение, используя команду:

    ./target/helidon-quickstart-mp/bin/start

    Также в кастомный образ включен архив Class Data Sharing (CDS), который улучшает производительность запуска вашего приложения и оптимизирует in-memory footprint. 

    Архив CDS немного увеличивает размер вашего образа для оптимизации производительности. Но он может вырасти до значительного размера (десятки МБ). Размер архива CDS сообщается в конце вывода сборки.

    Если вы предпочитаете меньший размер образа (с немного увеличенным временем запуска), вы можете пропустить создание архива CDS, выполнив сборку следующим образом:

    mvn package -Pjlink-image -Djlink.image.addClassDataSharingArchive=false

    Но можно билдить и сразу в docker образ, причем тоже простой командой:

    docker build -t helidon-quickstart-mp-jlink -f Dockerfile.jlink

    Эта команда сделает полную сборку внутри Docker контейнера. При первом запуске это займет некоторое время, потому что будут загружены все зависимости Maven и скэшированы на уровне Docker. Последующие сборки будут намного быстрее, если вы не измените файл pom.xml. Если pom изменен, зависимости будут загружены повторно.

    И вуаля, можем запустить наше приложение прямо в Docker:

    docker run --rm -p 8080:8080 helidon-quickstart-mp-jlink:latest

    Можете его протестировать curl-ами quickstarter-a выше.

    Custom runtime images идеально подходят для использования, когда вам нужна вся производительность JDK JVM в достаточно компактной форме.

    Ну а что если нам нужен бескомпромиссно малый размер образа и минимальное время старта приложения?

    Для этого у нас есть GraalVM Native Images!

    Native images представляют собой ahead-of-time скомпилированный код Java, в результате которого создается автономный исполняемый файл. В результате приложение стартует почти мгновенно и имеет меньшие накладные расходы памяти во время выполнения по сравнению с выполнением на JVM.

    Чтобы оценить все прелести этой технологии, необходимо скачать и установить GraalVM и указать, где он установлен:

    # Ваш путь к установке может отличаться

    export GRAALVMHOME=/usr/local/graalvm-ce-20.0.0/Contents/Home/

    Далее нужно доустановить команду native-image:

    $GRAALVMHOME/bin/gu install native-image

    Мы создадим native image из нашего quickstarter-mp приложения.

    Вы можете создать native файл все также двумя способами:

    • На локальной GraalVM

    • И, конечно, же на Docker-е!

    На локальной машине все также до безобразия просто! У нас есть готовый профиль native-image , который использует все тот же helidon-maven-plugin. Просту билдим с его использованием:

    mvn package -Pnative-image

    Билд будет длиться дольше обычного, ибо выполняется огромное количество ahead-of-time компиляции. В конце мы получим нативный исполняемый файл! Да да, прям исполняемый файл, JVM больше не нужно! Запустить можно выполнив:

    ./target/helidon-quickstart-mp

    … и да, эта штука получилась просто неприлично быстрая и маленькая!

    Ну и как в случае с jlink, все манипуляции по билду в native image, можно проводить непосредственно в docker! Просто выполняем:

    docker build -t helidon-quickstart-mp-native -f Dockerfile.native

    Точно также, как и в случае с jlink, первый билд займет больше времени, но, все последующие билды будут использовать все уже скачанные зависимости.

    Чтобы запустить приложение выполняем:

    docker run --rm -p 8080:8080 helidon-quickstart-mp-native:latest

    … и как в прошлый раз наше приложение запускается неприлично быстро и занимает неприлично мало места!

    Native-images идеально подходят для приложений с высокими требованиями к горизонтальной масштабируемости, где важна возможность быстрого запуска множества экземпляров.

    На локальной машине native-image представляет собой выполнимый файл для платформы, на которой эта самая машина работает. И поддерживается пока только Linux и Mac. Windows пока ждем. А в Docker только Linux, соответственно. То есть на Mac можно сбилдить Linux binary.

    Тем не менее, native images имеют некоторые ограничения, и для долго работающих приложений, где запуск и занимаемый объем памяти не столь критичны, виртуальная машина Java SE HotSpot может быть более подходящей.

    Полный список модулей, которые поддерживают native image приведен тут:

    https://helidon.io/docs/v2/#/mp/aot/01introduction

    Следует отметить, что поддержка native-image реализована на полной версии CDI без каких либо ограничений!

    Как вы видите, Helidon по максимуму использует современные достижения в Java-строении, и предлагает все варианты билдов для наиболее оптимальных результатов!

    Но это еще не все!..

    Tooling

    В Helidon 2 появилась консольная утилита, которая помогает нам создавать, а также ускорят наш процесс разработки.

    CLI Helidon позволяет легко создавать проект Helidon, выбирая его из набора архетипов. Он также поддерживает developer loop, который выполняет непрерывную компиляцию и перезапуск приложения. Вы можете просто кодить, а CLI заметит все изменения которые вы внесли, и вы сразу их увидите в действии

    CLI распространяется как отдельный исполняемый файл (скомпилированный с использованием GraalVM) для простоты установки. В настоящее время он доступен для загрузки для Linux и Mac. Просто загрузите binary, установите его в месте, доступном из вашего PATH, и все готово.

    Далее наберите:

    helidon init

    … и ответьте на несколько вопросов… и все готово!

    Откройте созданный проект в любимом IDE и начинайке кодить!

    На данный момент с помощью инструмента можно создать примерный проект с полной поддержкой MicroProfile. Можно также создать проект, основанный целиком на низкоуровневых реактивных API для максимальной производительности.

    И на данный момент, третьим вариантом приложения является пример с использованием DB Client.

    Функционал CLI Helidon будет расширен совсем скоро. Но того, что есть сейчас уже достаточно для 80% случаев в ежедневной разработке.

    Стоит также отметить, что у Helidon есть поддержка и на стороне Intellij IDEA. Достаточно лишь нажать два раза shift, набрать Endpoints, и IDEA нам их покажет:

    Поддержка в Intellij Idea
    Поддержка в Intellij Idea

    Welcome to the Danger Zone!

    Как мы уже смогли убедиться, Helidon прекрасное средство разработки, значительно упрощающее создание Микросервисов. С помощью нескольких аннотаций и минимального количества кода можно практически без усилий написать полноценное продукционное приложение. Но этим сейчас никого не удивишь. Очень многие это могут. Правда, стоит отметить, что, Helidon будучи MicroProfile based, обеспечивает полную портируемость программ идущих на нем в рамках спецификаций. Стандартизация - основной конек и акцент Helidon. 

    Но вся эта магия дается не бесплатно, за нее приходится платить производительностью. Архитектура Helidon строится на CDI Extensions, которые вызывают низкоуровневое API. Все обслуживание данной CDI инфраструктуры стоит времени.

    Так что это за низкоуровневое API? Данное API носит имя Helidon SE.

    По сути Helidon SE представляет собой очень компактный реактивный toolkit построенный поверх Netty, и использует последние нововведения Java SE, такие как reactive streams, асинхронное и функциональное программирование, а также fluent-style APIs.

    Архитектура Helidon
    Архитектура Helidon

    По сути, в некотором смысле мягкий и пушистый Helidon является оберткой над суровым и хардкорным Helidon SE.

    Helidon SE представляет из себя неблокирующий микрофреймворк, с микроскопическим memory footprint, где особое внимание уделяется асинхронности и производительности. В нем нет никакой “магии” - никакой dependency injection, практически нет аннотаций, только новейшие фичи Java (начиная с версии 11). Helidon SE предлагает полный набор API для создания реактивных приложений в функциональном стиле.

    На данный момент Helidon SE поддерживает следующие спецификации:

    Модули, поддерживаемые Helidon SE
    Модули, поддерживаемые Helidon SE

    Зеленым цветом обозначены экспериментальные компоненты. В рамках Helidon экспериментальные означает, что разработчики оставляют за собой право менять API в минорном релизе.

    Так как же писать на этом звере? На самом деле тоже довольно легко. Код получается многословнее, выразительнее и без каких либо аннотаций.

    Routing routing = Routing.builder()
        .get("/hello", (req, res) ->
         res.send("Hello World"))
        .build();
    
    WebServer.create(routing)
       .start();

    Особое внимание стоит уделить Helidon DB Client. В нем удалось реализовать полность неблокирующий доступ к базам данным, при этом независимо от того, является ли подлежащий JDBC драйвер БД блокирующим или нет. Из коробочки поддерживаются такие реляционные СУБД, как Postgres, MySQL, MariaDB (вообще все для чего есть JDBC драйвер), a также нереляционные как MongoDB.

    Вот так, например выглядит вызов Select в транзакции:

    dbClient.inTransaction(tx -> tx
        .createQuery("SELECT name FROM Pokemons WHERE id = :id")
        .addParam("id", 1)
        .execute()
    
    );  

    А так Update вызов для MongoDb:

    dbClient.execute(exec -> exec
        .createUpdate("{\"collection\": \"pokemons\","
            + "\"value\":{$set:{\"name\":$name}},"
            + "\"query\":{id:$id}}")
        .addParam("id", 1)
        .addParam("name", "Pikachu")
        .execute()
    );

    На данный момент DB Client  

    При этом, конфигурация происходит централизованно через Helidon Config. Например:

    db:
      source: "jdbc" 
      connection:
        url: "jdbc:mysql://127.0.0.1:3306/pokemon?useSSL=false" 
        username: "user"
        password: "password"
      statements: 
        ping: "DO 0" 
        select-all-pokemons: "SELECT id, name FROM Pokemons"

    Это делает код частично портируемым, позволяет менять базу данных без перекомпиляции.

    Больше информации и примеров в официальной документации https://helidon.io/docs/v2/#/se/dbclient/01introduction

    Helidon SE также предлагает свой реактивный неблокирующий Web Client. Он поддерживает все Helidon SE observability фичи, и расширяем по своему дизайну. Пользоваться им исключительно легко:

    WebClient client = WebClient.builder()
            .baseUri("http://localhost")
            .build();
    
    Single<String> response = client.get()
            .path("/endpoint")
            .request(String.class); 

    Его можно конфигурировать через Helidon Config.

    Больше инфы в прекрасной и подробной документации https://helidon.io/docs/v2/#/se/webclient/01introduction

    Стоит отметить и Reactive Streams / Messaging поддержку в Helidon.

    Helidon имеет собственный набор реактивных операторов, независимых вне экосистемы Helidon. Эти операторы могут использоваться с реактивными потоками на основе java.util.concurrent.Flow. Цепочку операторов потоковой обработки можно легко построить с помощью io.helidon.common.reactive.Multi или io.helidon.common.reactive.Single для потоков с одним значением.

    Reactive Streams API применяется очень широко и полность совместимо с существующими API и имплементациями (RxJava, Reactor, и т.д.).

    Уже есть интеграция с Kafka и Oracle Streaming Service.

    Поддержка JMS и Oracle Advanced Queueing уже на подходе.

    Пример Multi:

    AtomicInteger sum = new AtomicInteger();
    Multi.just("1", "2", "3", "4", "5")
            .limit(3)
            .map(Integer::parseInt)
            .forEach(sum::addAndGet);
    
    System.out.println("Sum: " + sum.get());
    
    > Sum: 6

    Пример Single: 

    Single.just("1")
            .map(Integer::parseInt)
            .map(i -> i + 5)
            .toStage()
            .whenComplete((i, t) -> System.out.println("Result: " + i));
    
    > Result: 6

    Особую гордость разработчиков Helidon составляют gRPC Server & Client. Реализации обоих модулей по сути написали с нуля, без каких либо зависимостей от библиотек Google, и прекрасно работают в модульной среде Java9+.

    Минималистичное gRPC приложение выглядит так:

    public static void main(String[] args) throws Exception {
          // Implement the simplest possible gRPC service.  
          GrpcServer grpcServer = GrpcServer
                          .create(GrpcRouting.builder()
                          .register(new HelloService()) 
                          .build())
                          .start() 
                          .toCompletableFuture()
                          .get(10, TimeUnit.SECONDS); 
          System.out.println("gRPC Server started at: http://localhost:"    
          + grpcServer.port()); 
    }
    
    static class HelloService implements GrpcService { 
        @Override
        public void update(ServiceDescriptor.Rules rules) {
             rules.unary("SayHello", ((request, responseObserver) -> complete(responseObserver, "Hello " + request))); 
        }
    }

    Но, Helidon может быть не только сервером gRPC услуг, но и сам быть их потребителем.

    Клиент Helidon gRPC предоставляет фреймворк для создания клиентских приложений gRPC. Данный фреймворк обеспечивает единый способ доступа к службам gRPC, которые используют либо Protobuf, либо какой-либо настраиваемый формат сериализации. 

    Пример клиента выглядит следующим образом:

    public static void main(String[] args) throws Exception {
        // Дескриптор gRPC, который использует унарный метод. По умолчанию, Java 
        // сериализация, сериализация и десериализация.
        ClientServiceDescriptor descriptor = ClientServiceDescriptor
          .builder(HelloService.class)
          .unary("SayHello")
          .build();
    
        // Создаем канал на порту 1408 
        Channel channel = ManagedChannelBuilder.forAddress("localhost", 1408)                           
                                                   .usePlaintext()
                                                   .build();
        // Ну и инициализируем непосредственно клиент 
        GrpcServiceClient client = GrpcServiceClient.create(channel, descriptor);                   
        // Теперь можно вызывать метод SayHello, который возвращает CompletableFuture
        CompletionStage<String> future = client.unary("SayHello", "Helidon gRPC!!"); 
        // С чистой совестью печатаем результат!                
        System.out.println(future.get());                                                           
    }

    gRPC и сервер и клиент уже стабилизированы и готовы использованию в production. Больше информации: https://helidon.io/docs/v2/#/se/grpc/01_introduction

    Стоит отметить, совсем недавно, при интеграции Helidon и Neo4J, как раз было использовано реактивное API Neo4J, обернутое со стороны Helidon SE в Multi, и далее асинхронно отправлено в Response. Получилась отличная кооперация между ребятами из Neo4J и Helidon! Примеры будут скоро! Сейчас идет процесс полной интеграции Neo4j и Helidon.

    Учитывая, что драйвер Neo4J полность совместим с GraalVM, весь проект полностью компилируется в Native. … и он очень быстро работает!

    Кстати, раз уж речь пошла о производительности, стоит отметить, что Helidon чаще лучше других справляется со многими операциями. Порой в два раз лучше!

    Операций в секунду. Больше лучше.   Код данного бенчмарка доступен здесь: https://github.com/danielkec/helidon-jmh
    Операций в секунду. Больше лучше.  Код данного бенчмарка доступен здесь: https://github.com/danielkec/helidon-jmh

    Ну и в целом, Helidon SE -  тайное скрытое оружие для любителей перформанса, реативщины и прочего хардкора. 

    Судя по отзывам, пользователи отмечают очень высокую интуитивность архитектуры Helidon SE. Просто нажмите точку в конце выражения в примерах стартеров, и из intellisense-a вашего IDE становится понятно, что еще можно сделать и какую функциональность приктутить.

    Вместо того, чтобы закрывать низкоуровневые API, команда Helidon открыла их для всех. Понятно, что для 90% случаев “магии” будет вполне достаточно, но часто те 10% “остальных хардкорных случаев” могут быть абсолютно критичными с точки зрения производительности и скорости реакции. Необходимо написать чуть больше кода, но работать он будет кратно быстрее!   

    Отлично.. но как сие тестировать?

    На самом деле очень просто! Helidon SE это чистая Java без магии. Можно тестить просто Junit :)

    Но для Helidon MP, учитывая, что там много магии от CDI, существует специальные помощники.

    Для начала нужно добавить одну зависимость:

    <dependency>     
     		<groupId>io.helidon.microprofile.tests</groupId>     
        <artifactId>helidon-microprofile-tests-junit5</artifactId>     
        <scope>test</scope> 
    </dependency>

    Тест можно обозначить аннотацией @HelidonTest. Эта аннотация запустит контейнер CDI перед вызовом любого тестового метода и остановит его после вызова последнего метода. Эта аннотация также позволяет выполнять Injection в сам тестовый класс. Поэтому само тестирование получается очень простым:

    @HelidonTest
    @DisableDiscovery
    @AddBean(MyBean.class)
    @AddExtension(ConfigCdiExtension.class)
    @AddConfig(key = "app.greeting", value = "TestHello")
    class TestNoDiscovery {
        @Inject
        private MyBean myBean;
    
        @Test
        void testGreeting() {
            assertThat(myBean, notNullValue());
            assertThat(myBean.greeting(), is("TestHello"));
        }
    }

    Как видно из примера можно применят и другие аннотации, позволяющие отключать Beans Discovery, добавить конфигурацию и т.д.

    Кстати, когда генерируются примеры квикстартеров, они все идут с тестами. Можно из изучить там. Все очень интуитивно!

    Что же в конце концов получает пользователь?

    Все вышеперечисленное просто замечательно, но, уверен, многим из нас хочется видеть цифры! Действительно ли Ласточка такая маленькая?

    Сколько может весить наше приложение? На самом деле вариантов может быть несколько, в зависимости от того как мы его билдим. Helidon предлагает несколько build профилей.

    1. Executable JAR: Hollow jar. Все внешние зависимости сохраняются отдельно. Это особенно полезно в условиях использования Docker-а и его layering-а;

    2. Jlink image: как уже было сказано, Helidon живет на Java версии не ниже 11, поэтому спокойно пользуется всеми “плюшками”, в том числе Jlink! Тем самым создается оптимизированное по размеру JRE + приложение. В результате имеем лучший старт, меньший размер.. и никаких ограничений по коду!

    3. Ну и конечно GraalVM native-image: с определенным количеством известных ограничений по коду и runtime операциями мы получаем самое быстрое время старта, минимальный memory footprint и занимаемый размер!

    Если в цифрах то это выглядит так:

    И место на диске:

    Ну и конечно время старта!!!:

    Более чем достойные результаты! Особенно если посмотреть на Helidon SE приложение скомпилированное в native-image!

    А, как известно, время (и место) это деньги! Особенно в облаках! 

    Вместо вывода. 

    Наша ласточка продолжает очень быстро развиваться, но остается все такой же быстрой и изящной. Она маленькая, скоростная и очень маневренная! Helidon сочетает в себе такие качества как стандартизация и портируемость, благодаря поддержке MicroProfile, а также высочайшая производительность, благодаря написанным с нуля реактивным низкоуровневым API и их реализаций на новейших версиях Java, начиная с версии 11, с полноценным использованием всех нововведений.

    Наличие доступа и к низкоуровневым высокопроизводительным API позволяет создавать высоконагруженные реактивные приложения, без потерь на магию.

    Для начала работы нужно просто сходить на сайт http://helidon.io и ознакомится с очень подробной документацией с кучей примеров. Для любителей видео есть отличный канал на ютубчике, а для любителей почитать - официальный блог :)

    Ну а еще лучше скачать CLI :)

    На данный момент ведется разработка имплементаций как основных, так и не основных спецификаций MicroProfile, таких как Long Running Actions и GraphQL. Все это с обязательной поддержкой GraalVM native-image! 

    И несмотря на то, что “Ласточка” и так демонстрирует солидные показатели производительности, над ними продолжает вестись большая работа, чтобы сделать ее еще быстрее. 

    Helidon это полноценное, готовое к production, решение, созданное на основе новейших версий Java, без каких либо компромиссов. К тому же полностью стандартизованное!

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 12

      +4
      А где посмотреть реализацию какого-то целого приложения, типа PetClinic на Helidon?

      На Spring есть, на Quarkus есть, и на Micronaut есть.

        +2

        О да, это уже in progress. PetClinic это святое!
        Но пока CLI позволяет сгенерировать отличные очень компактные quickstarter-ы :)

          +2
          Я уже ниже ответил, но и тут продублирую. Реализация магазина с носками на Хелидоне:
          github.com/helidon-sockshop/sockshop
          +3

          А если сравнивать с Quarkus есть очевидные плюсы?

            +4
            Из того, что известно: Quarkus не реализует полностью CDI и содержит хаки, которые не соответствуют спецификации. Хотя сама спецификация тоже не восторг.
            +3

            Очевидные плюсы:


            • Живет на Java 11+, по сему использует все плюшки новых версий (modularity например).
            • Полная поддержка CDI. Все работает по стандарту! Более того и в native-image.
            • Наличие SE и всего того, что есть в его спецификациях и реализациях (DB client, реактивщина и т.д.)

            Стоит отметить, что полная поддержка стандартов, оптимизация их имплементаций это основной конек Helidon, и для JVM и для native-image.
            Сейчас много работы ведется над интеграциями с другими технологиями (Neo4j, Microstreams и т.д)

              0
              каким образом обеспечена неблокирующая работа с бд, если используются обычные (блокирующие) драйвера?
                +2
                Вызовы врапятся ExecurorService-ом.
                +2
                Типичный микросервис на Helidon (под JVM) будет весить не более 20 Mb, что в несколько раз меньше чем, например, у Spring Boot.

                Там, где выбирают Spring Boot, на это всем пофиг. А вот быстрое время старта может пригодится, если его не «съест» инициализация БД или подключение к Kafka. Но тоже захотелось увидеть какой-то пример реального приложения.
                  +1
                  Небольшое, но вполне себе приложение:
                  helidon.io/docs/v2/#/mp/guides/02_quickstart
                    +2
                    Нет, это не то. Я про приложение, которое, например, реализует несколько ендпоинтов, при этом что-то сохраняет в БД и взаимодействует с другими микросервисами. Т.е. примерно то, что обычно и бывает на практике.
                      +2
                      Ок, вот реализация магазина с носками на Хелидоне:
                      github.com/helidon-sockshop/sockshop

                      Думаю, это то, что вы ищете.

                Only users with full accounts can post comments. Log in, please.