Чи може Micronaut замінити Spring Boot? Розберемося на прикладі

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Привіт, мене звати Іван Козіков, я Full Stack Java Developer в NIX. Маю сертифікації Oracle і Kubernetes, люблю досліджувати нові технології та вивчати нові теми за напрямом Java.

Кожного року ресурс JRebel проводить опитування серед Java-розробників, якими фреймворками вони користуються. У 2020 році переміг Spring Boot із 83%. Однак у 2021 році його частка зменшилася до 62%. Одним із тих, хто збільшив свою присутність на ринку більше ніж у два рази, став Micronaut. Стрімке зростання популярності цього фреймворку викликає логічне питання: що в ньому цікавого? Я вирішив дізнатися, які проблеми долає Micronaut, та зрозуміти, чи може він стати альтернативою Spring Boot.

У цій статті я пройдуся по історії архітектури програмного забезпечення, що допоможе зрозуміти, чому виникли такі фреймворки та які завдання вирішують. Я виділю основні фічі Micronaut і порівняю два застосунки з ідентичними технологіями: один — на цьому фреймворку, а інший — на Spring Boot.

Від монолітів до мікросервісів і далі...

Сучасна розробка програмного забезпечення починалася з монолітної архітектури. В ній застосунок подається через один файл розгортання. Якщо ми говоримо про Java, то це буде один JAR-файл, в якому схована вся логіка та всі бізнес-процеси застосунку. І далі ви цей JAR-файл вигружаєте туди, куди вам потрібно.

Ця архітектура має свої переваги. Насамперед, із нею дуже легко почати розробляти продукт. Ви створюєте один проєкт і наповнюєте його бізнес-логікою, не задумуючись над комунікацією між різними модулями. Також на старті потрібно зовсім небагато ресурсів і легше робити інтеграційне тестування для всього застосунку.

Проте у цієї архітектури є й недоліки. Майже завжди застосунки на монолітній архітектурі переростали так званий Big Ball of Mud, «Великий шар бруду». Компоненти застосунку настільки перепліталися, що підтримувати їх потім — важко. І чим більшим ставатиме продукт, тим більше необхідно буде ресурсів і сил, щоб змінити щось у проєкті.

Тому на зміну прийшла мікросервісна архітектура. Вона розділяє застосунок на маленькі сервіси та залежно від бізнес-процесів створює окремі файли розгортання. Але нехай слово «мікро» не вводить вас в оману. Воно стосується бізнес-можливостей сервісу, а не його розміру.

Зазвичай мікросервіс орієнтований на один процес та його підтримку. Це дає кілька переваг. По-перше, оскільки це окремі незалежні застосунки, то можна підбирати необхідні технології для конкретного бізнес-процесу. По-друге, так значно легше збирати проєкт та розбиратися з ним.

Однак існують і мінуси. Потрібно від початку продумувати взаємозв’язок між сервісами, їх канали. Також на підтримання інфраструктури мікросервісів потрібно більше ресурсів, ніж у випадку з монолітом. І при переході до хмарних технологій це питання ще критичніше, адже потрібно платити за споживання застосунками ресурсів хмарної інфраструктури.

Яка різниця між фреймворками та мікрофреймворками

Щоб пришвидшити розробку програмного забезпечення, почали створювати фреймворки. Історично склалося, що для багатьох Java-розробників зразком такого рішення став Spring Boot. Однак з часом його популярність знизилась, і це можна пояснити. За роки розвитку Spring Boot досить сильно «набрав ваги», що не дозволяє йому працювати швидко та використовувати менше ресурсів, як того вимагає сучасна розробка ПЗ у рамках хмарного середовища. Саме через це його почали витісняти мікрофреймворки.

Мікрофреймворки — це досить новий вид фреймворків, які націлені на те, щоб досягти максимальної швидкості розробки вебсервісів. Зазвичай у них урізана більша частина функціоналу — на противагу до Full Stack рішень, як Spring Boot. Наприклад, дуже часто в них немає аутентифікації та авторизації, абстракцій для доступу до баз даних, вебшаблонів для відображення на UI компонентів тощо. Micronaut зароджувався так само, але переріс цей етап. Сьогодни у нього є все те, завдяки чому він може вважатися Full Stack-фреймворком.

Головні переваги Micronaut

