grpc 详解 java版
Java中gRPC的基本教程介绍。
本教程提供了有关使用gRPC的基本Java程序员介绍。
通过遍历此示例,您将学习如何:
grpc设计的核心概念。
在.proto文件中定义服务。
使用协议缓冲区编译器生成服务器和客户端代码。
使用Java gRPC API为您的服务编写一个简单的客户端和服务器。
假定您已经阅读了gRPC简介并且熟悉协议缓冲区。请注意,本教程中的示例使用了 proto3协议缓冲区语言的版本:您可以在proto3语言指南中找到更多信息和Java生成的代码指南。
为什么要使用gRPC?
我们的示例是一个简单的路由映射应用程序,它使客户端可以获取有关其路由功能的信息,创建其路由的摘要以及与服务器和其他客户端交换路由信息(例如流量更新)。
借助gRPC,我们可以在一个.proto文件中定义一次服务,并以gRPC支持的任何语言生成客户端和服务器,而这又可以在从大型数据中心内的服务器到您自己的平板电脑的各种环境中运行– gRPC为您处理不同的语言和环境。我们还获得了使用协议缓冲区的所有优点,包括有效的序列化,简单的IDL和轻松的接口更新。
核心概念
GRPC包含三个不同的层:Stub, Channel和Transport。
Stu
Stub层是大多数开发人员都可以接触到的,它为您要适应的任何数据模型/ IDL /接口提供类型安全的绑定。gRPC带有协议缓冲区编译器的插件,该插件可以从.proto文件中生成Stub接口,但是与其他数据模型/ IDL的绑定是容易的并且值得鼓励。
Channel
通道层是传输处理上的抽象,适合于侦听/装饰,并且比存根(Stub)层向应用程序公开更多的行为。对于应用程序框架而言,使用该层来解决诸如日志记录,监视,身份验证等跨领域的问题很容易。
Transport
传输层不费吹灰之力地将字节从导线中取出。它的接口是抽象的,足以允许插入不同的实现。请注意,传输层API被认为是gRPC内部的,并且与包中的核心API相比,其API保证较弱io.grpc。
gRPC带有三种传输实现:
基于Netty的传输是基于Netty的主要传输实现 。它适用于客户端和服务器。
基于OkHttp的传输是基于OkHttp的轻量级传输 。它主要用于Android,并且仅用于客户端。
进程内传输适用于服务器与客户端处于同一进程中的情况。它对于测试很有用,同时也可以安全地用于生产。
示例代码和设置
$ git clone -b v1.34.0 https://github.com/grpc/grpc-java.git
然后将当前目录更改为grpc-java/examples:
$ cd grpc-java/examples
定义服务
在此示例中生成Java代码时,我们java_package 在.proto中指定了一个文件选项:
option java_package = "io.grpc.examples.routeguide";
这指定了我们要用于生成的Java类的包。如果java_package.proto文件中未提供显式选项,则默认情况下将使用proto软件包(使用“ package”关键字指定)。但是,proto软件包通常不能成为良好的Java包,因为proto软件包不应以反向域名开头。如果我们从此.proto生成另一种语言的代码,则该java_package选项无效。
要定义服务,我们service在.proto文件中指定一个名称:
service RouteGuide {
...
}
然后,rpc在服务定义中定义方法,并指定其请求和响应类型。gRPC允许您定义四种服务方法,所有这些方法都在RouteGuide服务中使用:
一个简单的RPC,客户端使用存根将请求发送到服务器,然后等待响应返回,就像正常的函数调用一样。
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
一个服务器端流RPC,其中客户端发送请求到服务器,并获得一个流中读取消息的序列后面。客户端从返回的流中读取,直到没有更多消息为止。如我们的示例所示,您可以通过stream 在响应类型之前放置关键字来指定服务器端流方法。
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
一个客户端流传输的RPC,其中客户端将消息写入Point序列,并且将它们发送到服务器,再次使用提供的流。客户端写完消息后,它将等待服务器读取所有消息并返回其响应。您可以通过将stream关键字放在请求类型之前来指定客户端流方法。
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
一个双向流RPC双方都派出使用读写流的消息序列。这两个流是独立运行的,因此客户端和服务器可以按照自己喜欢的顺序进行读写:例如,服务器可以在写响应之前等待接收所有客户端消息,或者可以先读取一条消息再写入一条消息,或其他一些读写组合。每个流中的消息顺序都会保留。您可以通过stream 在请求和响应之前放置关键字来指定这种类型的方法。
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
我们的.proto文件还包含用于服务方法中所有请求和响应类型的协议缓冲区消息类型定义-例如,以下是Point消息类型:
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +