Построение устойчивого приложения с использованием Redis Offering.


Давайте попробуем построить приложение, используя Node Js и Redis для кэширования, а также задействуя подмодель Redis pub.

Давайте попробуем построить приложение с использованием Node Js и Redis, которое использует кэширование, а также задействует паттерн Redis pub-sub.

Итак, в этой статье мы рассмотрим, как можно использовать Redis в качестве системы кэширования, а также задействовать возможности парадигмы обмена сообщениями Publish/Subscribe, предоставляемой Redis. В настоящее время мы используем Node JS в качестве технологии бэкенда, но Redis совместим с большинством языков программирования.

Введение

Прежде всего, давайте попробуем понять общую картину всей системы, которую мы планируем построить. Для лучшего визуального понимания я нарисовал диаграмму архитектуры, которая поможет нам понять связь между различными сервисами. А также роль Redis во всей системе.

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

Здесь, в целях демонстрации, мы планируем построить два микросервиса, используя технологию Node Js. После этого мы создадим API входа в систему в одном из сервисов, который будет содержать данные для входа пользователя. Первый микросервис будет проверять наличие данных в Redis. Если вдруг он не сможет найти данные в Redis, он обратится к выбранной базе данных, которая будет конечным источником истины.

Как только он найдет данные, он обновит Redis, и в будущем Redis будет нашим источником истины.

После этого в игру вступит второй микросервис. Он попытается получить информацию о пользователе по ID, подключившись к тому же экземпляру Redis. Мы будем сравнивать с ним, напрямую получая данные из нашей базы данных. Хотя Redis означает Remote Dictionary Service и может использоваться как база данных. Но предложение базы данных Redis будет темой для обсуждения в другой статье. В противном случае это просто загромоздит текущую статью.

На втором этапе логики входа мы обновим информацию о пользователе в одном из микросервисов и позволим другому микросервису слушать ее вместо опроса. Мы будем использовать парадигму pub-sub, предоставляемую Redis. Это будет повесткой дня всего учебника.

Необходимые условия для занятий.

  1. Понимание node, express и javascript. Node должен быть установлен в вашей системе.

  2. Понимание MongoDB. MongoDB должна быть установлена в вашей системе.

  3. Редактор кода Microsofts VS. Хотя можно использовать любой редактор.

Table of Content
    1. Setting Up Two microservices using Node JS.
    2. Setting Up Mongo DB and connecting it with the microservices.
    3. Setting Up Redis and connecting them with microservices.
    4. Creating Login API in Microservice One.
    5. Setting Up Redis Pub-Sub and utilising it in our microservices.
    6. Redis Commander.
    7. Wrap Up and References.

Вход в полноэкранный режим Выход из полноэкранного режима

1. Настройка двух микросервисов с помощью Node JS.

Давайте приступим к работе с двумя микросервисами Node. Для настройки обоих сервисов нам необходимо выполнить следующие шаги.

  1. Инициализация проекта с помощью npm init

  2. Создайте файл «index.js» и добавьте основной код express.

  3. Установка пакета express с помощью команды npm install express.

Мы можем настроить проект node, выполнив следующую команду, которая инициализирует

проект node с помощью следующей команды.

> npm init
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы увидите следующую команду в терминале, заполните следующие данные, которые вы можете увидеть на изображении ниже. Такая информация, как имя, версия, описание, основные, скрипты, автор, лицензия и т.д. Назовем этот сервис backend-service-1.

После этого создадим файл index.js. Мы можем создать простой экспресс-сервер, добавив следующую команду. Эта служба запустит ваш экспресс-сервер на порту 3000, как мы указали в нашем коде.

**// index.js**

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
    res.send('Hello World Service 1! ')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
});
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь мы можем создать еще одну службу, аналогичную backend-service-1, и назвать ее backend-service-2. Давайте повторим аналогичную процедуру для сервиса backend-service-2, т.е.

  1. Запуск с помощью npm init

  2. Создание файла index.js

  3. Установка express с помощью команды. npm install express

  4. Добавляем основной код express и запускаем на порту 3001. Обновляя переменную port. const port = 3001;

