gRPC клиент. Попробуй на вкус клиент/сервер на gRPC

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

   В прошлой статье мы разобрали, как писать сервер на gRPC. И протестировали его с помощью BloomRPC. Теперь, давайте разберем как пишется клиент. И попробуем отправлять запросы с клиента на сервер. Это будет наш первый шаг к созданию микросервисов на грпц. 

   В моем случае я использую многомодульный проект, но можно создать отдельный проект. Структура проекта будет примерно следующей: 

Структура проекта
Структура проекта

Мы реализуем основные методы, которые были описаны в .proto. Обратите внимание, что serverStream разобьется на 2 метода, о чем я расскажу дальше.

Эти методы мы реализуем в ходе статьи
Эти методы мы реализуем в ходе статьи

Как и в прошлой статье нам необходимо добавить плагин для генерации .proto файлов. Если возникли сложности, можно посмотреть код примера в репозитории.

Для того, чтобы отправлять вызовы на удаленный сервер, нам необходимо создать клиента. gRPC предоставляет несколько возможностей создания клиента - это BlockingStub и Stub. В чем отличие этих “заглушек”? BlockingStub - создает новую блокирующую заглушку, которая поддерживает вызовы унарного и потокового вывода (unary and streaming output calls, офф. док.), Stub - cоздает новую асинхронную заглушку, которая поддерживает все типы вызовов. Мы рассмотрим оба варианта заглушек. Для создании заглушки нам необходим Channel. Channel - если коротко, то это виртуальное соединение с концептуальной конечной точкой для выполнения RPC. Для создания Channel нам потребуется хост и порт. 

// Access a service running on the local machine on port 7777
String target = "localhost:7777";

// Create a communication channel to the server, known as a Channel. Channels are thread-safe
// and reusable. It is common to create channels at the beginning of your application and reuse
// them until the application shuts down.
ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
  // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
  // needing certificates.
  .usePlaintext()
  .build();

Затем мы можем создать newBlockingStub и newStub (создаем через Channel и ManagedChannel для примера)

// 'channel' here is a Channel, not a ManagedChannel, 
// so it is not this code's responsibility to
// shut it down.
// Passing Channels to code makes code easier to test 
// and makes it easier to reuse Channels.
blockingStub = ProfileServiceGrpc.newBlockingStub(channel);
asyncStub = ProfileServiceGrpc.newStub(ManagedChannelBuilder.forAddress(HOST, PORT).usePlaintext().build());

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

Реализация getCurrentProfile
Реализация getCurrentProfile

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

Main
Main

  Теперь если вызвать getCurrentProfile, то мы получим ответ профиля с именем “test” (сервер из прошлой статьи). 

Отлично, с базовым методом разобрались. Давайте теперь рассмотрим clientStream. Отличия от предыдущего метода минимальные. Нам лишь нужно передавать сообщения на сервер не единожды, как было в прошлом примере, а постоянно. Если обратиться к логам сервера, то можно заметить, что он получает сообщения от клиента и логирует их. 

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

// Блокирующая и асинхронная заглушки
private final ProfileServiceGrpc.ProfileServiceBlockingStub blockingStub;
private final ProfileServiceGrpc.ProfileServiceStub asyncStub;
// Создание заглушек в конструкторе
public GrpcProfileClientImpl() {
    // Create a communication channel to the server, known as a Channel. Channels are thread-safe
    // and reusable. It is common to create channels at the beginning of your application and reuse
    // them until the application shuts down.
    ManagedChannel channel = ManagedChannelBuilder.forTarget(TARGET)
            // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
            // needing certificates.
            .usePlaintext()
            .build();
    blockingStub = ProfileServiceGrpc.newBlockingStub(channel);
    asyncStub = ProfileServiceGrpc.newStub(channel);
}

Для принятия ответов, используя BlockingStub нам потребуется Iterator, куда сервер будет складывать ответы. И потом, пробежавшись по нему, мы увидим то, что нам прислал сервер. 

А вот для не блокирующего принятия сообщений нам потребуется передать StreamObserver, в который сервер будет передавать ответы.

Не блокирующее получение ответов от сервера
Не блокирующее получение ответов от сервера

Так как у нас получение происходит асинхронно, я добавляю CountDownLatch с await, для того что бы текущий поток подождал ответов от сервера. 

И последний вариант клиент серверного взаимодействия - biDirectionalStream. Нам снова потребуется реализовать StreamObserver в который клиент будет передавать сообщения и получать ответы от сервера.

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

Подведем итоги.

Мы написали клиент, для рассмотренного в прошлой статье сервера на gRPC. Рассмотрели и реализовали основные варианты клиент серверного взаимодействия с использованием gRPC. А вы используете gRPC для клиент серверного общения? Почему вы выбрали gRPC? 

Источник: https://habr.com/ru/post/566504/


Интересные статьи

Интересные статьи

SWAP (своп) — это механизм виртуальной памяти, при котором часть данных из оперативной памяти (ОЗУ) перемещается на хранение на HDD (жёсткий диск), SSD (твёрдотельный накоп...
С точки зрения пользователя процесс онлайн-покупки продуктов у «ВкусВилла» выглядит просто — открыл приложение (самого «ВкусВилла» или партнеров доставки и агрегаторов), выбрал нужные тов...
1С Битрикс: Управление сайтом (БУС) - CMS №1 в России по версии портала “Рейтинг Рунета” за 2018 год. На рынке c 2003 года. За это время БУС не стоял на месте, обрастал новой функциональностью...
От скорости сайта зависит многое: количество отказов, брошенных корзин. Согласно исследованию Google, большинство посетителей не ждёт загрузки больше 3 секунд и уходит к конкурентам. Бывает, что сайт ...
Здравствуйте. Я уже давно не пишу на php, но то и дело натыкаюсь на интернет-магазины на системе управления сайтами Битрикс. И я вспоминаю о своих исследованиях. Битрикс не любят примерно так,...