Автори цього фреймворку надихалися саме Spring Boot, але зробили акцент на мінімальному використанні рефлексії та проксі-класів, що пришвидшує його роботу. Micronaut мультимовний та підтримує Java, Groovy і Kotlin.

Серед основних переваг Micronaut я виділяю наступні:

  • Абстракції для доступу до всіх популярних БД. У Micronaut наявні готові рішення для роботи з БД. Також вони надають API для того, щоб зробити свої класи та методи для доступу до баз даних. До того ж підтримують обидві варіації: як звичайний блокуючий доступ, так і реактивний.
  • Аспектно-орієнтоване API. В Spring Boot завдяки анотаціям можна дуже швидко розробляти ПЗ. Але ці анотації побудовані на рефлексії та створенні проксі-класів під час виконання програми. Micronaut надає набір готових до використання анотацій. За допомогою його інструментів можна написати власні анотації, які будуть використовувати рефлексію тільки на етапі компіляції, а не під виконання. Це пришвидшує запуск застосунку та покращує його роботу.
  • Нативно вбудована робота з хмарними середовищами. Про це детально поговоримо далі, я окремо розкрию важливі моменти.
  • Вбудований набір інструментів для тестування. Вони дозволяють швидко піднімати клієнти і сервери, необхідні для інтеграційного тестування. Також є можливість використовувати звичні бібліотеки JUnit та Mockito.

Що нам дає ahead-of-time компіляція

Я вже вказував, що Micronaut не використовує рефлексію та проксі-класи. Це можливо за рахунок компіляції перед виконанням — ahead-of-time compilation. Micronaut перед тим, як виконувати застосунок на момент створення пакету, намагається комплексно вирішити всі ін’єкції залежностей та скомпілювати класи для того, щоб не робити це під час роботи самого застосунку.

На сьогодні існує два основних підходи до компіляції: JIT — just-in-time та AOT — ahead-of-time. У JIT-компіляції декілька основних переваг. Перша: більша швидкість збірки артефакту — JAR-файлу. Їй не потрібно компілювати додаткові класи, вона просто робить це на етапі виконання. Також тут легше реалізована підгрузка класів саме на етапі виконання. При AOT-компіляції це потрібно вирішувати вручну.

Проте в AOT-компіляції час старту менший, адже все потрібне для роботи застосунку буде скомпільовано ще до того, як його запустять. За такого підходу розмір артефакту буде меншим, адже немає проксі-класів для роботи, через які потім виконуються компіляції. Плюс — з такою компіляцією потрібно менше ресурсів.

Важливо підкреслити, що в Micronaut «з коробки» вбудована підтримка GraalVM. Це окрема тема для статті, тому тут я глибоко у неї занурюватися не буду. Скажу одне: GraalVM — це віртуальна машина для різних мов програмування, побудована як раз на ahead-of-time компіляції. Вона дозволяє створювати виконувані файли image, які можна запускати у межах контейнерів. Там швидкість старту та роботи застосунку максимальна.

Проте, коли я спробував використати це в Micronaut, то навіть орієнтуючись на коментарі творця фреймворку, при створенні native image довелося позначити ключові класи застосунку такими, якими вони будуть докомпільовуватися під час виконання. Тому це питання треба ретельно досліджувати в порівнянні з рекламними обіцянками.

Як Micronaut працює з хмарними технологіями

Окремо треба розкрити нативну підтримку хмарних технологій. Я виділю чотири основні моменти:

  • Micronaut підтримує визначення оточення. Коли ми працюємо з хмарними середовищами, особливо коли є декілька вендорів, ми повинні створювати компоненти конкретно під ту інфраструктуру, в якій будемо використовувати застосунок. Для такого випадку Micronaut дозволяє створювати умовні компоненти, які залежать від певних умов. Він надає набір конфігурацій для різних оточень і намагається сам максимально визначити те оточення, на якому він відпрацьовує. Це значно спрощує роботу розробника.
  • У Micronaut є вкладені інструменти для визначення сервісів, необхідних для роботи застосунку. Навіть якщо він не знає його реальної адреси, він все одно спробує його знайти. Через це є декілька варіантів: можна використовувати вбудовані або ж додаткові модулі (наприклад, Consul, Eureka чи Zookeeper).
  • Можливість зробити load balancer із клієнтської сторони. Можна регулювати навантаження на репліки застосунку з клієнтської сторони, що трохи спрощує розробнику життя.
  • Micronaut підтримує serverless-архітектуру. Я неодноразово зустрічав серед розробників вислів «Я ніколи не буду писати лямбда-функції на Java». На Micronaut у нас є дві можливості писати лямбда-функції. Перша — використання API, яке безпосередньо дається інфраструктурою. Друга — визначати контролери, як у звичайному REST API, щоб потім використовувати їх в межах цієї інфраструктури. Micronaut підтримує AWS, Azure та Google Cloud Platform.

