Comments 22
2) «программист забыл проверить на null» — а вы не пробовали код покрывать тестами? Слышал, это помогает
3) «достаточно занудного и трудоёмкого процесса выкладывания новой» — может стоит упростить процесс? Уверен, что можно разбить части на кусочки и релизить «атомарно», либо другим способом упростить
А вообще, данный подход из разряда «ху....-ху… и в продакшен». Печально слышать о его использовании в такой компании
Денег ввалились и в разработку немало. Потому что это не про HCR
Вопрос такой: а если патчуемый код уже заинструменчен каким-нибудь фреймворком в рантайме? Будет ли повторно вызываться инструментация фреймворка или нет?
Другой вопрос: а как вы тестируете сам процесс патчинга? HCR очень деликатная и ограниченная штука, и успешно пропатчить код может лишь в некоторых случаях. И вот у вас зафейлился патч на продакше. Что делать дальше?
Вообще, я нахожу использование такого подхода более чем странным особенно для Одноклассников. Как я себе представляю подобные системы, перезагрузка одного сервиса никак не должна влиять на общую работу: микросервисы, распределенность и все такое… Если же система монолитная или ее рестарт занимает значительное время, то можно попытаться разделить всю логику на контексты внутри приложения при помощи класслоадеров и рестартать их вбелую по мере необходимости. Или например использовать OSGi, где все это уже реализовано из коробки ввиде модулей. Но патчить на продакшне через интерфейс, предназначенный для дебага — это странное решение.
а если патчуемый код уже заинструменчен каким-нибудь фреймворком в рантайме? Будет ли повторно вызываться инструментация фреймворка или нет?Смотря как фреймворк работает. Если он регистрирует инструментацию через Instrumentation.addTransformer, то после патчинга трансформация будет выполнена повторно.
а как вы тестируете сам процесс патчинга?Зависит от сложности патча. В общем случае применяем сначала на тестовом сервере, потом на одном продакшн сервере, проверяем функциональность руками и/или автотестами, затем применяем на группе хостов, смотрим графики, и, наконец, на всём продакшне. Если патч сломался, его можно отменить применением обратного патча, либо уже традиционной процедурой апдейта. На практике до откатывания патча ни разу дело не доходило.
перезагрузка одного сервиса никак не должна влиять на общую работуПерезагрузка одного сервера — да. А если надо рестартануть кластер из 600 инстансов? Это надо делать частями, с выводом трафика и плавным заводом, при этом старт и прогрев приложения может занимать десятки минут. Именно так и делается при плановых апдейтах, но это занимает время. Патчинг не заменяет апдейты. Он для простых, но срочных фиксов.
патчить на продакшне через интерфейс, предназначенный для дебага — это странное решениеЭто необычно, согласен. Поэтому и удостоилось статьи. Ключевая особенность фиксов через HCR — что это происходит без даунтайма и без потери состояния. Все текущие соединения, запросы, накопленные данные, кеши, значения переменных — всё остаётся. Не требуется никакой активации/деактивации модулей и никакой миграции со старой версии на новую. OSGi в данном случае не поможет.
К примеру на Load Balancer перевести трафик на чистый сервер, потом спокойно рестартануть сервис. Такой подход добавляет большую надежность общей системы, и убирает приседания с байт кодом. что-то типа netflix style.
Для особенно нетерпеливых и ленивых еще можно поставлять с каждым приложением простую UI висящую на 8080, например, куда в текстовую форму просто копипастится целиком класс и все на лету тоже меняется (если сможет конечно, потому что редефайн сигнатур не переживет и придется рестартовать приложение). Отсутствие адекватного трекинга изменений и версионирования плюс сюрпризы наподобие "почему вижу в коде одно, а на сервере ничего не работает" во время параллельной разработки гарантированы, но для фикс мастера уровень бог такие вещи помехой никогда не были)
Оформить центр управления в виде игры в самих Одноклассниках, как всякие «весёлые фермы» там сделаны. Желающий пропатчить production-сервер разработчик покупает ОК-и и заливает фикс.
Жизнь же разнообразна. Иногда нужно уметь и пластырь на артерию. И после того как научился необязательно артерии резать направо и налево, показывая всем свой навык.
Ну чтобы старт приложения не занимал больше десятка секунд
Со временем, реальная жизнь цинично ломает такие мечты своей суровой реальностью :) Даже вынос всяких расплодившихся кешей наружу и поддержка их в «горячем» состоянии, не всегда позволяет выйти на «десятки секунд»
Допустим, у нас в бегущем приложении есть экземпляр следующего класса:
public class AssignmentOrderMatter {
private Supplier<String> firstSupplier;
private Supplier<String> lastSupplier;
public AssignmentOrderMatter() {
this.lastSupplier = () -> "Farewell!";
this.firstSupplier = () -> "Hallo!";
}
public String getFirstValue() {
return firstSupplier.get();
}
public String getLastValue() {
return lastSupplier.get();
}
}
Мы замечаем опечатку в строке "Hello!"
, исправляем её, попутно меняем порядок присвоения полей в конструкторе т.к. ну некрасиво же первых инициализировать последними. Скорее всего даже не сразу вспомним потом про эту правку.
Применяем шаманство «Hot Code Replace» и, внезапно, последние стали первыми и getFirstValue()
начинает возвращать строку "Farewell!"
.
apangin, возможен ли в вашей системе такой сценарий или его поймают по дороге в продакшн?
У меня получилось воспроизвести такое поведение: https://github.com/Maccimo/BreakingLambdaBody
Патчинг Java кода на продакшене без анестезии