什么是 gRPC? 它比 REST API 好吗?

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

在国外的一些公司,包括网飞、谷歌、 Square 和其他公司已经采用了gRPC,国内的字节跳动、美团、阿里巴巴在许多业务线上也采取了gRPC的通信方式。这篇文章是入门级别的文章,带大家初探gRPC。

什么是REST API

REST 是一种设计基于 web 的 api 的架构风格,它成为 REST api。当 Client 和 Server 使用 restapi 进行通信时,它们将拥有一个预定义的端点和有效负载契约。REST API 使用所有的 HTTP 方法,比如 GET、 PATCH、 PUT、 POST、 DELETE。

什么是RPC?

RPC (remote procedure call 是一种请求-响应协议。RPC API 只使用 HTTP GET 和 POST 方法。客户端-服务器通信是通过服务器端接口和客户端存根实现的。

什么是gRPC

gRPC is a modern, open source remote procedure call (RPC) framework that can run anywhere. It enables client and server applications to communicate transparently, and makes it easier to build connected systems. - From gRPC docs.

引用出自gRPC文档,大致的意思是gRPC是一个现代的开源远程过程调用(RPC)框架,可以在任何地方运行。它使客户机和服务器应用程序能够透明地通信,并使构建连接的系统更加容易。

这个框架是由 Google 开发的。与其他 RPC 系统一样,gRPC 还定义了一个接口,定义了客户机可以访问的所有方法。默认情况下,gRPC 使用协议缓冲作为接口定义语言和数据交换格式。它还支持其他数据交换格式,比如 JSON。

gRPC 中的 IDL 在扩展名为的文件中定义。保罗。我们可以在这些文件中定义一个版本,并以可选的不同语言维护相同 api 的不同版本。

由 gRPC 支持的不同类型的 RPC,包括:

  • Unary-从客户机发送单个请求,从服务器发送回单个响应。
  • Server Streaming-从客户机发送一个请求,然后从服务器发送回一系列消息。
  • Client Streaming -从客户端向服务器发送一系列消息,服务器用一条消息作出回应。
  • Bidirectional streaming -客户端和服务器相互发送消息流的地方。

它是否比REST更好?

像 REST API 这样的通信在使用一元操作的 gRPC 中是可能的,但是当涉及到流时,gRPC 允许全双工流,并使用静态路径进行通信,这消除了路径解析和查询参数增加的延迟。因此,它的性能优于 REST API。

服务端实现

在这个例子中,我们使用java gRPC 实现一对一(Unary)通信。

首先使用 Maven 创建一个简单的 Java 应用程序,在 maven 中添加以下依赖项。

<dependencies>
<!-- https://mvnrepository.com/artifact/io.grpc/grpc-netty-shaded -->
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-netty-shaded</artifactId>
        <version>1.45.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.grpc/grpc-protobuf -->
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-protobuf</artifactId>
        <version>1.45.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.grpc/grpc-stub -->
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>1.45.0</version>
    </dependency>
    <dependency> <!-- necessary for Java 9+ -->           
        <groupId>org.apache.tomcat</groupId>
        <artifactId>annotations-api</artifactId>
        <version>6.0.53</version>
        <scope>provided</scope>
    </dependency>
    <!-- This is needed to override a managed guava dependency-->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>21.0</version>
    </dependency>
</dependencies>
复制代码

我们还需要添加相关的插件到我们的 maven 文件。

在配置完成相关依赖后,然后在.prot 文件中定义服务器接口proto协议。

syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.code_examples.grpc.v1";
service HelloWorldService {
rpc ExecuteOrder(HelloRequest) returns (HelloResponse) {};
}
message HelloRequest {
string greetings = 1;
}
message HelloResponse {
string info = 1;
}
复制代码

接下来使用 mvn clean install 构建项目。此步骤将自动生成stubs和abstract files 。在使用 IDE 引用我们创建的类时,一定要确保将它们添加到类路径中。

然后创建一个 Service 类并重写基类的 executeOrder ()方法。

@Override
public void executeOrder(com.code_examples.grpc.v1.HelloRequest request,io.grpc.stub.StreamObserver<com.code_examples.grpc.v1.HelloResponse> responseObserver) {
    HelloResponse response = HelloResponse.newBuilder().setInfo(request.getGreetings()).build();responseObserver.onNext(response);
    responseObserver.onCompleted();
}
复制代码

在这个service中,我们从请求中读取信息,并将其作为响应发送回客户机。

最后,我们创建建一个类来启动服务器。

public static void main(String[] args) throws IOException, InterruptedException {
    Server server = ServerBuilder.forPort(8085).addService(new HelloWorldServiceImpl()).build();
    server.start();
    server.awaitTermination();
}
复制代码

在main方法中,我们调用上面实现的service,并在端口8085上启动服务器。

最后我们运行main方法,完成启动服务器。

客户端实现

创建一个客户端类,并向服务器发送消息。

ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost",8085).usePlaintext().build();
HelloWorldServiceBlockingStub orderServiceBlockingStub = HelloWorldServiceGrpc.newBlockingStub(managedChannel);
HelloRequest helloReq = HelloRequest.newBuilder().setGreetings("Hey Foo").build();
HelloResponse helloResponse = orderServiceBlockingStub.executeOrder(helloReq);
System.out.println("Received response: " + helloResponse.getInfo());
managedChannel.shutdown();
复制代码

运行客户端类并验证检查输出。以下为来自服务器的响应。

image.png

猜你喜欢

转载自juejin.im/post/7082910429990617124