Хтось може заперечити, що все це є й на Spring Boot. Однак підключення хмарної підтримки там можливе завдяки додатковим бібліотекам чи стороннім модулям, а в Micronaut усе вбудовано нативно.

Порівнюємо застосунки на Micronaut і Spring Boot

Переходимо до найбільш цікавої частини! У мене є два застосунки, один з яких написаний на Spring Boot, інший — на Micronaut. Це так званий User Service, в якому є набір CRUD-операцій для роботи з юзерами. У нас підключена база даних PostgreSQL, підключення до якої відбувається через реактивний драйвер, брокер повідомлень Kafka та WEB Sockets. Також є HTTP-клієнт для спілкування зі сторонніми сервісами, щоб отримувати додаткову інформацію щодо наших юзерів.

Чому саме такий застосунок? Часто в презентаціях про Micronaut метрики проходять у вигляді застосунків Hello World, де не підключено жодних бібліотек і немає нічого, що є в реальному світі. А я хочу показати, як це працює в приближеному до справжньої практики зразку.

Хочу звернути увагу, наскільки просто перейти зі Spring Boot на Micronaut. Наш проєкт досить стандартний: є сторонній клієнт для HTTP, REST-контролер для хендлінгу операцій, сервіси, репозиторій тощо. Якщо ми зайдемо в контролер, то побачимо, що після Spring Boot все легко зрозуміти. Анотації дуже схожі. Вивчити це все не складе труднощів. Навіть самі анотації, як PathVariable, один в один до Spring Boot.

@Controller("api/v1/users")
public class UserController {
  @Inject
  private UserService userService;

  @Post
  public Mono<MutableHttpResponse<UserDto>> insertUser(@Body Mono<UserDto> userDtoMono) {
      return userService.createUser(userDtoMono)
          .map(HttpResponse::ok)
          .doOnError(error -> HttpResponse.badRequest(error.getMessage()));
  }

Це ж стосується і Service. Якщо б ми в Spring Boot писали анотацію Service, то тут у нас є анотація Singleton, яка визначає масштаб, на який вони поширюються. Також є схожий механізм ін’єкції залежностей. Вони, як і в Spring Boot, можуть використовуватися через конструктори, проводитися через property, на параметри метода. В моєму прикладі написана бізнес-логіка для того, щоб працював наш клас:

@Controller("api/v1/users")
public class UserController {
  @Inject
  private UserService userService;

  @Post
  public Mono<MutableHttpResponse<UserDto>> insertUser(@Body Mono<UserDto> userDtoMono) {
      return userService.createUser(userDtoMono)
          .map(HttpResponse::ok)
          .doOnError(error -> HttpResponse.badRequest(error.getMessage()));
  }

  @Get
  public Flux<UserDto> getUsers() {
    return userService.getAllUsers();
  }

  @Get("{userId}")
  public Mono<MutableHttpResponse<UserDto>> findById(@PathVariable long userId) {
    return userService.findById(userId)
        .map(HttpResponse::ok)
        .defaultIfEmpty(HttpResponse.notFound());
  }

  @Put
  public Mono<MutableHttpResponse<UserDto>> updateUser(@Body Mono<UserDto> userDto) {
    return userService.updateUser(userDto)
        .map(HttpResponse::ok)
        .switchIfEmpty(Mono.just(HttpResponse.notFound()));
  }

  @Delete("{userId}")
  public Mono<MutableHttpResponse<Long>> deleteUser(@PathVariable Long userId) {
    return userService.deleteUser(userId)
        .map(HttpResponse::ok)
        .onErrorReturn(HttpResponse.notFound());
  }

