学习gRPC的基本用法,并在 gRPC 中实现客户端用户核验的两个demo

本文介绍了gRPC的基本用法,包括RPC和gRPC的概念、四种通信模式及拦截器。还阐述了JWT的相关知识,如无状态登录、数据结构、交互流程等,并实践了在gRPC中结合JWT完成身份校验,给出了主项目、服务端、客户端代码及功能测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码仓库1(实现grpc四种通信模式和拦截器的demo):代码仓库1

代码仓库2(在grpc中实现客户端用户核验,使用JWT):代码仓库2

一、gRPC的基本用法

1.什么是RPC

在学习gRPC之前,我们首先要了解什么是RPC。

RPC(Remote Procedure Call)是远程过程调用协议,它是一种通过网络从远程计算机上请求服务,而不需要了解底层网络技术的协议。RPC的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC框架需提供一种透明调用机制,让使用者不必显式的区分本地调用和远程调用。

通俗地讲,使用RPC进行通信,调用远程函数就像调用本地函数一样,RPC底层会做好数据的序列化与传输,从而能使我们更轻松地创建分布式应用和服务。

2.什么是gRPC

gRPC是一种用于实现RPC的新式的、开源的高性能框架。gRPC源自Google,他基于定义服务的思想,指定可以远程调用的接口及其参数和返回类型。服务端实现这个接口并运行一个 gRPC 服务器来处理客户端调用。而客户端有一个stub(存根,在某些语言中称为客户端client),它提供与服务器相同的方法。客户端通过调用stub的方法来与服务端进行通信,获取响应结果。

gRPC的典型特征就是使用protobuf(全称protocol buffers)作为其接口定义语言(Interface Definition Language,缩写IDL),同时底层的消息交换格式也是使用protobuf。开发人员使用IDL为每个微服务定义服务协定。该协定作为基于文本的 .proto 文件实现,描述了每个服务的方法、输入和输出。同一文件可用于基于不同开发平台不同语言构建的gRPC客户端和服务。

3.gRPC的四种通信模式

gRPC中服务端和客户端的交互存在着四种不同的通信模式:

  1. 一元RPC(unary RPC)
  2. 服务端流 RPC(server-streaming RPC)
  3. 客户端流 RPC(client-streaming RPC)
  4. 双向流 RPC(bidirectional-streaming RPC)

下面我们将通过一个小的demo来了解一下这四种通信模式(对应代码仓库1的内容)

3.1 准备工作

我的整体项目结构如下

grpc-communicationMode
│ 
├───bidirectional-streamingRPC-client//双向流RPC客户端
│   ├───pom.xml
│   ├───src
├───bidirectional-streamingRPC-server//双向流RPC服务端
│   ├───pom.xml
│   ├───src
├───client-streamingRPC-client//客户端流RPC客户端
│   ├───pom.xml
│   ├───src
├───client-streamingRPC-server//客户端流RPC服务端
│   ├───pom.xml
│   ├───src
├───server-streamingRPC-client//服务端流RPC客户端
│   ├───pom.xml
│   ├───src
├───server-streamingRPC-server//服务端流RPC服务端
│   ├───pom.xml
│   ├───src
├───src//主项目源码
├───UnaryRPC-client//一元RPC客户端,内部实现了客户端拦截器
│   ├───pom.xml
│   ├───src
├───UnaryRPC-server//一元RPC服务端,内部实现了服务端拦截器
│   ├───pom.xml
│   ├───src
└───pom.xml//主项目配置文件

首先在idea中创建maven项目 grpc-communicationMode ,作为父项目,引入项目依赖和所需插件

    <dependencies>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.52.1</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.52.1</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.52.1</version>
        </dependency>
        <dependency> 
            <groupId>org.apache.tomcat</groupId>
            <artifactId>annotations-api</artifactId>
            <version>6.0.53</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

   <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.21.7:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.51.0:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

默认情况下,gRPC 使用 Protocol Buffers,这是 Google 提供的一个成熟的开源的跨平台的序列化数据结构的协议,我们编写对应的 proto 文件,通过上面这个插件可以将我们编写的 proto 文件自动转为对应的 Java 类。

接着在src/main/proto 的位置,我们新建一个 book.proto 文件,用于定义数据结构和服务接口。

数据结构即消息类型,我们可以在.proto文件中定义各种消息类型,每种消息类型都可以包含多个字段,每个字段都有一个名称和类型。这些数据结构会在客户端和服务端之间进行交换。
服务接口则定义了服务端可以提供哪些RPC方法,以及这些方法的输入和输出参数。

一旦定义了数据结构和服务接口,就可以使用gRPC的工具来自动生成客户端和服务器的代码。这些代码可以在gRPC支持的任何语言中运行,包括但不限于C++, Java, Python, Go, Ruby,等。
book.proto内容如下,主要定义了一些图书相关的方法:

syntax = "proto3";

option java_multiple_files = true;
option java_package = "ustc.codemaker.grpc.demo1";
option java_outer_classname = "BookServiceProto";
import "google/protobuf/wrappers.proto";

package book;

service BookService {
   rpc addBook(Book) returns (google.protobuf.StringValue);//添加图书,使用图书对象插入,返回插入图书的id
   rpc getBook(google.protobuf.StringValue) returns (Book);//获取图书,使用id查找,返回图书对象
   rpc searchBooks(google.protobuf.StringValue) returns (stream Book);//查找图书,使用tag查找,返回所有包含tag的图书对象
   rpc updateBooks(stream Book) returns (google.protobuf.StringValue);//更新图书,给出一系列更新操作,返回所有被更改的图书id
   rpc processBooks(stream google.protobuf.StringValue) returns (stream BookSet);//模拟双向流,没有实际意义
}

message Book {
  string id = 1;
  repeated string tags = 2;
  string name = 3;
  float price = 4;
  string author = 5;
}

message BookSet {
  string id = 1;
  repeated Book bookList = 3;
}

注意如果不在src/main/proto这个默认位置创建.proto文件的话,那么在配置插件的时候需要指定 proto 文件的位置。

.proto文件是grpc中比较核心的配置,我们简单介绍一下:

  1. option java_multiple_files = true;可选字段,如果设置为 true,表示每一个 message 文件都会对应一个单独的 class 文件;否则,message 将被全部定义在 outerclass 文件里。
  2. option java_package = "ustc.codemaker.grpc.ddemo1"; 可选字段,用于标识生成的 java 文件的 package。如果没有指定,则使用 proto 里定义的 package,如果package 也没有指定,那就会生成在根目录下。
  3. option java_outer_classname = "BookServiceProto"; 可选字段,用于指定 proto 文件生成的 java 类的 outerclass 类名。outerclass是一个包含所有message对应的Java类的class文件。如果没有指定,那么outerclass的名称将默认为proto文件的驼峰式名称。
  4. package book;这个属性用于定义message的包名。包名的含
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值