После создания обоих сервисов структура вашего кода должна выглядеть примерно так, как показано на рисунке ниже (изображение 3). Для контекста ниже приведен расширенный вид структуры кода для бэкенд-службы 1. Аналогичную структуру вы можете ожидать для бэкенд-службы 2.

Вы можете запустить код для каждой службы, открыв целевое местоположение и выполнив следующую команду

> node index.js
Войти в полноэкранный режим Выйти из полноэкранного режима

После этого вы увидите в терминале следующую команду.

2. Настройка БД Mongo и подключение ее к микросервисам.

После шага настройки микросервисов нам необходимо подключить MongoDB к нашему приложению. Для подключения MongoDB к нашему приложению нам необходимо сначала установить и запустить MongoDB на нашей системе/сервере.

Для установки и запуска MongoDB вы можете следовать этому руководству. Установите MongoDB на OSX.

Обычно мы создаем кластер MongoDB на нескольких серверах, что помогает сделать его более устойчивым к падениям.

Но для целей учебника прекрасно подойдет и один экземпляр. Этот учебник предназначен для OSX, но если вы используете другую ОС, например Windows или Ubuntu. Вы можете найти соответствующий учебник и продолжить установку.

Вы можете попробовать выполнить следующую команду, чтобы проверить, установлен ли mongo, вы увидите что-то вроде следующего.

> mongo
Войти в полноэкранный режим Выйти из полноэкранного режима

После установки и других действий мы можем подключить mongo к нашему NodeJS микросервису, используя пакет MongoDB npm.

Установите пакет npm с помощью следующей команды.

> npm i mongodb
Войдите в полноэкранный режим Выйдите из полноэкранного режима

После установки пакета нам нужно добавить код для подключения к mongo. Создайте файл с именем mongo.js, в который мы будем добавлять код mongo.

Нам нужно добавить {type: «module»} в файл package.json, который можно найти в корневом расположении, это поможет вам использовать синтаксис es6.

Ниже приведен код для подключения БД mongo к вашему приложению. Здесь вы можете видеть, что мы подключили mongo DB, которая работает на localhost:27017.

Порт Mongo DB по умолчанию: 27017

Это глобальная функция, которая создаст соединение с БД. Используя это соединение, мы выполним последующий запрос к БД.

**//mongo.js**

import { MongoClient } from 'mongodb';