  @Get("{name}/hello")
  public Mono<String> sayHello(@PathVariable String name) {
    return userService.sayHello(name);
  }

Репозиторій теж має знайомий вид після Spring Boot. Єдине: я використовую в обох застосунках реактивний підхід.

@Inject
private UserRepository userRepository;

@Inject
private UserProxyClient userProxyClient;

Мені особисто дуже сподобався HTTP-клієнт для спілкування зі сторонніми сервісами. Його можна прописати декларативно, просто визначивши інтерфейс та позначивши, які типи методів це будуть, які Query-значення будуть передаватися, які це будуть частини URL і яке буде body. Все це швидко, до того ж, можна зробити свій клієнт. І знову ж таки, це можна зробити за рахунок сторонніх бібліотек і в межах Spring Boot за допомогою рефлексії та проксі класів.

@R2dbcRepository(dialect = Dialect.POSTGRES)
public interface UserRepository extends ReactiveStreamsCrudRepository<User, Long> {
  Mono<User> findByEmail(String email);

  @Override
  @Executable
  Mono<User> save(@Valid @NotNull User entity);
}
@Client("${placeholder.baseUrl}/${placeholder.usersFragment}")
public interface UserProxyClient {

  @Get
  Flux<ExternalUserDto> getUserDetailsByEmail(@NotNull @QueryValue("email") String email);

  @Get("/{userId}")
  Mono<ExternalUserDto> getUserDetailsById(@PathVariable String userId);

}

Тепер переходимо безпосередньо до роботи в терміналі. У мене відкрито два вікна. Зліва на жовтому фоні — Spring Boot, а справа на сірому — Micronaut. Я зробив білд пакетів. У Spring Boot це тривало майже 5 секунд, а Micronaut через AOT-компіляцію робить це довше: у нашому випадку процес займав чи не вдвічі більше часу.

Далі порівняв розміри артефакту. JAR-файл для Spring Boot займає 40 МБ, а для Micronaut 38 МБ. Не набагато менше, але все одно менше.

Після цього я виконав тест на швидкість старту застосунку. В Spring Boot Netty-сервер стартував на порті 8081, і це тривало 4,74 секунди. А ось в Micronaut ми маємо 1,5 секунди. Як на мене, досить суттєва перевага.

Наступний крок — дуже цікавий тест. У мене є Node.js-скрипт, якому передаємо як аргумент шлях до JAR-файлу. Він запускає застосунок і кожні півсекунди намагається отримати дані з URL, який я йому записав, — тобто наших юзерів. Цей скрипт завершує роботу, коли отримує першу відповідь. У Spring Boot він фінішував за 6,1 секунди, а в Micronaut — через 2,9 секунди — знову вдвічі швидше. При цьому на метриках видно: Spring Boot стартанув за 4,5 секунди, і результат був за 1,5 секунди. А в Micronaut ці цифри приблизно 1,5 та 1,3 с відповідно. Тобто виграш здобуто саме за рахунок більш швидкого старту застосунку і практично Spring Boot міг відповідати так само швидко, якщо б не робив додаткову компіляцію на старті.

Наступний тест: запустимо застосунки (старт займає 4,4 с та 1,3 с — на користь Micronaut) і подивимося, скільки пам’яті використають обидва фреймворки. Я використовую jcmd: передаю ідентифікатор процесу й отримую heap_info. На метриках видно, що в загальному застосунок на Spring Boot запросив 149 МБ для роботи та використовував у реальності 63 МБ. Повторюємо те саме для Micronaut, з тією ж командою, але поміняємо ідентифікатор процесу. Результат: застосунок запросив 55 МБ і використав 26 МБ. Тобто різниця по ресурсах — 2,5-3 рази.

Наприкінці наведу ще одну метрику, яка покаже: Micronaut — не «срібна пуля», йому є куди рости. З ApacheBench я симулював 500 запитів на Spring-сервер для Spring Boot, із concurrency на 24 запити. Тобто ми симулюємо ситуацію, коли 24 юзери одночасно роблять запити на застосунок. Із реактивною базою даних Spring Boot показує доволі непоганий результат: він може пропускати близько 500 запитів за секунду. Адже JIT-компіляція добре відпрацьовує на пікових навантаженнях на систему. Копіюємо процедуру на Micronaut, повторюємо декілька разів. Результат: близько 106 реквестів за секунду. Я перевіряв показники на різних системах і машинах — і плюс-мінус вони були однакові.

Висновок — простий

Micronaut — не ідеал, який може одразу замінити Spring Boot. Досі в ньому є якісь моменти, які на першому фреймворку більш зручні чи функціональні. Проте де в чому більш популярний продукт поступається менш популярним, але доволі просунутим конкурентам. При цьому у Spring Boot також є шляхи розвитку. Наприклад, та ж AOT-компіляція опціонально існує в Java з 9-ї версії, з 2017 року.

Я ж додам від себе: розробникам не треба боятися пробувати нові технології. Вони можуть надавати нам широкі можливості та дозволяти виходити за межі стандартних фреймворків, із якими ми зазвичай працюємо.

👍НравитсяПонравилось5
В избранноеВ избранном5
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Наступний тест: запустимо застосунки (старт займає 4,4 с та 1,3 с — на користь Micronaut) і подивимося, скільки пам’яті використають обидва фреймворки.

Якщо ви розповідали про AOT та GraalVM native images, то було б доречно згенерувати native images для кожного випадку та перевірити час запуску та обсяг використовуваної пам’яті. Я не впевнений, але думаю, що тут перевага Micronaut якщо і була б, то мінімальною.

Мені особисто дуже сподобався HTTP-клієнт для спілкування зі сторонніми сервісами. Його можна прописати декларативно, просто визначивши інтерфейс та позначивши, які типи методів це будуть, які Query-значення будуть передаватися, які це будуть частини URL і яке буде body.

У Spring є проект Spring Cloud Feign, який також дозволяє писати декларативний HTTP клієнт, більш того він підтримує і Spring MVC, і JAX-RS

Важливо підкреслити, що в Micronaut «з коробки» вбудована підтримка GraalVM.

Так і у Spring є аналогічна підтримка — проект Spring Native. І ви можете абсолютно спокійно компілювати Spring Boot додатки як GraalVM native images.

Я вже вказував, що Micronaut не використовує рефлексію та проксі-класи. Це можливо за рахунок компіляції перед виконанням — ahead-of-time compilation. Micronaut перед тим, як виконувати застосунок на момент створення пакету, намагається комплексно вирішити всі ін’єкції залежностей та скомпілювати класи для того, щоб не робити це під час роботи самого застосунку.

Тут переплутано все, що тільки можна.
Що означає компіляція перед виконанням? А що Spring Boot програми не компілюються? Для них є окремий інтерперетатор?
Головна відмінність Micronaut — в тому, що він генерує конфігурацію бінів на етапі компіляції програми, щоб не робити цього в run-time, і це дійсно прискорює завантаження. Але це не має жодного відношення до AOT.

Нативно вбудована робота з хмарними середовищами. Про це детально поговоримо далі, я окремо розкрию важливі моменти.

Ок, а в Spring є Spring Cloud, де є все те саме.

Вбудований набір інструментів для тестування. Вони дозволяють швидко піднімати клієнти і сервери, необхідні для інтеграційного тестування. Також є можливість використовувати звичні бібліотеки JUnit та Mockito.

І у Spring це є. Більше того, у Spring MVC це все працює швидше, тому що не вимагає підняття сервера.

Серед основних переваг Micronaut я виділяю наступні:

Абстракції для доступу до всіх популярних БД. У Micronaut наявні готові рішення для роботи з БД. Також вони надають API для того, щоб зробити свої класи та методи для доступу до баз даних. До того ж підтримують обидві варіації: як звичайний блокуючий доступ, так і реактивний.

Ну так і в Spring є така абстракція — Spring Data. Більше того, що він підтримує найбільш популярні NoSQL бази даних, а ось Micronaut Data — не підтримує, і не думають, що колись буде підтримує. То в чому тут перевага?

Мікрофреймворки — це досить новий вид фреймворків, які націлені на те, щоб досягти максимальної швидкості розробки вебсервісів. Зазвичай у них урізана більша частина функціоналу — на противагу до Full Stack рішень, як Spring Boot. Наприклад, дуже часто в них немає аутентифікації та авторизації, абстракцій для доступу до баз даних, вебшаблонів для відображення на UI компонентів тощо.

Ну, так і в Spring Boot немає нічого цього. Spring Boot — це каркас, де є в основному правила авто-конфігурації та налаштування. Якщо вам потрібна авторизація — додаєте Spring Security, якщо потрібна робота з Інтернетом — Spring MVC/WebFlux і т.д.

По-перше, оскільки це окремі незалежні застосунки, то можна підбирати необхідні технології для конкретного бізнес-процесу. По-друге, так значно легше збирати проєкт та розбиратися з ним.

Однак існують і мінуси. Потрібно від початку продумувати взаємозв’язок між сервісами, їх канали.

Тут ви трохи суперечите. Спочатку кажете, що мікросервіси незалежні один одного, а потім, що їм необхідна комунікація.

Ця архітектура має свої переваги. Насамперед, із нею дуже легко почати розробляти продукт. Ви створюєте один проєкт і наповнюєте його бізнес-логікою, не задумуючись над комунікацією між різними модулями

А чому не задумуючись ? Таке враження, що монолітну архітектуру пишуть лише джуніори чи неосвічені дикуни.

Проте у цієї архітектури є й недоліки. Майже завжди застосунки на монолітній архітектурі переростали так званий Big Ball of Mud, «Великий шар бруду». Компоненти застосунку настільки перепліталися, що підтримувати їх потім — важко. І чим більшим ставатиме продукт, тим більше необхідно буде ресурсів і сил, щоб змінити щось у проєкті.

З таким самим успіхом можна сказати, що класи в Java стали настільки великими і заплутаними, що потрібно всім переходити на функції та використовувати тільки їх.

Тому на зміну прийшла мікросервісна архітектура. Вона розділяє застосунок на маленькі сервіси та залежно від бізнес-процесів створює окремі файли розгортання

На жаль, але не прийшла. Зараз безліч проектів і справді успішних проектів, як і раніше, розробляються як моноліти і чудово почуваються.

Сучасна розробка програмного забезпечення починалася з монолітної архітектури. В ній застосунок подається через один файл розгортання. Якщо ми говоримо про Java, то це буде один JAR-файл, в якому схована вся логіка та всі бізнес-процеси застосунку. І далі ви цей JAR-файл вигружаєте туди, куди вам потрібно.

Не можу з цим погодитись. Якщо ви пишете про історію ПЗ, то повинні знати, що спочатку Java веб-застосунки деплоїлися як WAR/EAR-файли, і тільки з 2014 року, коли з’явився Spring Boot, з’явилася можливість використовувати JAR-файли.

Дякуємо за статтю, але є кілька коментарів:

У 2020 році переміг Spring Boot із 83%. Однак у 2021 році його частка зменшилася до 62%. Одним із тих, хто збільшив свою присутність на ринку більше ніж у два рази, став Micronaut

Так, все так, тільки він виріс із 2% до 4%. Не так вже й багато, щоб заявляти, що він почав домінувати над Spring Boot.

Я вирішив дізнатися, які проблеми долає Micronaut, та зрозуміти, чи може він стати альтернативою Spring Boot.

Зі статті не зовсім зрозуміло, ви використовуєте Micronaut для своїх проектів або просто вивчили для цієї статті.

I’m an Architect at Viber and I recently investigate the best framework for writing Java microservices. We operate at massive scale (a billion registered users) so I had to find the right fit. This is what I came up with.

# Spring Boot: It does a lot but it’s very prescriptive and too heavyweight for small microservices that need high performance

# Micronaut: Pretty good but my developers got frustrated by the poor documentation

# Vertx: This is what I chose as my favorite. It performs really well, it’s relatively lightweight and my developers really liked the code structure. It also handles threading very elegantly without the developer having to think about how many threads to create based on the server resources. Vertx optimizes itself based on the number of server cores.

If you are interested in getting more details, the developer implementing this at our company is a moderator on the “Ask the Architect” Viber channel
invite.viber.com/...​sZ36pYNQwPt6bOEW70qspJsrB

Після цього я виконав тест на швидкість старту застосунку. В Spring Boot Netty-сервер стартував на порті 8081, і це тривало 4,74 секунди. А ось в Micronaut ми маємо 1,5 секунди. Як на мене, досить суттєва перевага.

Судя по логам, при этом Spring Boot сервис открыл connection к Kafka, а Micronaut нет.

То же самое касается

У мене є Node.js-скрипт, якому передаємо як аргумент шлях до JAR-файлу. Він запускає застосунок і кожні півсекунди намагається отримати дані з URL, який я йому записав, — тобто наших юзерів. Цей скрипт завершує роботу, коли отримує першу відповідь

Так что если хотите сравнивать в цифрах, то сравнивать надо одинаковую функциональность

Quarks — це Java EE/Jakarta EE стек, тому він сильно прив’язаний до розробки Java EE, а Micronaut може розвиватися як хоче

Майже завжди застосунки на монолітній архітектурі переростали так званий Big Ball of Mud, «Великий шар бруду». Компоненти застосунку настільки перепліталися, що підтримувати їх потім — важко. І чим більшим ставатиме продукт, тим більше необхідно буде ресурсів і сил, щоб змінити щось у проєкті.

ок, є така проблема.

читаємо далі про її радикальне вирішення:

мікросервіс ...
Однак існують і мінуси. Потрібно від початку продумувати взаємозв’язок між сервісами, їх канали.

А моноліт не продумували від початку?

Ще питання
А чому з часом моноліт переростає у Big Ball of Mud?
Прояв якого — Компоненти застосунку настільки перепліталися
Що саме переплітається?
А переплітається: взаємозв’язок між компонентами, та їх канали

Бо немає принципової різниці, як реалізований той зв’язок, та ті канали
Є
Компонент А викликає компонет Б та чекає на відповідь
Компонент Б викликає компонент В, чекає на відповідь, щось там додає свого і відсилає відповідь компоненту А.
Тобто якщо намалювати UML — то потім хоч компоненти моноліта туди підстав, хоч мікро чи макро сервіси. та й те ж саме буде і у важкому фронтенді, на реактах/ангулярах — коли кому рендеритись, хто кого чекає, хто як повинен відреагувати, і що кому далі послати

Але з часом у моноліті буде Big Ball of Mud. А у системі з сервісів — не буде?
Наприклад як у моноліті — а у нас є випадкі, коли ефективніше буде щоб А викликав В напряму. Ну, ще, треба у разі такого виклика щоб В повідомив Б, що був викликаний напряму А... чекайте но, а давайте додамо сервіс Д, щоб оцю групу обміну запитами між Б і В закешував, ...

Зміна сигнатури метода то — тим більше необхідно буде ресурсів і сил, щоб змінити щось у проєкті.
А зміна протоколу обміну — не потребує сил? І чим більше різноманіття сервісів — чи не більше буде й різноманіття каналів зв’язку?

Але нехай слово «мікро» не вводить вас в оману. Воно стосується бізнес-можливостей сервісу, а не його розміру.

ну тобто у самому цьому сервісі теж можлива еволюція у Big Ball of Mud? бо він — не мікро, тобто не простенький.

Що саме унеможливлює переплітіння каналів взаємозв’язків у розподіленій на сервіси системі?
І чому це ж саме — неможливо викорститати для моноліту?

Тобто якщо намалювати UML — то потім хоч компоненти моноліта туди підстав, хоч мікро чи макро сервіси

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

и чем же «бизнес-процессы» отличаются принципиально от «процессов» что их не нарисовать в UML?
ну что вот «совсем не так»

подсказываю, я их, бизнес процессы неоднократно рисовал. на разных проектах
рисовал и, в качестве иллюстраций к спекам и в UML для API

поясните принципиальное отличие?

Возможно некорректно понял/выразился
Имел в виду что проблема не непосредственно

нарисовать в UML?

а сами процессы будут отличаться

106 реквестів за секунду

ну не знаю...

Ги... Це такий синтаксис у Java, чи це Kotlin? Декоратори схожі із декораторами TypeScript.

Це такий синтаксис у Java, чи це Kotlin

Java

Декоратори схожі із декораторами TypeScript

Молодьож не знає про анотації.

Логично было бы сравнивать Spring Boot + Spring Native с Micronaut, а то теплое с мягким получилось

Адже JIT-компіляція добре відпрацьовує на пікових навантаженнях на систему.

GraalVM позволяет переюзать эту оптимизацию через Profile Guided Optimisation, т.е. в большинстве случаев не будет разницы

Подписаться на комментарии