Русский
Русский
English
Статистика
Реклама

Конфигурация Java систем как убрать боль

Читать конфиги через Java-интерфейсЧитать конфиги через 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();}

Теперь этот интерфейс надо зарегистрировать в какой-то классной штуке, которая умеет автоматически создавать магические реализации подобных интерфейсов, и после этого пользоваться, например, таким способом:

@Autowireprivate 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 { @Overridepublic Path getBaseDir() {return Paths.get("/path/to/directory/where/config/files/are/located");}  @Overrideprotected 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
К списку статей
Опубликовано: 29.01.2021 16:08:57
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Open source

Java

Configuration

Interface

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru