GRPC

google的RPC框架:grpc 介绍

原创 2016年05月24日 05:26:01
  • 7148

简要介绍

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

要编译上面的代码,首先参照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=protoc-gen-grpc-java \
--grpc-java_out="./src/java/helloworld" hello.proto
  • 1
  • 2
  • 3

就会自动生成一些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();
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

代码中各部分的作用,看方法名也能猜出来,就不再加注释了。

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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

运行

首先运行HelloServer.java,让其处于监听请求的状态,然后运行客户端,即可看到hello wangliang的输出。

本文的完整代码可见https://github.com/intfloat/mass-stuff/tree/master/grpc.

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页