简要介绍
google 去年开源了一个RPC(remote procedure call)框架grpc:https://github.com/grpc/grpc
RPC的中文翻译是远程过程调用,是在服务器端程序设计常用的一种技术。对于本地过程调用,要做某件事,就在本机上执行某个代码段;对于RPC来说,服务的使用者和提供者可以位于不同的计算机上,客户端(client)只需要告诉服务器端(server)要做什么事情,这一请求通过网络发送给server,server上执行完成之后把结果返回给客户端。
gprc采用了protocol buffer来做数据的序列化与反序列化,用http 2作为数据传输协议,性能更优。
下面以grpc-java为基础来写一个简单的HelloWorld项目。
定义proto接口
首先用protocol buffer来定义相关的接口(下面简称proto),proto是一种IDL(Interface Definition Language),语法比较简洁,可以生成各种主流语言版本的代码,比如C++, Java, Python等等。
详细的语法请看https://developers.google.com/protocol-buffers/。我们给出代码:
syntax = "proto2";
// compile commands:
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}
要编译上面的代码,首先参照https://github.com/google/protobuf安装proto compiler,安装完成之后可以直接在命令行执行protoc
.
要想使用grpc
,还需要安装一个proto
插件,参照https://github.com/grpc/grpc-java/blob/master/COMPILING.md
这个确实比较麻烦一点,google应该把这部分做得更用户友好一些。
然后执行
protoc --plugin=protoc-gen-grpc-java \
--grpc-java_out="./src/java/helloworld" hello.proto
就会自动生成一些java
文件,特别特别长。。。
写RPC的服务器端
rpc服务器端和web服务器比较类似,都是在某个端口监听来自客户端的请求,收到请求之后就调用相应的方法处理,然后把执行的结果返回给客户端。
package io.grpc.examples.helloworld;
import io.grpc.examples.helloworld.GreeterGrpc.AbstractGreeter;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
/**
* Created by Liang Wang on 16-5-8.
* email: intfloat@pku.edu.cn
*/
public class HelloServer {
private int port = 8883;
private io.grpc.Server server;
public void run() {
server = io.grpc.ServerBuilder.forPort(port).addService(new GreetRpc()).build();
try {
server.start();
server.awaitTermination();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
HelloServer hs = new HelloServer();
hs.run();
return;
}
private class GreetRpc extends AbstractGreeter {
@Override
public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
String name = request.getName();
name = "Hello " + name;
HelloReply reply = HelloReply.newBuilder().setMessage(name).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
代码中各部分的作用,看方法名也能猜出来,就不再加注释了。
server在8883端口上监听,收到一个带名字name的请求,就说一句”Hello name”返回给客户端。
写RPC的客户端
客户端需要知道服务器端的ip地址和端口,然后调用proto中定义的服务接口就好了。
package io.grpc.examples.helloworld;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
/**
* Created by Liang Wang on 16-5-15.
* email: intfloat@pku.edu.cn
*/
public class HelloClient {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 8883)
.usePlaintext(true)
.build();
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
HelloRequest req = HelloRequest.newBuilder().setName("wangliang").build();
HelloReply reply;
reply = stub.sayHello(req);
System.out.println(reply.getMessage());
return;
}
}
运行
首先运行HelloServer.java
,让其处于监听请求的状态,然后运行客户端,即可看到hello wangliang
的输出。