- PVSM.RU - https://www.pvsm.ru -
В последнее время микросервисные архитектуры пользуются определённой популярностью. От того, как взаимодействуют микросервисы, может зависеть производительность и масштабируемость решений, основанных на них. Это взаимодействие может быть синхронным или асинхронным. В материале, перевод которого мы представляем вашему вниманию сегодня, рассматриваются синхронные методы взаимодействия микросервисов. А именно, речь пойдёт об исследовании двух технологий: HTTP/1.1 и gRPC. Первая технология представлена стандартными HTTP-вызовами. Вторая основана на использовании высокопроизводительного RPC-фреймворка от Google. Автор материала предлагает взглянуть на код, необходимый для реализации взаимодействия микросервисов с использованием HTTP/1.1 и gRPC, провести замеры производительности, и выбрать технологию, которая позволяет организовать обмен данными между микросервисами наилучшим образом.
Начнём с малого и создадим систему из двух микросервисов, которые могут взаимодействовать друг с другом. Обратите внимание на то, что здесь не используется кластерный режим. Вот схема нашего приложения.
Архитектура приложения, работающего в обычном режиме
Приложение состоит из следующих компонентов:
HTTP/1.1 — это стандартная технология организации взаимодействия микросервисов, которая применяется при использовании любых HTTP-библиотек вроде axios [3] или superagent [4].
Вот код сервиса B, реализующий API нашей системы:
server.route({
method: 'GET',
path: '/',
handler: async (request, h) => {
const response = await new Promise((resolve) => {
setTimeout(() => {
resolve({
id: 1,
name: 'Abhinav Dhasmana',
enjoys_coding: true,
});
}, 10);
});
return h.response(response);
},
});
Вот код сервиса А, который обращается к сервису B, используя HTTP/1.1:
server.route({
method: 'GET',
path: '/',
handler: async (request, h) => {
try {
const response = await Axios({
url: 'http://localhost:8001/',
method: 'GET',
});
return h.response(response.data);
} catch (err) {
throw Boom.clientTimeout(err);
}
},
});
Запустив эти микросервисы, мы можем воспользоваться возможностями jMeter для выполнения тестов производительности. Выясним, как система ведёт себя при работе с ней 50 пользователей, каждый из которых выполняет по 2000 запросов. Как можно видеть на следующем рисунке, медиана результатов измерения равна 37 мс.
Результаты исследования системы, работающей в обычном режиме и использующей HTTP/1.1, с помощью jMeter
gRPC использует по умолчанию технологию Protocol Buffers [5]. Поэтому, применяя gRPC, в дополнение к коду двух сервисов, нам понадобится написать и код proto-файла, который описывает интерфейс взаимодействия модулей системы.
syntax = "proto3";
service SampleDataService {
rpc GetSampleData (Empty) returns (SampleData) {}
}
message SampleData {
int32 id = 1;
string name = 2;
bool enjoys_coding = 3;
}
message Empty {}
Теперь, так как теперь мы планируем использовать gRPC, надо переписать код сервиса B:
const grpc = require('grpc');
const proto = grpc.load('serviceB.proto');
const server = new grpc.Server();
const GetSampleData = (call, callback) => {
setTimeout(() => {
callback(null, {
id: 1,
name: 'Abhinav Dhasmana',
enjoys_coding: true,
});
}, 10);
};
server.addService(proto.SampleDataService.service, {
GetSampleData,
});
const port = process.env.PORT;
console.log('port', port);
server.bind(`0.0.0.0:${port}`, grpc.ServerCredentials.createInsecure());
server.start();
console.log('grpc server is running');
Обратите внимание на некоторые особенности этого кода:
const server = new grpc.Server();
мы создаём grpc-сервер. server.addService(proto...
мы добавляем сервис к серверу.server.bind(`0.0.0.0:${port}...
служит для привязки порта и учётных данных.Теперь перепишем сервис A с использованием gRPC:
const protoPath = `${__dirname}/../serviceB/serviceB.proto`;
const proto = grpc.load(protoPath);
const client = new proto.SampleDataService('localhost:8001', grpc.credentials.createInsecure());
const getDataViagRPC = () => new Promise((resolve, reject) => {
client.GetSampleData({}, (err, response) => {
if (!response.err) {
resolve(response);
} else {
reject(err);
}
});
});
server.route({
method: 'GET',
path: '/',
handler: async (request, h) => {
const allResults = await getDataViagRPC();
return h.response(allResults);
},
});
Среди особенностей этого кода можно отметить следующие:
const client = new proto.SampleDataService...
мы создаём grpc-клиент.client.GetSampleData({}...
.Теперь протестируем то, что у нас получилось, с помощью jMeter.
Результаты исследования системы, работающей в обычном режиме и использующей gRPC, с помощью jMeter
Проведя несложные расчёты, можно выяснить, что решение, использующее gRPC, оказывается на 27% быстрее решения, использующего HTTP/1.1.
Вот схема приложения, аналогичного тому, которое мы только что исследовали, но работающего в кластерном режиме.
Архитектура приложения, работающего в кластерном режиме
Если сравнить эту архитектуру с рассмотренной ранее, можно отметить следующие изменения:
Подобная архитектура характерна для реальных проектов.
Исследуем HTTP/1.1 и gRPC в новой среде.
При использовании в кластерной среде микросервисов, применяющих HTTP/1.1, их код менять не придётся. Нужно лишь настроить nginx для организации балансировки трафика сервиса B. В нашем случае, для того, чтобы это сделать, нужно привести файл /etc/nginx/sites-available/default
к такому виду:
upstream httpservers {
server ip_address:8001;
server ip_address:8002;
server ip_address:8003;
}
server {
listen 80;
location / {
proxy_pass http://httpservers;
}
}
Запустим теперь то, что у нас получилось, и посмотрим на результаты тестирования системы с использованием jMeter.
Результаты исследования системы, работающей в кластерном режиме и использующей HTTP/1.1, с помощью jMeter
Медиана в данном случае равна 41 мс.
Поддержка gRPC появилась в nginx 1.13.10 [7]. Поэтому нам понадобится самая свежая версия nginx, для установки которой обычная команда sudo apt-get install nginx
не подходит.
Также тут мы не используем Node.js в кластерном [8] режиме, так как в таком режиме gRPC не поддерживается [9].
Для того чтобы установить самую свежую версию nginx, воспользуйтесь следующей последовательностью команд:
sudo apt-get install -y software-properties-common
sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install nginx
Кроме того, нам понадобятся SSL-сертификаты. Самоподписанный сертификат можно создать с помощью openSSL [10]:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost'
-keyout localhost-privatekey.pem -out localhost-certificate.pem
Для использования gRPC нужно отредактировать файл /etc/nginx/sites-available/default
:
upstream httpservers {
server ip_address:8001;
server ip_address:8002;
server ip_address:8003;
}
server {
listen 80;
location / {
proxy_pass http://httpservers;
}
}
Теперь всё готово для того, чтобы испытать кластерное gRPC-решение с помощью jMeter.
Результаты исследования системы, работающей в кластерном режиме и использующей gRPC, с помощью jMeter
В данном случае медиана равна 28 мс, а это, в сравнении с аналогичным показателем, полученным при исследовании кластерного HTTP/1.1-решения, на 31% быстрее.
Результаты исследования показывают, что приложение, основанное на микросервисах, и использующее gRPC, оказывается примерно на 30% производительнее аналогичного приложения, в котором для обмена данными между микросервисами используется HTTP/1.1. Исходный код проектов, рассмотренных в этом материале, можно найти здесь [11].
Уважаемые читатели! Если вы занимаетесь разработкой микросервисов, просим рассказать о том, как вы организуете обмен данными между ними.
Автор: ru_vds
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/290896
Ссылки в тексте:
[1] Image: https://habr.com/company/ruvds/blog/421579/
[2] jMeter: https://jmeter.apache.org/
[3] axios: https://github.com/axios/axios
[4] superagent: https://github.com/visionmedia/superagent
[5] Protocol Buffers: https://developers.google.com/protocol-buffers/docs/overview
[6] NGINX: https://www.nginx.com/
[7] nginx 1.13.10: https://www.nginx.com/blog/nginx-1-13-10-grpc/
[8] кластерном: https://nodejs.org/api/cluster.html
[9] не поддерживается: https://github.com/grpc/grpc/issues/6976
[10] openSSL: https://www.openssl.org/
[11] здесь: https://github.com/abhinavdhasmana/interserviceCommunication
[12] Источник: https://habr.com/post/421579/?utm_campaign=421579
Нажмите здесь для печати.