gRPC最全详解(定义原理及使用示例)

gRPC最全详解(定义原理及使用示例)-mikechen

gRPC定义

gRPC最全详解(定义原理及使用示例)-mikechen

gRPC,全程是Google Remote Procedure Call,是由Google开发并开源,是一种高性能、通用的开源远程过程调用RPC框架。

 

gRPC原理

gRPC架构由以下几个主要组件构成:

gRPC最全详解(定义原理及使用示例)-mikechen

1.服务定义(Service Definition)

gRPC使用接口描述语言(IDL)来定义服务接口和消息结构。

IDL提供了一种统一的方式来描述服务和消息,使得不同语言的开发者可以根据IDL生成对应的客户端和服务器端代码。

2.代码生成器(Code Generator)

基于服务定义的IDL文件,gRPC提供了代码生成器工具,可以根据IDL文件自动生成客户端和服务器端的代码。

生成的代码包含了接口的实现、序列化和反序列化的逻辑,提供了对应语言的API和运行时支持。

3.传输层(Transport Layer)

gRPC使用HTTP/2作为底层的传输协议,HTTP/2是一种二进制协议,相比于传统的HTTP/1.x协议,它具有更低的延迟和更高的吞吐量。

HTTP/2支持多路复用,允许多个请求和响应在同一个TCP连接上同时进行,减少了网络连接的开销。

4.序列化和反序列化(Serialization/Deserialization)

gRPC使用Protocol Buffers(ProtoBuf)作为默认的序列化和反序列化机制。

ProtoBuf是一种轻量级的结构化数据交换格式,能够将结构化数据序列化为二进制格式进行传输。

5.服务器端(Server)

gRPC服务器端负责接收和处理客户端发起的RPC请求。

服务器端根据服务定义生成的代码实现服务接口中的方法,并根据接收到的请求进行相应的处理。

6.客户端(Client)

gRPC客户端负责发起RPC请求并接收服务器端的响应。

客户端根据服务定义生成的代码调用相应的方法,并将请求参数传递给服务器端。

 

gRPC工作流程

与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法,包含参数和返回类型。

在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用,在客户端拥有一个存根能够像服务端一样的方法。

远程过程调用流程图,如下图所示:

gRPC最全详解(定义原理及使用示例)-mikechen

主要会包含如下步骤:

  1. 调用客户端句柄,执行传送参数;
  2. 调用本地系统内核发送网络消息;
  3. 消息传送到远程主机上;
  4. 服务器句柄得到消息并取得参数;
  5. 执行远程过程;
  6. 执行的过程将结果返回服务器句柄;
  7. 服务器句柄返回结果,调用远程系统内核;
  8. 消息传回本地主机上;
  9. 客户端句柄由内核接收消息;
  10. 客户接收句柄返回的数据。

 

RPC使用示例

下面是一个简单的RPC使用示例,以展示客户端和服务器端之间的远程过程调用。

1.定义服务接口和消息结构

创建一个名为Calculator.proto的ProtoBuf文件,其中定义了一个计算器服务的接口和消息结构。

syntax = "proto3";

package com.example.grpc;

service Calculator {
  rpc Add(AddRequest) returns (AddResponse) {}
}

message AddRequest {
  int32 operand1 = 1;
  int32 operand2 = 2;
}

message AddResponse {
  int32 sum = 1;
}

 

2.生成代码

使用 Protocol Buffer 编译器 protoc 来生成Java代码。

protoc --java_out=. Calculator.proto

 

3.实现服务接口

package com.example.grpc;

import io.grpc.stub.StreamObserver;

public class CalculatorImpl extends CalculatorGrpc.CalculatorImplBase {

  @Override
  public void add(AddRequest request, StreamObserver<AddResponse> responseObserver) {
    int sum = request.getOperand1() + request.getOperand2();
    AddResponse response = AddResponse.newBuilder().setSum(sum).build();

    responseObserver.onNext(response);
    responseObserver.onCompleted();
  }
}

 

4.启动 gRPC 服务器

package com.example.grpc;

import io.grpc.Server;
import io.grpc.ServerBuilder;

import java.io.IOException;

public class Server {
  public static void main(String[] args) throws IOException, InterruptedException {
    Server server = ServerBuilder.forPort(50051)
        .addService(new CalculatorImpl())
        .build();

    server.start();
    System.out.println("Server started on port 50051");
    server.awaitTermination();
  }
}

 

5.创建 gRPC 客户端

package com.example.grpc;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

public class Client {
  public static void main(String[] args) {
    ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
        .usePlaintext()
        .build();

    CalculatorGrpc.CalculatorBlockingStub stub = CalculatorGrpc.newBlockingStub(channel);

    AddRequest request = AddRequest.newBuilder()
        .setOperand1(5)
        .setOperand2(3)
        .build();

    AddResponse response = stub.add(request);

    System.out.println("Sum: " + response.getSum());

    channel.shutdown();
  }
}

在上述示例中,我们创建了一个 gRPC 服务器,并实现了计算器服务的接口。然后,我们创建了一个 gRPC 客户端,使用该客户端向服务器发送 AddRequest 请求,并接收 AddResponse 响应。

作者简介

陈睿|mikechen,10年+大厂架构经验,BAT资深面试官,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

👇阅读更多mikechen架构文章👇

阿里架构 |双11秒杀 |分布式架构 |负载均衡 |单点登录 |微服务 |云原生 |高并发 |架构师

以上

关注作者「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法