tl; dr: проверьте репозиторий кода на странице https://github.com/teamzerolabs/config-service-reference.
Ваш проект подключается к базам данных или стороннему Apis?
Скорее всего да. Пока ваша программа подключается к удаленным конечным точкам или выполняет вызовы к ним, ей необходимо откуда-то получать учетные данные безопасности.
Есть много разных способов загрузить эти учетные данные в программу:
Уровень 1: жестко закодируйте его в самом текстовом файле - обычно это происходит в пятницу или для людей, только начинающих. Эталонное репо должно помочь вам получить код, который вы можете использовать вместо этого.
Уровень 2: загрузка из объекта process.env в том месте, где происходит соединение. Это лучше, чем жесткое кодирование, но со временем переменная среды становится немного сложной. выслеживать. Потому что вы не можете перейти к одному файлу, чтобы найти все переменные среды, на которые есть ссылки.
Уровень 3: загрузите все конфигурации среды из одного файла - это предусмотрено в этой статье и в примере кода! Это дает вам преимущество знать, где искать конфигурации, и позволяет программе преждевременно выйти из строя, если были предоставлены неверные значения.
Уровень 4. Превратите сценарий конфигурации в службу. Таким образом мы получаем возможность делать другие интересные вещи: проверять типы загруженных значений и загружать дополнительные конфигурации из S3 или базы данных перед другой инициализацией. код работает.
Прежде чем ты начнешь
- Подготовьте среду выполнения Node.JS (Версия ›10)
- Скачайте Postman, если у вас его нет. Кроме того, вы можете использовать браузер или curl, чтобы попасть в Api.
- Проверьте https://github.com/teamzerolabs/config-service-reference в своем локальном пространстве.
- Установите и запустите MySQL: я включил файл docker-compose в папку
db-setup
, вы можете развернуть его, перейдя туда и запустивdocker-compose up -d
.
Краткий пример - минимальная книжная служба, которая возвращает книги, хранящиеся в базе данных MySQL
В первой папке node-starthere
у нас есть два файла:
- main.js - здесь мы настраиваем
express
сервер для обслуживания запроса наlocalhost:3000/books
- models / index.js - мы подключимся к MySQL с
mysql2
иsequelize
. - Запустите
yarn start
, чтобы начать.
Вы можете увидеть, как учетные данные базы данных в настоящее время хранятся в models/index.js
:
Оборотная сторона жесткого кодирования учетных данных базы данных
- Это небезопасно - любой, кто проверяет общедоступный репозиторий, теперь будет знать слишком много, особенно если ваш экземпляр базы данных является общедоступным, он теперь доступен.
- Сложно работать с разными средами - если вам нужно подключить этот код к тестовым или производственным развертываниям, вы не хотите вносить изменения в код только для развертывания.
Шаг №1 - Загрузите каждый из них из переменных среды
Вы можете узнать больше о переменных окружения здесь. Суть в том, что вы можете передавать значения в работающую программу следующим образом
DB_NAME=configexample DB_HOST=localhost DB_USER=root DB_PASSWORD=dIKnUfyfUPURi9irSplTOqGO4OtE0 DB_PORT=3306 yarn start .... // In the program const sequelize = new Sequelize( process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, { dialect: "mysql", host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT) } );
Этот подход хорош, если у вас небольшое количество конфигураций, но, как мы все знаем, любые проекты, пережившие первый месяц использования, начнут интегрироваться с большим количеством сервисов. (В моем недавнем 4-месячном проекте 40 переменных! Представьте, что вы набираете их в приведенном выше заявлении о начале пряжи, это слишком много).
Шаг № 2 - Загрузите переменные среды во время выполнения для локальной разработки перед использованием.
К счастью, есть пакет, который избавит нас от многократного ввода переменных. Он называется dotenv
. Вы используете dotenv так:
const dotenv = require("dotenv"); let env = process.env.NODE_ENV; if (env !== "production") { // Development will use .env. // Anything else will use .env.<NODE_ENV> if (env === "development") { env = ""; } const path = `src/config/.env${env ? `.${env}` : ""}`; // Well, it's better to use winston logger, perhaps we can cover in another tutorial console.log(`Loading config from environment file ${path}`); dotenv.config({ path }); }
Поместите свой код в src, создайте папку config и создайте внутри нее файл .env
:
DATABASE_URL=localhost DATABASE_PORT=3306 DATABASE_USERNAME=root DATABASE_PASSWORD=dIKnUfyfUPURi9irSplTOqGO4OtE0 DATABASE_NAME=configexample
И dotenv.config
загрузит переменные из текстовых файлов в process.env
, теперь вы можете пропустить ввод переменных в yarn start
!
Шаг № 3 - Удобные методы для анализа значений и досрочного выхода, если они отсутствуют
Единственное, что опаснее неправильно настроенной программы, - это неправильно настроенная программа, работающая месяцами.
Если мы забыли создать файл .env
или поместили в него неверные значения, в идеале мы хотим узнать об этом как можно раньше. Запуск кода с неполной или неправильной конфигурацией затрудняет устранение неполадок.
Если вы посмотрите на вторую папку node-with-config-service
, вы увидите, что следующие служебные методы добавлены и используются для анализа переменных:
/** * Retrieves environment variable and throws if missing without default * * @param name name of environment variable * @param defaultVal */ function parseEnv(name, defaultVal) { let env = process.env[name]; if (!env) { if (isNullOrUndefined(defaultVal)) { throw new Error(`Missing environment variable for ${name}`); } env = defaultVal; } return env; } /** * Retrieves environment variable as a number and throws if missing without default * * @param name name of environment variable * @param defaultVal */ function parseEnvNumber(name, defaultVal) { const number = parseInt(parseEnv(name, `${defaultVal}`)); if (isNaN(number)) { throw new Error(`Bad environment variable for ${name}: Not a Number`); } return number; } /** * Retrieves environment variable as a boolean and throws if missing without default * * @param name name of environment variable * @param defaultVal */ function parseEnvBoolean(name, defaultVal) { return parseEnv(name, `${defaultVal}`).toLowerCase() === "true"; }
И перепишем раздел подключения к базе данных так:
// in src/config/index.js const config = { app: { port: parseEnvNumber("APP_PORT", 3000) }, mysql: { host: parseEnv("DATABASE_URL"), port: parseEnvNumber("DATABASE_PORT", 3306), username: parseEnv("DATABASE_USERNAME"), password: parseEnv("DATABASE_PASSWORD"), database: parseEnv("DATABASE_NAME") } }; // in src/models/index.js const config = require("../config"); const sequelize = new Sequelize( config.mysql.database, config.mysql.username, config.mysql.password, { dialect: "mysql", host: config.mysql.host, port: config.mysql.port } );
Программа теперь выйдет раньше с ошибками, если переменные среды отсутствуют, и вы можете полагаться на статический объект конфигурации, существующий из любого места в программе!
У этого подхода есть еще два расширения: вы можете применять те же шаблоны в TypeScript и пойти дальше, настроив фактическую вспомогательную службу в NestJS. Оба включены в репозиторий git. Мы рассмотрим это в будущей статье о TypeScript + NestJs!
Используйте шаблон конфигурации для вашего демонстрационного проекта / прототипа / портфолио
Ваш коллега / DevOps / партнер по обзору кода / в будущем вы через 3 месяца поблагодарит вас за это, :)
Есть вопросы о том, где разместить конфигурации? Спрашивайте нас в любое время по адресу [email protected]