Настоящие лиды фиксят баги на продакшене изменением параметров.
(c) один из настоящих лидов.
Все мы прекрасно знаем, что очень многое в любом приложении (да чего уж там - куске кода) определяется параметрами. Крутанул в одну сторону - работает, крутанул в другую - не работает.
Знаем и пользуемся этим. За что иногда хочется оторвать руки.
В большинстве случаев параметры получаются один раз на старте приложенияи и могут быть переопределены только после его рестарта. Однако есть случаи когда параметры необходимо переопределять в runtime и для этого тоже есть инструменты.
Лирическое отступление: Если последняя фраза (про переопределение параметров в runtime) вас смутила, повергла в шок или просто удивила - идите и смотрите как это делается у Netflix на примере Archaius. Дальше вам читать может быть без пользы.
Но не все управляется параметрами.
Бывает так, что подкрутить нужно не только параметры, но и логику.
С логикой все несколько хуже, я бы даже сказал стремновато.
Перекрутить логику можно на заранее заготовленную (другая реализация интерфейса и переключение параметра), но трудно переткнуть на новую - то есть ту которой в рантайме приложения нет.
Я говорю «трудно» потому, что ничего невозможного нет, и для этой задачи в Java например есть OSGI. Вот с этой строчки вы бы наверное уже могли бы на меня накинутся, но потерпите - я и сам не фанат OSGI и прекрасно отдаю себе отчет о том, чего стоит использование таких вот решений и как придется переколбасить архитектуру приложения.
Не хочется OSGI но хочется крутить логику ? Ну ок, тогда читаем дальше.
А читать-то собственно и немного. Идите на гитхаб, я уже все слепил.
Что там ? Там стандартная Jetty c одним сервлетом который принимает один параметр (строковый) и возвращает вам его в некоем обработанном виде. Обработки ошибок и всего что там по идее должно быть там нет.
При запуске приложения нужно указать в аргументы путь к файлику с кодом в котором собственно находится логика (примеры файликов в папке resources).
Дальше собственно самое интересное.
Берем листинг номер 1, сохраняем в файлик, скармливаем приложению на старте - и, вуаля, у нас с вами есть какая-то логика, которая просто будет нам возвращать строку которую передали в приложение.
Раз в 10 секунд приложение будет дергать файлик и вычитывать из него значение.
Если нам нужно поменять логику приложения, и, например, сделать реверс строки, то мы пишем код который нам это сделает, и сохраняем его в файлик.
При следующей прогрузке файлика (10 секунд) приложение подцепит этот код и запустит его.
Как это работает ?
Работает это на дефолтных возможностях Groovy по парсингу кода.Ключевой является вот эта строчка кода
Тут Groovy грузит исходный код из файла и компилирует его.
Внимание! ClassLoader от Groovy кэширует сорсы, так что не стоит удивляться если что-то не прогрузилось, а стоит использовать параметр метода parse которые говорит кэшировать или нет.
Приведение объекта содержащего логику к интерфейсу изначально было сделано сугубо из-за простоты такого подхода, но после, в процессе размышлений я пришел к выводу что так и надо : хочешь менять логику - потрудись хотя бы выделить под нее интерфейс и реализовать его!
Ограничения решения.
Первое и самое главное ограничение - это то что ваша «сменяемая» логика не может тащить за собой зависимости на код которого нет в рантайме. То есть если вы в альтернативной версии логики хотите попользоваться другой библиотекой,эмммм скажем для нарезки изображений, то вы должны протащить ее (при деплое приложения) заблаговременно. Если вас не устраивает подобного рода ограничение - то вам нужно идти на … OSGI.Второе ограничение решения - слабая устойчивость к конфигурационным ошибкам.
Если кто-то скормит в такое место некорректную логику (некомпилируемый код), то логика вашего приложения в этой точке не будет работать. Совсем. Что из этого следует для вас - придумайте сами. Можно предпринять какие-то методы защиты - кэшировать предыдущее значение, откатываться к нему в случае чего, автоматически откатываться на реализацию логики по умолчанию и прочее, но фундаментально это проблемы не решает - это решение плохо защищено. Отсюда вывод и рекомендация - использовать подобного рода решения только для проведения экспериментов и/или дебага.
Третье - Groovy сильно медленнее чистой Java. Если вы хотите вставить это в нагруженный/частоиспользуемый кусок кода, то искренне надеюсь, что вы это делаете по нужде (дебаг) или из профессионального любопытства (контроллируемый эксперимент в полевых условиях). Вывод - окончание эксперимента/отладки должно привести к убиранию такой разводки в коде.
Преимущества решения.
Преимущество первое - реальный боевой код кругом, реальное окружение, реальные данные (если не боитесь их повредить/потерять).
Второе - писать такую логику можно прямо в окружении проекта, потом просто копировать код и подсовывать в приложение.
Преимущество третьв (хипстерское) - синтаксический сахар грувей. Но лично я к нему прохладен.
К исследованию возможности такого решения меня побудили вот эти статьи на хабре (раз и два).
Матчасть.
P.S. и не упарывайтесь, пожалуйста.
P.P.S да, я знаю что есть Java 8 , а в ней Nashorn и все такое. Просто я не люблю JS.
Комментариев нет:
Отправить комментарий