В сегодняшнем посту мы узнаем, что такое GRPC, когда вы должны добраться до такого инструмента, а некоторые из плюсов и минусов их использования. После прохождения введения GRPC мы погрузимся прямо в пример при применении, где мы построим API Elixir Backend Powered на GRPC.
Давайте прыгнем прямо!
Что такое GRPC. И как это работает?
GRPC — это рамка, используемая для включения стиля связи вызова удаленной процедуры (RPC). RPC — это стиль системы связи, когда клиент может напрямую вызывать открытые методы на сервере. С точки зрения клиента, это не отличается от того, чтобы позвонить в локальную функцию или метод до тех пор, пока вы предоставляете применимые параметры и обрабатывать тип возврата соответствующим образом. GRPC облегчает эту связь, предоставляя 2 вещи для вас:
- Клиентская библиотека, которая может быть использована для вызова допустимых процедур
- Стандарт последовательной серии данных через буферы протокола
Давайте сломаем эти два предмета вниз, чтобы мы могли оценить внутреннюю работу GRPC. При создании сервера GRPC вам придется определить, какие процедуры пополняются от клиента, какие входы они принимают, и какие выходы они возвращаются. Этот спецификация интерфейса — это то, что позволяет клиентским библиотекам (в целом называемых stubs GRPC), которые будут автоматически сгенерированы для различных языков, а runtimes, поскольку договор на вызов удаленной процедуры явно определен. Этот клиент GRPC Затем библиотека может взаимодействовать с сервером с использованием буферов протокола. Буферные буферы протокола обеспечивают механизм для сериализации и десериализации полезных нагрузок (как запрос и ответ), чтобы вы могли работать на данных с типами, находящимися на вашем языке. Диаграмма, доступная в документации GRPC, может помочь визуализировать Это взаимодействие :
Одна вещь, которую мы еще не обсуждали, так это, как данные передаются между клиентом и сервером. Для этого GRPC наклоняется к протоколу HTTP/2. Используя HTTP/2 в качестве базового протокола, GRPC может поддерживать такие функции, как двунаправленные потоковые данные и несколько других функций, которые недоступны в HTTP/1.1.
Когда вы бы использовали GRPC За отдых/график?
Очевидный вопрос, который может прийти к уму, это: «Как GRPC сравнивается с REST/GRAPHQL, а когда я использую один над другим?».
В целом, если вы планируете использовать GRPC для приложения Frontend, есть пара предупреждений, которые вам нужно иметь в виду. Чтобы сериализовать и десериализировать полезные нагрузки протокола из приложения JavaScript, вам придется использовать GRPC-Web Отказ Кроме того, вам также нужно будет запустить прокси-сервер на бэкэнде (поддерживаемый по умолчанию GRPC по умолчанию GRPC — посланник), поскольку браузеры не могут говорить непосредственно на серверы GRPC. В зависимости от ваших ресурсов и временных ограничений, это может быть шоу-пробкой; В каком случае отдых и график будут просто отлично.
Если приложение Frontend Applications не является требованием, и вместо этого вам требуется взаимосвязь, является межмесифицированная связь из системы обслуживания, то барьер к записи для GRPC значительно снижается. На момент написания, GRPC в настоящее время имеет клиентские библиотеки и инструменты для большинства основных языков, включая Elixir, Python, C ++, Go, Ruby, чтобы назвать несколько. Я бы утвердовал, что барьер для входа для потребления восстановленного API по-прежнему намного ниже, чем потребляющий службу GRPC, учитывая, что все, что вам нужно для первого, это клиент HTTP, который запекается на большинстве языков и запусков в наши дни.
С другой стороны, если вы готовы принять инвестиции, вы получите дополнительные преимущества в том, чтобы ваши ответы и запросы проверены по спецификации буфера протокола, который используется для генерации кода. Это, в свою очередь, предоставляет вам некоторые гарантии относительно того, что вы можете ожидать на стороне клиента и на стороне сервера. Эта гарантия и самоанализация также является то, что вы получаете с GraphQL, когда определяете свои схемы серверов. Добавлена дополнительное преимущество GraphQL Over GRPC заключается в том, что вы можете динамически запрашивать встроенные свойства изнутри вашей схемы в зависимости от запроса, который вы делаете на ваш сервер Backeng.
Как и большинство вещей в области программного обеспечения, технология, которую вы выбираете, во многом зависят от вашего приложения. Ниже приведены мой персональный TL; DR правил большого пальца в отношении различных технологий:
GRPC:
- Использовать: При связи между микросимами в моем сервисном кластере или если производительность является требованием
- Не используйте: Когда мне нужно передавать данные из браузера на бэкэнду
Graphql:
- Использование: Когда мне нужно составлять данные из нескольких микросервисов для целей оптимизации разработки Frontend, или если мои требования к данным Frontend являются динамическими
- Не используйте: При связи между микросервисами в моем сервисном кластере или если мой API должен использоваться самым низким распространенным знаменателем потребителей
ОСТАЛЬНОЕ:
- Использовать: Когда мне нужно быстро поставить что-то вместе или если мне нужно обслуживать самый низкий общий знаменатель потребителей
- Не используйте: если мне нужен какой-либо тип проверки или Если я хочу уменьшить размеры полезной нагрузки через проволоку
Экспериментируя с GRPC в эликсире
Со всей теорией выходит из пути, пришло время добиться наших рук и экспериментировать с подключением сервера GRPC. Чтобы держать нас сосредоточены на опыте GRPC, мы выберемся на том, чтобы иметь бэкэнду, работающую агентом по сравнению с фактической базой данных, но все понятия должны быть легко передаваться на приложение, поддерживаемое postgres, например. Наше Приложение GRPC будет простая служба управления пользователем, где мы можем создавать и получать пользователям. После создания нашего Elixir Service мы будем взаимодействовать с ним через GRPCURL, что эффективно завитка, но для GRPC. Если в любой момент вы застряли или требуете исходного кода, не стесняйтесь Проверьте это на Github Отказ Со всеми, что говорится, давайте погрузимся прямо в!
Перед созданием нашего проекта Elixir есть пара вещей, которые мы требуем на нашей машине, чтобы правильно разработать и проверить наше приложение. Сначала нам нужно установить проток Так что .Proto Файлы могут быть скомпилированы соответствующим образом. Если вы на машине OSX, вы можете запустить Brew Установить Protobuf , в противном случае, Смотрите инструкции специфично для вашей платформы. Теперь, с Проток Доступно на вашем компьютере, вы также захотите установить grpcurl. Так что вы можете взаимодействовать с приложением. Еще раз, если вы находитесь на машине OSX, вы можете запустить Brew install grpcurl. , в противном случае, Проверьте наличие инструкций, относящихся к вашей платформе Отказ
Наконец, вы захотите запустить Mix Escript.install Hex Protobuf и убедитесь, что Protoc-Gen-Elixir Сценарий доступен на вашем пути (если вы используете ASDF в качестве версии Runtime Version, это требует запуска ASDF Reshim Elixir ). Со всей этой котельной сделано, вы можете запустить Смешайте новый образец_app --sup Чтобы запустить новое приложение.
Оказавшись в вашем каталоге приложения пример, вы захотите обновить свой Mix.exs Файл, чтобы включить наши зависимости связанных с GRPC. Для этого приложения мы будем использовать https://github.com/elixir-grpc/grpc и https://github.com/tony612/protobuf-elixir Отказ Чтобы принести эти две зависимости в ваш проект, убедитесь, что ваш Депс/0 Функция выглядит так:
defp deps do
[
{:grpc, "~> 0.5.0-beta"},
{:cowlib, "~> 2.8.0", hex: :grpc_cowlib, override: true}
]
end
С этим на месте беги MIX DEPS.S.GET От терминала, чтобы потянуть все необходимые проектные зависимости. Далее вы захотите создать файл конфигурации в config/config.exs Со следующим контентом:
use Mix.Config # Configures Elixir's Logger config :logger, :console, format: "$time $metadata[$level] $message\n" config :grpc, start_server: true
Затем мы захотите создать необходимые определения буферов протокола для нашего приложения. Спецификация буфера протокола Довольно большой, и мы будем использовать только небольшое подмножество его, чтобы сохранить все возможное. Создать файл образец_app.proto В корне вашего проекта со следующим контентом:
syntax = "proto3";
package sample_app;
service User {
rpc Create (CreateRequest) returns (UserReply) {}
rpc Get (GetRequest) returns (UserReply) {}
}
message UserReply {
int32 id = 1;
string first_name = 2;
string last_name = 3;
int32 age = 4;
}
message CreateRequest {
string first_name = 1;
string last_name = 2;
int32 age = 3;
}
message GetRequest {
int32 id = 1;
}
Как видите, наше определение буфера протокола довольно прост и легко читать. Мы определяем услугу, которая выставляет два метода RPC- Создать и Получить Отказ Мы также определяем типы, которые каждый из этих вызовов RPC принимает в качестве ввода и возврата в результате. С образец_app.proto Файл на месте, мы захочем открыть терминал и выполнить следующее:
$ protoc --elixir_out=plugins=grpc:./lib sample_app.proto
Вы заметите, что эта команда производит файл lib/thumb_app.pb.ex с несколькими модулями внутри нее. Если вы посмотрите внимательно, вы увидите, что был сгенерирован код, является эликсиром представление о образец_app.proto Файл, который мы написали. Он содержит все типы, которые мы определили вместе с определениями метода RPC. С нашим автогенерируемым Код на месте, давайте приступим к работе на фактических обработчиках RPC.
Как уже упоминалось ранее, мы будем использовать агент для сохранения состояния через вызовы GRPC вместо базы данных, ради простоты. Наш агент будет иметь возможность просматривать пользователей через свой идентификатор, и также сможет создавать новые пользователи. Создать файл lib/user_db.ex. Со следующим кодом, который обеспечивает эту функциональность:
defmodule UserDB do
use Agent
def start_link(_) do
Agent.start_link(
fn ->
{%{}, 1}
end,
name: __MODULE__
)
end
def add_user(user) do
Agent.get_and_update(__MODULE__, fn {users_map, next_id} ->
updated_users_map = Map.put(users_map, next_id, user)
{Map.put(user, :id, next_id), {updated_users_map, next_id + 1}}
end)
end
def get_user(id) do
Agent.get(__MODULE__, fn {users_map, _next_id} ->
Map.get(users_map, id)
end)
end
end
С помощью этого на месте мы можем создавать наши обработчики RPC для создания и получения пользователей. Создать файл lib/thumb_app.ex. Со следующим контентом:
defmodule SampleApp.Endpoint do
use GRPC.Endpoint
intercept GRPC.Logger.Server
run SampleApp.User.Server
end
defmodule SampleApp.User.Server do
use GRPC.Server, service: SampleApp.User.Service
def create(request, _stream) do
new_user =
UserDB.add_user(%{
first_name: request.first_name,
last_name: request.last_name,
age: request.age
})
SampleApp.UserReply.new(new_user)
end
def get(request, _stream) do
user = UserDB.get_user(request.id)
if user == nil do
raise GRPC.RPCError, status: :not_found
else
SampleApp.UserReply.new(user)
end
end
end
Наш файл определяет два модуля. SampleApp. Конечная точка Модуль определяет сервер GRPC и предоставляет модуль обработчика для запросов на обслуживание. SampleApp. Пользователь. Сервер Модуль содержит фактические реализации двух RPC вызовов, которые мы определены. Вы заметите, что для каждого из обработчиков мы предоставляем правильный тип возврата (как определено в нашем файле буфера протокола). Когда мы столкнулись с ошибкой (в этом случае, глядя вверх пользователя, который не существует), мы поднимаем Grpc.rpcError с соответствующим кодом состояния.
Все, что осталось сейчас, — это запустить наш агент и наш сервер GRPC, и мы приятно идти. Откройте lib/thumb_app/application.ex и убедитесь, что ваш процесс дети Список выглядит так:
children = [
UserDB,
{GRPC.Server.Supervisor, {SampleApp.Endpoint, 50051}}
]
С этим на месте вы должны быть в состоянии запустить Mix GrPc.server От терминала, чтобы начать свой сервер GRPC. В другом сеансе терминала (и из каталога проекта) вы должны быть в состоянии использовать grpcurl Команды для взаимодействия с вашим приложением:
$ grpcurl -plaintext -proto sample_app.proto -d '{"first_name": "Bob", "last_name": "Smith", "age": 40}' localhost:50051 sample_app.User.Create
{
"id": 1,
"firstName": "Bob",
"lastName": "Smith",
"age": 40
}
$ grpcurl -plaintext -proto sample_app.proto -d '{"id": 1}' localhost:50051 sample_app.User.Get
{
"firstName": "Bob",
"lastName": "Smith",
"age": 40
}
$ grpcurl -plaintext -proto sample_app.proto -d '{"id": 2}' localhost:50051 sample_app.User.Get
ERROR:
Code: NotFound
Message: Some requested entity (e.g., file or directory) was not found
Вывод
Спасибо за прилипание ко мне до конца. Надеюсь, вы узнали вещь или две о GRPC И как пойти, используя его в приложении Elixir. Если вы хотите узнать больше о GRPC или любом из инструментов, которые я уже упоминал, я предлагаю пройти через следующие ресурсы:
Автор гостей Алекс Куутмос Является старшим программным обеспеченным инженером, который пишет бэкэнды в эликсире, в Vuejs и развертывает его приложения, используя Kubernetes. Когда он не программирует или вести блог, он мучится на его 1976 Datsun 280Z.
Слияние Если вы хотите прочитать алхимии Эликсира, как только они сойдут с пресса, Подпишитесь на нашу рассылку Alichiry Alchemy и никогда не пропустите ни одного поста !
Оригинал: «https://dev.to/appsignal/how-to-use-grpc-in-elixir-21j3»