[Open source, Java] Конфигурация Java систем — как убрать боль
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Читать конфиги через Java-интерфейсПроблемаЕсли вы хотя бы однажды разрабатывали большую систему на Java и сопровождали её, то, наверняка, сталкивались с неудобствами настройки тех или иных процессов в системе. А именно: размеры различных буферов; параметры почтового ящика; хост, порт, логин, пароль вызова внешних сервисов; всякие таймауты и многое другое.Каждый раз менять всё это в коде, пересобирать и перенакатывать на реал — не комильфо.Естественно все эти параметры нужно выносить в файлы конфигов и считывать их оттуда — все так делают.В Java из коробки для этого есть некий Properties. Но пользоваться им крайне неудобно. Во-первых, UTF-8 там не работают, во-вторых — если вы поменяли какой-нибудь параметр в конфиге, то чтобы новое значение попало в систему — требуется перезапуск приложения. А если вы не хотите его перезапускать, или это невозможно в 11 утра — час пиковой нагрузки. И отложить на потом не вариант — нужно срочно. Что делать? Нужно чтобы конфиги перечитывались на «горячую», т. е. без перезапуска системы.А ещё очень важно: нужно как-то так придумать чтобы имена параметров конфигов в коде программы соответствовали тем, которые в файле. Т. е. чтобы трудно было ошибиться. Обычно используют для этого константы — помогает, но хотелось бы что-то удобнее, проще и гибче.И вот ещё что: представьте у вас крупная система в которой уже накопилось около тридцати конфигурационных файлов, и в каждом по десятку параметров. И вам нужно накатить новую инстанцию. Как вы будете настраивать эти конфиги? Создавать каждый вручную? В каждом прописывать имена параметров и их значения, вспоминая что каждый из них значит? А если забыли? А есть документация? А эта документация актуальная? А если вы ошибётесь в одной буковке параметра — позволит ли вам система при старте сразу объяснить что не так? Или она свалится в час ночи, когда вы крепко спите? Вам придётся просыпаться, включать как-то мозг и разбираться во всей этой истории…Хотелось бы избежать всей этой нервотрёпки.Надо как-то сделать так, чтобы система создавала все эти конфиги сама, и описывала их всех — что каждый конфиг делает в общем, и каждый параметр в частности. Ну и разработчик не должен сильно напрягаться чтобы поддерживать всю эту автоматизацию в актуальном состоянии.Всё это должно быстро и легко активироваться — подключил какую-то маленькую библиотечку, прописал какой-то магический код размером не больше пяти-десяти строк (автосгенерированные вашей IDE строки не считаем) — и вуаля — всё работает.Можно конечно использовать конфигурационный сервер, и даже кто-то это делает (вроде), но это как-то напряжно — хочется что-нибудь проще, но эффективно.Мы в greetgo! поискали в разных интернетах, но так ничего подходящего не нашли — пришлось пилить самим.РешениеОсновной идеей было использовать Java-интерфейс для чтения данных конфига, и, одновременно, формирования структуры конфига. Вы один раз в интерфейсе написали имя метода — и это имя автоматически становится именем параметра в конфиге. Вам не нужно его писать второй раз в файле конфига, опасаясь допустить ошибку в одной букве — файл пусть создаётся автоматически со всеми параметрами — вам нужно будет только подкорректировать значения параметров.Например вы хотите вынести в конфиг updateTimeout и batchSize — потому что трудно их подобрать изначально. Для этого создаёте Java-интерфейс:
public interface MyMigrationConfig {
long updateTimeoutMs();
int batchSize();
}
Хотя вот так будет лучше:
@Description("Миграция состояний в ядро системы");
public interface MyMigrationConfig {
@Description("Максимальное время миграции одной порции в миллисекундах."
+ " Если оно будет превышено, то миграция будет немедленно"
+ " прервана с ошибкой")
@DefaultLongValue(30000)
long updateTimeoutMs();
@Description("Размер порции мигрируемых данных в записях")
@DefaultIntValue(150)
int batchSize();
}
Теперь этот интерфейс надо зарегистрировать в какой-то классной штуке, которая умеет автоматически создавать магические реализации подобных интерфейсов, и после этого пользоваться, например, таким способом:
@Autowire
private MyMigrationConfig config;
public void migrate() {
// ...
System.out.println(" updateTimeoutMs = " + config.updateTimeoutMs());
System.out.println(" batchSize = " + config.bachSize());
// ...
}
Такой простой подход позволяет легко настраивать и сопровождать любые настройки системы, как во время разработки так и во время сопровождения.Нами была разработана библиотека, которая позволяет реализовать такой подход. Она получилась маленькой и у неё нет никаких других зависимостей. И она уже долго и интенсивно нами используется, другими словами она production ready. Лицензия — MIT.Называется она greetgo conf — она есть и в maven и в github: https://github.com/greetgo/greetgo.confПодключив её к проекту, необходимо создать фабрику конфигов примерно так:
public class MyConfigFactory extends FileConfigFactory {
@Override
public Path getBaseDir() {
return Paths.get("/path/to/directory/where/config/files/are/located");
}
@Override
protected String getConfigFileExt() {
return ".conf";
}
}
Дальше создаём инстанцию этой фабрики и пользуемся магическим методом createConfig:
MyConfigFactory confFactory = new MyConfigFactory();
MyMigrationConfig config = confFactory.createConfig(MyMigrationConfig.class);
Теперь у нас есть инстанция интерфейса конфига и мы можем считывать данные конфига. Они будут считываться из файла с именем MyMigrationConfig.conf. Этот файл создастся автоматически, если его ещё нет, с примерно таким содержимым:
# Created at 2021-01-29 11:03:21
# Миграция состояний в ядро системы
# Размер порции мигрируемых данных
batchSize=150
# Максимальное время миграции одной порции в миллисекундах. Если оно будет
# превышено, то миграция будет немедленно прервана с ошибкой
updateTimeoutMs=30000
Теперь вы можете менять эти параметры и система автоматически их будет перечитывать. Естественно про оптимизацию мы подумали — всё это внимательно кэшируется, и, если вы будете очень часто считывать параметры (тысячи раз в секунду), то это не вызовет большую нагрузку на файловую систему.ВозможностиСо временем у нас появились распределённые проекты с большим количеством нод и с использованием kubernetes. Хранить настройки в файлах в таких проектах оказалось не удобно, и мы сделали расширение библиотеки, которое позволяет хранить настройки в Zookeeper, для этого нужно просто заменить FileConfigFactory на AbstractZookeeperConfigFactory, ну и прописать параметры доступа к Zookeeper.Также есть реализация JdbcConfigFactory — которая позволяет хранить настройки в реляционной БД.Архитектура библиотеки позволяет достаточно просто разрабатывать свои фабрики конфигов, например чтобы хранить конфиги в яндекс-диске.Также есть возможность использовать аннотацию @FirstReadEnv — которая считывает помеченный ей параметр не из конфига, а из переменной окружения — в kubernetes некоторые параметры удобнее задавать через переменные окружения.На этом все. Спасибо за внимание.
===========
Источник:
habr.com
===========
Похожие новости:
- [Ненормальное программирование, JavaScript, HTML, Браузеры, DIY или Сделай сам] Как я создаю приложения для браузера прямо в браузере
- [Java, API] Как трассировка запросов сломала API
- [Тестирование IT-систем, Программирование, Java, Тестирование веб-сервисов] AspectJ в автоматическом тестировании — несколько практических примеров
- [Open source, Виртуализация, Читальный зал, Openshift] 8 Kubernetes-инсайтов, шпаргалка по Curl и онлайн-курс «Разработка облачных приложений с микросервисными архитектурами»
- [Java] Разбираемся, как работает Spring Data Repository, и создаем свою библиотеку по аналогии
- [Java, Разработка мобильных приложений, Разработка под Android] Android Bluetooth Low Energy (BLE) – готовим правильно, часть #4 (bonding) (перевод)
- [Разработка веб-сайтов, Open source, Тестирование IT-систем, Тестирование веб-сервисов] Callisto. Зачем мы придумали замену Selenium Grid
- [PHP, PostgreSQL, SQL] Установка Redmine за 15 минут (RVM + RoR + Unicorn + Nginx)
- [Информационная безопасность, Разработка веб-сайтов, JavaScript] Опасная уязвимость в популярной библиотеке Sequelize
- [Open source, Java, API, Apache, Natural Language Processing] Поиск по синонимам — контролируем процесс или доверяемся нейросетям
Теги для поиска: #_open_source, #_java, #_java, #_configuration, #_interface, #_open_source, #_java
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:11
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Читать конфиги через Java-интерфейсПроблемаЕсли вы хотя бы однажды разрабатывали большую систему на Java и сопровождали её, то, наверняка, сталкивались с неудобствами настройки тех или иных процессов в системе. А именно: размеры различных буферов; параметры почтового ящика; хост, порт, логин, пароль вызова внешних сервисов; всякие таймауты и многое другое.Каждый раз менять всё это в коде, пересобирать и перенакатывать на реал — не комильфо.Естественно все эти параметры нужно выносить в файлы конфигов и считывать их оттуда — все так делают.В Java из коробки для этого есть некий Properties. Но пользоваться им крайне неудобно. Во-первых, UTF-8 там не работают, во-вторых — если вы поменяли какой-нибудь параметр в конфиге, то чтобы новое значение попало в систему — требуется перезапуск приложения. А если вы не хотите его перезапускать, или это невозможно в 11 утра — час пиковой нагрузки. И отложить на потом не вариант — нужно срочно. Что делать? Нужно чтобы конфиги перечитывались на «горячую», т. е. без перезапуска системы.А ещё очень важно: нужно как-то так придумать чтобы имена параметров конфигов в коде программы соответствовали тем, которые в файле. Т. е. чтобы трудно было ошибиться. Обычно используют для этого константы — помогает, но хотелось бы что-то удобнее, проще и гибче.И вот ещё что: представьте у вас крупная система в которой уже накопилось около тридцати конфигурационных файлов, и в каждом по десятку параметров. И вам нужно накатить новую инстанцию. Как вы будете настраивать эти конфиги? Создавать каждый вручную? В каждом прописывать имена параметров и их значения, вспоминая что каждый из них значит? А если забыли? А есть документация? А эта документация актуальная? А если вы ошибётесь в одной буковке параметра — позволит ли вам система при старте сразу объяснить что не так? Или она свалится в час ночи, когда вы крепко спите? Вам придётся просыпаться, включать как-то мозг и разбираться во всей этой истории…Хотелось бы избежать всей этой нервотрёпки.Надо как-то сделать так, чтобы система создавала все эти конфиги сама, и описывала их всех — что каждый конфиг делает в общем, и каждый параметр в частности. Ну и разработчик не должен сильно напрягаться чтобы поддерживать всю эту автоматизацию в актуальном состоянии.Всё это должно быстро и легко активироваться — подключил какую-то маленькую библиотечку, прописал какой-то магический код размером не больше пяти-десяти строк (автосгенерированные вашей IDE строки не считаем) — и вуаля — всё работает.Можно конечно использовать конфигурационный сервер, и даже кто-то это делает (вроде), но это как-то напряжно — хочется что-нибудь проще, но эффективно.Мы в greetgo! поискали в разных интернетах, но так ничего подходящего не нашли — пришлось пилить самим.РешениеОсновной идеей было использовать Java-интерфейс для чтения данных конфига, и, одновременно, формирования структуры конфига. Вы один раз в интерфейсе написали имя метода — и это имя автоматически становится именем параметра в конфиге. Вам не нужно его писать второй раз в файле конфига, опасаясь допустить ошибку в одной букве — файл пусть создаётся автоматически со всеми параметрами — вам нужно будет только подкорректировать значения параметров.Например вы хотите вынести в конфиг updateTimeout и batchSize — потому что трудно их подобрать изначально. Для этого создаёте Java-интерфейс: public interface MyMigrationConfig {
long updateTimeoutMs(); int batchSize(); } @Description("Миграция состояний в ядро системы");
public interface MyMigrationConfig { @Description("Максимальное время миграции одной порции в миллисекундах." + " Если оно будет превышено, то миграция будет немедленно" + " прервана с ошибкой") @DefaultLongValue(30000) long updateTimeoutMs(); @Description("Размер порции мигрируемых данных в записях") @DefaultIntValue(150) int batchSize(); } @Autowire
private MyMigrationConfig config; public void migrate() { // ... System.out.println(" updateTimeoutMs = " + config.updateTimeoutMs()); System.out.println(" batchSize = " + config.bachSize()); // ... } public class MyConfigFactory extends FileConfigFactory {
@Override public Path getBaseDir() { return Paths.get("/path/to/directory/where/config/files/are/located"); } @Override protected String getConfigFileExt() { return ".conf"; } } MyConfigFactory confFactory = new MyConfigFactory();
MyMigrationConfig config = confFactory.createConfig(MyMigrationConfig.class); # Created at 2021-01-29 11:03:21
# Миграция состояний в ядро системы # Размер порции мигрируемых данных batchSize=150 # Максимальное время миграции одной порции в миллисекундах. Если оно будет # превышено, то миграция будет немедленно прервана с ошибкой updateTimeoutMs=30000 =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:11
Часовой пояс: UTC + 5