export async function connectToCluster() {
    const uri = 'mongodb://localhost:27017';
    let mongoClient;

    try {
        mongoClient = new MongoClient(uri);
        console.log('Connecting to MongoDB');
        await mongoClient.connect();
        console.log('Successfully connected to MongoDB!');

        return mongoClient;
    } catch (error) {
        console.error('Connection to MongoDB failed!', error);
        process.exit();
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Аналогичную реализацию мы можем сделать для backend-service-2, и настроить mongo DB.

3. Настройка Redis и соединение с микросервисами.

После настройки микросервиса node и соединения его с MongoDB. Мы готовы перейти к следующему шагу — установке Redis и подключению его к нашему микросервису.

Для Mac OS мы можем использовать brew для установки и запуска службы Redis в нашем проекте.

brew install redis
Вход в полноэкранный режим Выход из полноэкранного режима

Порт Redis по умолчанию: 6379

Теперь вы можете запустить сервер Redis с помощью любой из следующих команд. Разумеется, после установки.

redis-server
Войти в полноэкранный режим Выйти из полноэкранного режима

Или вы можете запустить его как службу brew, что поможет этой службе работать в фоновом режиме.

brew services start redis
Войти в полноэкранный режим Выход из полноэкранного режима

До сих пор мы закончили с настройкой Redis на нашей локальной системе. Мы можем проделать аналогичную процедуру для настройки Redis в облаке (AWS, G Cloud, Azure и т.д.).

Теперь давайте подключим Redis к нашим сервисам. Следующим шагом будет установка пакетов Redis npm на оба сервиса с помощью следующей команды.

npm i redis
Войти в полноэкранный режим Выйти из полноэкранного режима

После установки пакета Redis нам нужно создать экземпляр Redis, который мы будем использовать в дальнейшем.

//redis.js
import redis from 'redis';

export const client = redis.createClient();

client.on('connect', () => {
    console.log('Connected to Redis Successfully.')
});
Войти в полноэкранный режим Выйти из полноэкранного режима

Здесь мы экспортируем экземпляр Redis, который мы будем использовать для подключения и дальнейших запросов.

Теперь мы закончили с базовой настройкой и на следующем этапе подключимся к серверу Redis. После установки правильного соединения мы задействуем кэширование в нашем запросе get.

4. Создание API входа в систему в микросервисе One.

Теперь, когда мы закончили с подключением Redis и Mongo DB и соединили их с нашим приложением, настало время использовать кэширование Redis с помощью простого API входа.

Здесь, в этом API, мы создадим простой API входа, в котором мы будем передавать имя пользователя и пароль.

Не рекомендуется передавать пароли открытым текстом. Но для учебных целей мы сделаем это.

Добавим код для login API, после чего пройдемся по коду. Ниже представлен обновленный файл index.js. Он содержит API входа, который включает вызов нашей БД, если вдруг мы не сможем найти данные в Redis in-memory DB.

// index.js

import express from 'express';
import { connectToCluster } from './mongo.js';
import { client } from './redis.js';

const app = express()
const port = 3000
let mongoClient = null;

app.get('/', async (req, res) => {
    res.send('Hello World Service 1! ')
});


app.get('/login/:name/:password', async (req, res) => {
    try {

        const { name, password } = req.params;
        // check if pass exist in redis.
        const tempPassword = await client.get(name);
        if (tempPassword) {
            if (tempPassword === password) {
                res.send('Login Success from Redis.');
            }
        } 
        else {

            // Mongo DB Query
            mongoClient = await connectToCluster();
            const dbName = 'test';
            const db = mongoClient.db(dbName);
            const collection = db.collection('user');
            const findResult = await collection.findOne({ name, password })


            if (findResult) {
                await client.set(name, password);
                res.send('Login Success from DB.');
            } else {
                res.send('Login Failed.');
            }

        }

    } catch (err) {
        console.log(err)
        res.send('Login Failed.');
    }
    finally {
        await mongoClient.close();
    }
});

app.listen(port, async () => {
    client.connect();
    console.log(`Example app listening on port ${port}`)
});
Вход в полноэкранный режим Выход из полноэкранного режима

Пояснение к приведенному выше коду.

app.get('/login/:name/:password'
Вход в полноэкранный режим Выход из полноэкранного режима

Это конечная точка API, которую мы определили, она ожидает, что пользователь передаст имя и пароль в качестве параметра.

const tempPassword = await client.get(name);
if (tempPassword) {
        if (tempPassword === password) {
            res.send('Login Success from Redis.');
        }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы проверяем наличие записей в Redis с ключом в качестве имени.

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

Это еще раз подчеркивает тот факт, что для производства мы не храним пароли в виде обычного текста, это просто для того, чтобы мы поняли Redis.

Двигаясь дальше, мы проверяем, получаем ли мы данные в Redis, мы просто сравниваем пароль. Если мы не получили ни одного ключа, соответствующего переданному имени, мы переходим к вызову БД.

else {
            // Mongo DB Query
            mongoClient = await connectToCluster();
            const dbName = 'test';
            const db = mongoClient.db(dbName);
            const collection = db.collection('user');
            const findResult = await collection.findOne({ name, password })


            if (findResult) {
                await client.set(name, password);
                res.send('Login Success from DB.');
            } else {
                res.send('Login Failed.');
            }

        }
Вход в полноэкранный режим Выход из полноэкранного режима

Вот простое представление else, на случай, если мы не смогли найти имя в хранилище Redis. В нашем блоке else, как только мы смогли найти успешный вход, мы добавили имя пользователя и пароль в наш кэш Redis in-memory. Используя следующий код.

if (findResult) {
                await client.set(name, password);
                res.send('Login Success from DB.');
} else {
                res.send('Login Failed.');
 }
Вход в полноэкранный режим Выход из полноэкранного режима

Мы создадим API, как показано ниже, он будет ожидать имя пользователя. Как только мы получим имя пользователя, мы опубликуем его для других сервисов на канале с именем ‘user’, будет много запросов, которые будут возвращать одни и те же данные, и кэширование кажется хорошим вариантом для этого.

5. Настройка Redis Pub-Sub и его использование в наших микросервисах.

Для использования парадигмы pub-sub мы создаем API для обновления информации о пользователе в бэкенд-сервисе-1. А другой сервис, т.е. backend-service-2, будет слушать изменения, подписываясь на канал.

Мы создадим API, как показано ниже, он будет ожидать имя пользователя. Как только мы получим имя пользователя, мы опубликуем его другим сервисам на канале с именем ‘user’. По сути, это сообщение транслируется из нашей внутренней службы 1. Теперь любой, кто хочет прослушать изменения, может просто подписаться на канал и использовать это сообщение.

app.get('/updateName/:name', async (req, res) => {
    const { name } = req.params;

    client.publish('user', name);
    res.send(`Name: ${name} is been published`)
});
Вход в полноэкранный режим Выход из полноэкранного режима

Мы подписались на канал под именем ‘user’ в нашей внутренней службе 2. Как объяснялось ранее, как только кто-то нажмет кнопку update name API на внутренней службе 1, сообщение будет опубликовано на канале пользователя. Поскольку бэкенд-сервис 2 подписан на тот же канал, он получит переданное сообщение, т.е. обновленное имя.

Теперь служба 2 может свободно работать с данными.

app.listen(port, async () => {
    client.connect();
    await client.subscribe('user', (message) => {
        console.log(message); // 'message'
    });
    console.log(`Example app listening on port ${port}`)
});
Вход в полноэкранный режим Выход из полноэкранного режима

Аналогичным образом, используя парадигму pub-sub, мы можем решить наши различные сценарии использования.

6. Redis Commander.

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

Чтобы установить инструмент, вы можете использовать следующую команду.

> npm i -g redis-commander
// Post installation to run redis commander, use this command.
> redis-commander
Войти в полноэкранный режим Выйти из полноэкранного режима

Будет отображен пользовательский интерфейс, как показано ниже. Это делает поиск и анализ очень простым.

Ссылка: https://www.npmjs.com/package/redis-commander

7. Подведение итогов и ссылки.

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

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

Существуют различные дополнительные возможности, предоставляемые Redis, которые можно использовать, например, использование Redis в качестве полнофункциональной базы данных, персистентность данных и т.д. Но эта тема будет рассмотрена в следующих уроках.

А пока читайте больше о Redis на их официальном сайте (Redis).

Другие ссылки.

  • Попробуйте Redis Cloud бесплатно

  • Посмотрите это видео о преимуществах Redis Cloud перед другими провайдерами Redis

  • По возможности вставьте это видео

  • Redis Developer Hub — инструменты, руководства и учебники по Redis

  • RedisInsight Desktop GUIRedis

Этот пост подготовлен в сотрудничестве с Redis.


Об авторе

Апурв Томар — разработчик программного обеспечения и сотрудник Mindroast. Вы можете общаться с ним в Twitter, Linkedin, Telegram и Instagram. Подпишитесь на рассылку новостей, чтобы получать самые свежие материалы. Не стесняйтесь говорить «Привет» на любой платформе, просто указывая ссылку, где вы нашли мой профиль.

Оцените статью
devanswers.ru
Добавить комментарий