gRPC - 客戶端呼叫



gRPC 客戶端支援兩種型別的客戶端呼叫,即客戶端如何呼叫伺服器。以下是兩種方式:

  • 阻塞式客戶端呼叫

  • 非同步客戶端呼叫

在本章中,我們將逐一檢視它們。

阻塞式客戶端呼叫

gRPC 支援阻塞式客戶端呼叫。這意味著,一旦客戶端向服務發出呼叫,客戶端將不會繼續執行其餘程式碼,直到從伺服器收到響應。請注意,對於單向呼叫和伺服器流式呼叫,阻塞式客戶端呼叫是可能的。

請注意,對於單向呼叫和伺服器流式呼叫,阻塞式客戶端呼叫是可能的。

這是一個單向阻塞式客戶端呼叫的示例。

示例

package com.tp.bookstore;

import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.tp.bookstore.BookStoreOuterClass.Book;
import com.tp.bookstore.BookStoreOuterClass.BookSearch;
import com.tp.greeting.GreeterGrpc;
import com.tp.greeting.Greeting.ServerOutput;
import com.tp.greeting.Greeting.ClientInput;

public class BookStoreClientUnaryBlocking {
   private static final Logger logger = Logger.getLogger(BookStoreClientUnaryBlocking.class.getName());
   private final BookStoreGrpc.BookStoreBlockingStubblockingStub;
   public BookStoreClientUnaryBlocking(Channel channel) {
      blockingStub = BookStoreGrpc.newBlockingStub(channel);
   }
   public void getBook(String bookName) {
      logger.info("Querying for book with title: " + bookName);
      BookSearch request = BookSearch.newBuilder().setName(bookName).build();

      Book response;
      try {
         response = blockingStub.first(request);
      } catch (StatusRuntimeException e) {
         logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
         return;
      }
      logger.info("Got following book from server: " + response);
   }
   public static void main(String[] args) throws Exception {
      String bookName = args[0];
      String serverAddress = "localhost:50051";
      ManagedChannel channel = ManagedChannelBuilder.forTarget(serverAddress)
         .usePlaintext()
         .build();
      try {
         BookStoreClientUnaryBlocking client = new
         BookStoreClientUnaryBlocking(channel);
         client.getBook(bookName);
      } finally {
         channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
      }
   }
}

在上面的示例中,我們有:

public BookStoreClientUnaryBlocking(Channel channel) {
   blockingStub = BookStoreGrpc.newBlockingStub(channel);
}

這意味著我們將使用阻塞式 RPC 呼叫。

然後,我們有:

BookSearch request = BookSearch.newBuilder().setName(bookName).build();

Book response;
response = blockingStub.first(request);

在這裡,我們使用 **blockingStub** 呼叫 RPC **method first()** 來獲取圖書詳情。

類似地,對於伺服器流式,我們可以使用阻塞式存根:

logger.info("Querying for book with author: " + author);
BookSearch request =
BookSearch.newBuilder().setAuthor(author).build();

Iterator<Book> response;
try {
   response = blockingStub.searchByAuthor(request);
   while(response.hasNext()) {
   logger.info("Found book: " + response.next());
}

我們在這裡呼叫 RPC 方法 **searchByAuthor** 方法,並迭代響應,直到伺服器流結束。

非阻塞式客戶端呼叫

gRPC 支援非阻塞式客戶端呼叫。這意味著當客戶端向服務發出呼叫時,它不需要等待伺服器響應。為了處理伺服器響應,客戶端可以簡單地傳入觀察者,該觀察者決定在收到響應時該做什麼。請注意,對於單向呼叫和流式呼叫,非阻塞式客戶端呼叫都是可能的。但是,我們將特別關注伺服器流式呼叫的情況,以便將其與阻塞式呼叫進行比較。

請注意,對於單向呼叫和流式呼叫,非阻塞式客戶端呼叫都是可能的。但是,我們將特別關注伺服器流式呼叫的情況,以便將其與阻塞式呼叫進行比較。

這是一個伺服器流式非阻塞式客戶端呼叫的示例

示例

package com.tp.bookstore;

import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;

import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.tp.bookstore.BookStoreOuterClass.Book;
import com.tp.bookstore.BookStoreOuterClass.BookSearch;
import com.tp.greeting.GreeterGrpc;
import com.tp.greeting.Greeting.ServerOutput;
import com.tp.greeting.Greeting.ClientInput;

public class BookStoreClientServerStreamingNonBlocking {
   private static final Logger logger = Logger.getLogger(BookStoreClientServerStreamingNonBlocking.class.getName());
   private final BookStoreGrpc.BookStoreStub nonBlockingStub;
   public BookStoreClientServerStreamingNonBlocking(Channelchannel) {
      nonBlockingStub = BookStoreGrpc.newStub(channel);
   }
   public StreamObserver<Book> getServerResponseObserver(){
      StreamObserver<Book> observer = new
      StreamObserver<Book>(){
         @Override
         public void onNext(Book book) {
            logger.info("Server returned following book: " +book);
         }
         @Override
         public void onError(Throwable t) {
            logger.info("Error while reading response fromServer: " + t);
         }
         @Override
         public void onCompleted() {
            logger.info("Server returned following book: " + book);
         }
      };
      return observer;
   }
   public void getBook(String author) {
      logger.info("Querying for book with author: " + author);
      BookSearch request = BookSearch.newBuilder().setAuthor(author).build();
      try {
         nonBlockingStub.searchByAuthor(request,getServerResponseObserver());
      } catch (StatusRuntimeException e) {
         logger.log(Level.WARNING, "RPC failed: {0}",e.getStatus());
         return;
      }
   }
   public static void main(String[] args) throws Exception {
      String authorName = args[0];
      String serverAddress = "localhost:50051";
      ManagedChannel channel =ManagedChannelBuilder.forTarget(serverAddress)
         .usePlaintext()
         .build();
      try {
         BookStoreClientServerStreamingNonBlocking client = new
         BookStoreClientServerStreamingNonBlocking(channel);
         client.getBook(authorName);
      } finally {
         channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
      }
   }
}

正如我們在上面的示例中看到的:

public BookStoreClientUnaryNonBlocking(Channel channel) {
   nonBlockingStub = BookStoreGrpc.newStub(channel);
}

它定義了存根是非阻塞式的。類似地,以下程式碼用於處理我們從伺服器接收到的響應。一旦伺服器傳送響應,我們就記錄輸出。

public StreamObserver<Book> getServerResponseObserver(){
   StreamObserver<Book> observer = new
   StreamObserver<Book>(){
   ....
   ....
   return observer;
}

以下 gRPC 呼叫是非阻塞式呼叫。

logger.info("Querying for book with author: " + author);
BookSearch request = BookSearch.newBuilder().setAuthor(author).build();
try {
   nonBlockingStub.searchByAuthor(request, getServerResponseObserver());
}

這就是我們確保客戶端不需要等到伺服器完成 **searchByAuthor** 執行的方式。這將由流觀察者物件在伺服器返回 Book 物件時直接處理。

廣告