定义服务
- 一个 RPC 服务通过参数和返回类型来指定可以远程调用的方法。gRPC 通过 protocol buffers 来实现。
- 我们使用 protocol buffers 接口定义语言来定义服务方法,用 protocol buffer 来定义参数和返回类型。客户端和服务端均使用服务定义生成的接口代码。
- 这里有我们服务定义的例子,在 helloworld.proto 里用 protocol buffers IDL 定义的。Greeter 服务有一个方法 SayHello ,可以让服务端从远程客户端接收一个包含用户名的 HelloRequest 消息后,在一个 HelloReply 里发送回一个 Greeter。
syntax = "proto3";
option java_package = "io.grpc.examples";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
写一个服务器
GreeterImpl.java 准确地实现了 Greeter 服务所需要的行为。 正如你所见,GreeterImpl 类通过实现 sayHello 方法,实现了从 IDL 生成的GreeterGrpc.Greeter 接口 。
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
sayHello 有两个参数:
- HelloRequest,请求。
- StreamObserver: 应答观察者,一个特殊的接口,服务器用应答来调用它。
为了返回给客户端应答并且完成调用:
用我们的消息构建并填充一个在我们接口定义的 HelloReply 应答对象。 将 HelloReply 返回给客户端,然后表明我们已经完成了对 RPC 的处理。
服务端实现
需要提供一个 gRPC 服务的另一个主要功能是让这个服务实在在网络上可用。 HelloWorldServer.java 提供了以下代码作为 Java 的例子。
private int port = 50051;
private Server server;
private void start() throws Exception {
server = ServerBuilder.forPort(port)
.addService(GreeterGrpc.bindService(new GreeterImpl()))
.build()
.start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}
});
}
写一个客户端
调用 RPC
客户端的 gRPC 非常简单。在这一步,我们将用生成的代码写一个简单的客户程序来访问我们在上一节里创建的 Greeter 服务器。 同样,我们也不打算对如何实现一个客户端程序深入更多,我们把这些内容放到教程里。
连接服务 首先我们看一下我们如何连接 Greeter 服务器。我们需要创建一个 gRPC 频道,指定我们要连接的主机名和服务器端口。然后我们用这个频道创建存根实例。
private final ManagedChannel channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public HelloWorldClient(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext(true)
.build();
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
现在我们可以联系服务并获得一个 greeting :
- 我们创建并填充一个 HelloRequest 发送给服务。
- 我们用请求调用存根的 SayHello(),如果 RPC 成功,会得到一个填充的 HelloReply ,从其中我们可以获得 greeting。
HelloRequest req = HelloRequest.newBuilder().setName(name).build();
HelloReply reply = blockingStub.sayHello(req);
|