Как обрабатывать конфигурацию приложений для всей среды по всей организации?

Проблема

В вашей организации есть много отдельных приложений, некоторые из которых взаимодействуют друг с другом (для создания "систем" ). Вам необходимо развернуть эти приложения в отдельных средах для облегчения ступенчатого тестирования (например, DEV, QA, UAT, PROD). В каждом окружении (например, в каждой среде есть отдельная база данных) необходимо настроить несколько приложений по-разному. Вы хотите, чтобы эта переконфигурация обрабатывалась каким-то автоматическим механизмом, чтобы менеджерам выпуска не приходилось вручную настраивать каждое приложение каждый раз, когда оно развертывается в другую среду.

Требуемые функции

Я хотел бы создать решение для всей организации со следующими свойствами (в идеале):

  • Поддерживает развертывание "одним нажатием" (необходимо указать только среду, и никакая ручная перенастройка во время/после развертывания не потребуется).
  • Должна быть единственная "система записи", в которой указано общее свойство, зависящее от среды (например, строка подключения к базе данных, которая используется многими приложениями).
  • Поддерживает повторную настройку развернутых приложений (в случае необходимости изменения свойства среды), в идеале без необходимости повторного развертывания приложения.
  • Позволяет запускать приложение на одном компьютере, но в разных средах (одновременно запускать экземпляр PROD и экземпляр DEV).

Возможные решения

Я вижу два основных направления, в которых может идти решение:

  • Сделать все приложения "осведомленными об окружающей среде". Вы должны передать имя среды (DEV, QA и т.д.) В командной строке приложения, а затем приложение будет "умным", чтобы определить значения конфигурации для конкретной среды во время выполнения. Приложение может извлекать значения из плоских файлов, развернутых вместе с приложением, или из центральной службы конфигурации.
  • Приложения не являются "умными", поскольку они находятся в №1, и просто получают конфигурацию по имени свойства из файлов конфигурации, развернутых в приложении. Значения этих свойств вводятся в конфигурационные файлы во время развертывания программой установки / script. Эта установка script принимает имя среды и извлекает все соответствующие значения конфигурации из центральной службы конфигурации.

Вопрос

Как было бы/вы получили решение по конфигурации, которое решает эти проблемы и поддерживает эти желаемые функции? Имею ли я цель с двумя возможными решениями? Есть ли у вас предпочтение между этими решениями? Также, пожалуйста, не стесняйтесь сказать мне, что я думаю о проблеме, все неправильно. Любая обратная связь будет с благодарностью.

Ответ 1

Мы все сталкиваемся с такими вещами, особенно в крупных организациях. Я думаю, что наиболее важно сначала управлять своими собственными ожиданиями, а также спросить, нужно ли действительно рассказать каждой системе и подсистеме в данном поле "перейти в режим DEV" или "перейти в режим PROD", Мои личные рекомендации заключаются в следующем:

  • Сделайте отдельные ящики ответственными за другой этап - т.е. "это поле DEV" и "это поле PROD".

  • Соберите как можно большую часть конфигурации, которая отличается от коробки к ящику в одном месте, даже если для этого требуются программные ссылки или скрипты, которые собирают информацию для распечатки.

    а. Таким образом, вы можете легко "сбросить эту конфигурацию ящика" в двух местах и ​​посмотреть, что отличается, например, после нового развертывания.

    В. Вы также можете внести изменения в конфигурацию отдельно от изменений программного обеспечения, по крайней мере до некоторой степени, что является хорошим способом устранения ошибок, которые происходят во время выпуска.

  • Затем все зависит от конфигурации, что-то/где-то, что не запечено или не закодировано - просто убедитесь, что вы собрали и задокументировали его в этом месте. Практически неважно, что такое механизм, что хорошо, потому что некоторые системы просто не хотят принуждать к использованию каких-либо механизмов или других.

Извините, если это слишком общий ответ - вопрос был очень общий. Раньше я работал в нескольких крупных программных организациях, и это казалось лучшим подходом. Использование автономного сервера как "одной единицы развертывания" является наиболее реалистичным сценарием (хотя иногда и дорого), поскольку приложения влияют друг на друга, и как бы вы ни были осторожны, вы дестабилизируете всю систему, когда вы перемещаете любое снаряжение или зубчатое колесо.

Альтернатива очень быстро становится очень сложной. Вам нужно начать переписывать приложения, которые вы контролируете, чтобы они приняли переключатель "DEV", и вы в конечном итоге добавляете слои kludge к тем, у которых вы не контролируете. Обычно те, на которые у вас нет контроля, по крайней мере, основывают свои свойства на чем-то определенном на общесистемном уровне, если только они не "называют материнство для инструкций".

Легче перенаправить людей в удаленное местоположение и заставить их "использовать DEV" и "использовать PROD", чем "заставить эту машину работать как DEV", а "заставить эту машину работать как PROD". И если вы смешиваете вещи, например, когда задача DEV выполняется вместе в том же поле, что и задача PROD, то это не реалистичный сценарий: я гарантирую, что в конечном итоге вы будете предоставлять незаконный доступ только DEV к кому-либо в PROD, и у вас будет задача DEV уничтожить базу данных PROD.

Надеюсь, это поможет. Дайте мне знать, если вы хотите обсудить более конкретные аспекты.

Ответ 2

Я лично предпочитаю решение 2 (приложение должно знать по своей конфигурации, в какой среде он работает). С решением 1 (передать имя среды в качестве параметра запуска) опасность использования неправильного спецификатора среды слишком высока. Доступ к базе данных TEST из кода PROD и наоборот может вызвать хаос, если две установленные базовые коды кода не имеют одинаковой версии, как это часто бывает.

В моем текущем проекте используется решение 1, но мне это не нравится. В предыдущем проекте, в котором я работал, использовался вариант решения 2: Процесс сборки сгенерировал один файл установки для каждой среды, убедившись, что они содержат одну и ту же базу кода, но соответствующие параметры конфигурации. Это работало как прелесть, но я знаю, что это противоречит парадигме, что "точные файлы сборки должны быть развернуты повсюду".

Ответ 3

Я думаю, что задал связанный, ответ на вопрос, прежде чем я прочитал следующее: Как организовать код, чтобы мы могли перемещать и обновлять его без необходимости редактировать расположение файла конфигурации?. Поэтому на этой основе я предоставляю ответ здесь. Мне не нравится идея "умного" приложения (решение 1 здесь) для такой простой задачи, как поиск настроек среды. Это кажется сложной основой для чего-то, что должно быть простым. Идея установки script (решение 2 здесь) является мощной, но полезно разрешить пользователю изменять содержимое конфигурационного файла, но позволит ли это изменить местоположение этого конфигурационного файла? Что это за "центральная конфигурация", где она расположена? Мой ответ заключается в том, что я бы пошел с вариантом 2, если цель состоит в том, чтобы установить содержимое конфигурационного файла, но я чувствую, что проблема с расположением этого файла конфигурации остается без ответа.

Ответ 4

Если вы используете JSON для хранения/передачи конфигурации (или можете использовать JSON в процессе предварительного развертывания для вывода в какой-либо другой формат), вы можете аннотировать имена ключей/свойств для значений среды/контекста с произвольной или внешней средой специфические суффиксы, а затем динамически предпочитают/различают их при построении/развертывании/run/render -time, оставляя только не аннотированные свойства.

Мы использовали это, чтобы избежать дублирования всех файлов конфигурации (с хорошо известными проблемами) И уменьшить повторение. Этот метод также идеально подходит для интернационализации (i18n) - даже в том же файле, если это необходимо.

Пример, фрагмент предварительно обработанной конфигурации JSON:

var config = {
    'ver': '1.0',
    'help': {
        'BLURB': 'This pre-production environment is not supported. Contact Development Team with questions.',
        'PHONE': '808-867-5309',
        'EMAIL': '[email protected]'
    },
    '[email protected]': {
        'BLURB': 'Please contact Customer Service Center',
        '[email protected]': 'S\'il vous plaît communiquer avec notre Centre de service à la clientèle',
        '[email protected]': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
        'PHONE': '1-800-CUS-TOMR',
        'EMAIL': '[email protected]'
    },
}

... и пост-обработанный (в данном случае во время рендеринга) с учетом динамического, известного в браузере location.hostname = ' www.productionwebsite.com' и navigator.language of де '):

prefer(config,['www.productionwebsite.com','de']); // prefer(obj,string|Array<string>)

JSON.stringify(config); // {
    'ver': '1.0',
    'help': {
        'BLURB': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
        'PHONE': '1-800-CUS-TOMR',
        'EMAIL': '[email protected]'
    }
}

Если не-аннотированное ( "базовое" ) свойство не имеет конкурирующего аннотированного свойства, оно остается одним (предположительно глобальным по средам), в противном случае его значение заменяется аннотированным значением, если суффикс соответствует одному из входов в функция предпочтения/дискриминации. Аннотированные свойства, которые не совпадают, полностью отбрасываются.

Вы можете смешивать и сопоставлять это поведение с аннотацией конфигурации для достижения различий в глобальном, по умолчанию, конкретном, которые (считая вас разумными) читаемыми с нулевым/минимальным дублированием.

Единая рекурсивная функция prefer() (как мы ее называем, не имея потребности или желания сделать из нее весь проект/каркас), которую мы разработали до сих пор (см. jsFiddle с встроенными документами) идет немного дальше этого простого примера и (более подробно объясняется здесь) обрабатывает глубоко вложенные объекты конфигурации, а также предпочтительный порядок и (если вам нужно остановиться) сочетание суффиксов.

Функция полагается на способность JS ссылаться на свойства объекта как строки, динамически и допускать @и и ограничители в именах свойств, которые недопустимы в синтаксисе точечных нотации, но, следовательно, (помощь), препятствуют разработчикам нарушать эту технику, случайно ссылаясь для предварительно обработанных/аннотированных атрибутов в коде (если они, не условно, не предпочитают использовать точечные обозначения.)

Нам еще предстоит сделать этот перерыв для нас, и мы не были обучены каким-либо фундаментальным недостаткам этой техники, помимо безответственного/непреднамеренного использования или инвестиций/привязанности к существующим основам/методам, которые существуют. Мы также не профилировали его для производительности (мы только запускаем его один раз для сборки/сессии и т.д.), Поэтому в вашем собственном использовании YMMV.

В большинстве конфигураций, переданных на стороне клиента, конечно, не хотелось бы содержать чувствительные предварительные значения, поэтому можно (нужно!) использовать одну и ту же функцию для создания версии, предназначенной только для производства (без аннотаций) в предварительном развертывании, в то же время наслаждаясь файлом конфигурации SINGLE вверх по вашему процессу.

Кроме того, если вы делаете это для i18n, вам может не потребоваться, чтобы весь пакет переходил по проводу, поэтому он мог обрабатывать серверную (кэшированную или живую и т.д.) или предварительно обрабатывать ее при построении/развертывании разделяя их на отдельные файлы, но STILL пользуется одним источником правды как можно раньше в вашем рабочем процессе.

Мы не изучали реализацию одной и той же функции в Java (или С#, PERL и т.д.), предположив, что это возможно (возможно, с некоторым экзотическим отражением?), но среда сборки, которая включает в себя NodeJS, может легко сэкономить.