Comments 25
Сейчас же большинство современных Java фреймворков генерируют код в рунтайме. Это и удобнее и больше простора для оптимизации.
Ага, а ещё замечательно увеличивается время старта сервера. И мешает делать AOT-компиляцию.
И почему лишняя секунда старта так важна — не совсем понятно.
Допустим разработчик, закрывает таску и деплоит на дев в конце рабочего дня. И что эта секунда даёт?
Кроме того, если следовать вашей парадигме, то вам нужно ещё выкинуть Hibernate, аспекты и некоторые другие фреймворки.
Вот уж воистину преждевременная оптимизация — корень всех зол.
Риалтайм и скорость стартапа в случае катастрофы или масштабирования — это разные штуки. Скорость стартапа важна, когда гипервизор вашего облака например, ставит на паузу приложение на одном хосте и переподнимает на другом из снимка бизнес-состояния. Или если приложение упало, и гипервизор поднимает его с сейфпоинта. Или тем паче, если никаких сейфпоинтов нет, и все переподнимается с нуля.
Разница во времени там не в секунде. Spring Boot грузится пару секунд только если вы не включили ничего, требующего его обычных "умных" механик. Подключаете Spring Security — и вся скорость запуска сразу проседает, наворачиваете работу с БД, кастомный AOP — и всё, скорость запуска в полной жопе. Где. собственно, и должна быть — Spring это не про скорость запуска.
И сколько секунд вам надо на запуск?
Если вам не надо «умные» механики, то не включайте их. Зачем из-за это переходить на фреймворк заведомо ущербнее — непонятно.
Мне кажется вы ищете проблем не там где они есть. Если ваше приложение постоянно падает, вы не можете запустить несколько копий параллельно и ваше приложение страдает от производительности то это явно не спринг в этом виноват.
И сколько секунд вам надо на запуск?
Чем меньше — тем лучше. Желательно ноль =)
Вы хотите сказать, что включение Spring Security, поднятие соединений с БД и кастомный AOP на других фреймворках по волшебству происходит быстрее?
Нет, оно не происходит быстрее. Оно просто не происходит. Ты отказываешься от Spring Security, удобных универсальных рефлективных коннекторов до баз данных, и начинаешь мучиться и пердолиться до тех пор, пока не получится что-то приличное, что влезает в целевые SLA
Например, в какой-то момент придется отказаться от обычной джавы и перейти на GraalVM. А может быть, придется отказаться от джавы вообще и перейти на C++, Golang и Node.js.
Например, можно написать на Java приложение в том же стиле, что на Ноде — у него есть основной fast event loop который стартует мгновенно, а всё остальное запускается в чисто асинхронном стиле. Тормоза будут происходить не на этапе старта, а на этапе выполнения каждого из запросов, особенно до прогрева локальных (по отношению к типу запроса) кэшей. Но при этом старт ивент лупа — это миллисекунды.
AOT мире своя система ценностей — "всё что можно вычить на этапе компиляции — должно быть вычислено на этапе компиляции". В C++ даже специальную фичу добавили — constexpr, завидуйте, кусайте локти джависты. Вон Micronaut Data может предвычислять какие-то SQL запросы, конечно. Благодаря этому, скорость выполнения таких действий в рантайме — тот самый ноль.
Другое дело, что на Spring Boot так не пишут. У Spring Boot есть вполне определенная система верований и ценностей. Есть понимание, что принято делать и как принято делать.
Если ваше приложение постоянно падает, вы не можете запустить несколько копий параллельно
Боюсь, мы тут говорим о совершенно разных вещах, отсюда такой рассинхрон. Я говорю о современных способах развертывания — это публичные и гибиридные облака, или приватные облака "как у Google", когда у тебя по полной используются технологии контейнеризации, включая кубернетисы, клауд-функции, и всё такое прочее. Не обязательно "тратить деньги на Амазон" (скорее экономить, но это другой разговор) — можно и у себя в гараже собрать точно такую же систему, опенстеки с кубернетисами в зубы и погали.
Если же речь идёт о том, чтобы поднять на Хецнере один-единственный сервак о сорока четырех ядрах и десяти терабайтах оперативки, и потом вдолбенить в него всю инфраструктуру компании, надеясь что сервак случайно не сотрут хостеры (как когда-то делали наши деды) — тут совершенно другой набор трейдоффов.
Как вы выражаетесь «современных» способов развёртывания — миллион и одна штука. Если у вас нет дублирования, то ни один из них вам не поможет.
Вы, надеюсь, в курсе, что в кубернетисе можно поднять несколько инстансов из одного образа? И в Амазоне тоже.
Нужны не просто миллисекунды, а именно миллисекунды на запуск. Если что-то упало, было перемещено, временно поставлено на паузу, отправлено на реконфигурацию и так далее — когда настанет его час, оно должно взлететь и вернуться в строй моментально, как чертик из табакерки. Особенно это актуально для cloud functions, которые только то и делают что перезапускаются.
Это вопрос совершенно ортогональный риалтаймовости после выхода на рабочую нагрузку. Например, в условной черной пятнице у вас могут начать виснуть и перезапускаться приложения — и важно, чтобы они вернулись назад как можно скорее. Но при этом сами эти приложения не только не обязаны быть риалтаймовыми (в смысле QNX), а им это даже вредно. Им по профилю нагрузки положены ни разу не риалтаймовые корутины. Включая джавовый Project Loom, а задолго до него был и вполне себе использовался Quasar. Нужно, чтобы вначале напринимать десятки тысячи соединений от клиентов и не упасть, уйти в спячку на долгоиграющих запросах вроде базы данных и файловой системы, и потом уже когда получится — проснуться и вернуть результат.
Мы ещё про джаву говорим?
Конечно про джаву. Например, есть чудесный фреймворк Vert.x с ивент-лупами, построенный с использованием не менее чудесного Netty — оба event-driven и non-blocking.
Его даже можно собрать с помощью GraalVM, и запустить в Docker, так что имидж в памяти займет 5 мегабайт, на диске — 40, и всё это с условно-мгновенной скоростью запуска.
В него можно даже встроить Micronaut DI, потому что жить без DI очень неприятно.
Видите, это платформа с совершенно другим набором трейдоффов и практик, чем у Spring Boot. Еще более другие, чем у Micronaut.
Это определённо ненормально лезть на прод посреди рабочего дня, чтобы чего-то там переконфигурить вручную без тестирования и быстро перезапуститить пока никто не заметит.
Нормальная практика — это когда мы деплоим новую версию приложения (например в куберентис), настраиваем, тестируем, а затем постепенно переводим трафик со старой версии на новую.
Если же у нас стартует нагрузка ты мы увеличиваем число инстанцев заранее.
Если же у меня вдруг начинает виснуть приложение, то мне надо отключить его от лоад балансера, сделать все дампы, собрать логи и пофиксить ошибку, чтобы такого больше не повторялось. А не в панике перезапускать, считая секунды
Перезапускаешь и переконфигурируешь не ты-как-человек, а гипервизор, каким бы он ни был. Условно говоря, в кубере можно сказать restartPolicy: "OnFailure", maxRetries: "100500" и наслаждаться результатом.
Приложение обычно нельзя отключить, даже если оно падает или виснет. Потому что им пользуются люди, и они не оценят. Скажем так, приложение всегда при каких-то условиях падает и виснет, не бывает идеальных приложений, это не повод чтобы отключить всё от балансировщика, разрегистрироваться в интернете и убить себя об стену :)
В кубере можно указать что угодно, но пользователь этого всё равно не заметит, когда есть дублирование. О чём вообще речь??
У вас нет дублирования? Так и скажите: мы не проходили теорию надёжности в университете и про дублирование не слышали.
И в случае failure надо собирать дампы и логи, анализировать и выпускать фиксы, а не заниматься бездумным перезапуском и прочей ерундой. Чтобы собрать memory дамп, к примеру, требуется намного больше чем 10 секунд, я вас уверяю.
Идеальных приложений не бывает, но нормальное приложение падает не чаще чем раз в год (условно), а не всегда. И в этом случае лишняя секунда даунтайма ничего не решает.
Я уж молчу, что при этом рвутся сессии, сбрасываются кэши и случается куча других неприятностей помимо даунтайма.
Если не относиться к фреймворкам исключительно как объектам моды (почему бы тогда не заняться коллекционированием шляп?), то подход может быть "подходящий" и "неподходящий" ;)
Есть же не только дихотомия на AOT vs JIT. Например, медленно компилирующее в AOT приложение — так же неудобно разрабатывать, как и жирную муть на Spring Boot которая стартует по минуте. Тебе как разработчику какая разница где ждать — один фиг ждать придется. Надо сюда ещё добавить как минимум ось про скорость фидбека, и еще одну ось про микросервисы против жирносервисов, и еще, и еще… короче, проблема куда больше
Если микросервис — действительно микро, а не монолит запиленный как микросервис, то разница между двумя "легковесами" вряд ли будет значительна.
С другой стороны заказчик на уменьшение счетов за облака обязательно скажет ееее, давай еще. Если крупный — ему экономия, а если мелкий, может вообще захочет на лямбдах AWS — и что тогда делать?
И вот, выбирая между хотелками разработчика и хотелками заказчика есть очень ненулевой шанс, что заказчик будет первичен.
Вообще, спринг (особенно бут) последних лет нередко монструозен. Это вряд ли будет продолжаться вечно. В разработке — да, удобен, но этот плюс ведь не главное, правда?
Все бы ничего, но основная задача так и не решена: приложение на Micronaut все-равно стартует долго. Когда все статично слинковано, и в рантайме отсутствует всякая кодогенерация, ожидание, что все запустится очень шустро. Но вот пустые Helidon и Quarkus почему-то стартуют быстрее.
«В идеале мы хотели бы вообще заменить Spring на Micronaut» — интервью с Грэмом Роше о перспективах развития Micronaut