gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准、ProtoBuf(Protocol Buffers)序列化协议而设计开发,带来诸如双向流、流控、头部压缩、单TCP连接上的多复用请求等特性,这些特性使得其在移动设备上表现更好。
一、强大的IDL特性
Protocol Buffers简称protobuf是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。它不依赖于语言和平台并且可扩展性极强。现阶段官方支持C++、JAVA、Python等三种编程语言,但可以找到大量的几乎涵盖所有语言的第三方拓展包。
gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。不过,当前gRPC仅支持 Protobuf ,且不支持在浏览器中使用。由于gRPC的设计能够支持支持多种数据格式,所以读者能够很容易实现对其他数据格式(如XML、JSON等)的支持。
定义服务的示例代码如下:
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
service HelloService {
rpc SayHello(HelloRequest) returns (HelloResponse);
}
二、支持多种语言
gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前,在GitHub上已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中 grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。
三、基于HTTP/2标准设计
由于gRPC基于HTTP/2标准设计,所以相对于其他RPC框架,gRPC带来了更多强大功能,如双向流、头部压缩、多复用请求等。这些功能给移动设备带来重大益处,如节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。同时,gRPC还能够提高了云端服务和Web应用的性能。gRPC既能够在客户端应用,也能够在服务器端应用,从而以透明的方式实现客户端和服务器端的通信和简化通信系统的构建。
四、应用场景
gRPC已经应用在Google的云服务和对外提供的API中,其主要应用场景如下:
1.低延迟、高扩展性、分布式的系统
2.同云服务器进行通信的移动应用客户端
3.设计语言独立、高效、精确的新协议
4.便于各方面扩展的分层设计,如认证、负载均衡、日志记录、监控等
官网: http://www.grpc.io/
java版本源码: https://github.com/grpc/grpc-java
C语言源码: https://github.com/grpc/grpc
go语言源码: https://github.com/grpc/grpc-go
一、强大的IDL特性
Protocol Buffers简称protobuf是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。它不依赖于语言和平台并且可扩展性极强。现阶段官方支持C++、JAVA、Python等三种编程语言,但可以找到大量的几乎涵盖所有语言的第三方拓展包。
gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。不过,当前gRPC仅支持 Protobuf ,且不支持在浏览器中使用。由于gRPC的设计能够支持支持多种数据格式,所以读者能够很容易实现对其他数据格式(如XML、JSON等)的支持。
定义服务的示例代码如下:
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
service HelloService {
rpc SayHello(HelloRequest) returns (HelloResponse);
}
二、支持多种语言
gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前,在GitHub上已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中 grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。
三、基于HTTP/2标准设计
由于gRPC基于HTTP/2标准设计,所以相对于其他RPC框架,gRPC带来了更多强大功能,如双向流、头部压缩、多复用请求等。这些功能给移动设备带来重大益处,如节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。同时,gRPC还能够提高了云端服务和Web应用的性能。gRPC既能够在客户端应用,也能够在服务器端应用,从而以透明的方式实现客户端和服务器端的通信和简化通信系统的构建。
四、应用场景
gRPC已经应用在Google的云服务和对外提供的API中,其主要应用场景如下:
1.低延迟、高扩展性、分布式的系统
2.同云服务器进行通信的移动应用客户端
3.设计语言独立、高效、精确的新协议
4.便于各方面扩展的分层设计,如认证、负载均衡、日志记录、监控等
官网: http://www.grpc.io/
java版本源码: https://github.com/grpc/grpc-java
C语言源码: https://github.com/grpc/grpc
go语言源码: https://github.com/grpc/grpc-go
学习实例:https://github.com/grpc/grpc-common
五、使用实例
1.数据结构定义:
syntax = "proto3";
package grpc.example.helloworld;
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloResponse) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloResponse {
string message = 1;
}
2.客户端HelloWorldServer.java
package io.grpc.examples.helloworld;
import io.grpc.ServerImpl;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NettyServerBuilder;
import java.util.logging.Logger;
/**
* Server that manages startup/shutdown of a {@code Greeter} server.
*/
public class HelloWorldServer {
private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
/* The port on which the server should run */
private int port = 50051;
private ServerImpl server;
private void start() throws Exception {
server = NettyServerBuilder.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() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws Exception {
final HelloWorldServer server = new HelloWorldServer();
server.start();
}
private class GreeterImpl implements GreeterGrpc.Greeter {
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) {
HelloResponse reply = HelloResponse.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onValue(reply);
responseObserver.onCompleted();
}
}
}
3.服务端HelloWorldClient.java
package io.grpc.examples.helloworld;
import io.grpc.ChannelImpl;
import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple client that requests a greeting from the {@link HelloWorldServer}.
*/
public class HelloWorldClient {
private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());
private final ChannelImpl channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public HelloWorldClient(String host, int port) {
channel =
NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTerminated(5, TimeUnit.SECONDS);
}
public void greet(String name) {
try {
logger.info("Will try to greet " + name + " ...");
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloResponse response = blockingStub.sayHello(request);
logger.info("Greeting: " + response.getMessage());
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
return;
}
}
public static void main(String[] args) throws Exception {
HelloWorldClient client = new HelloWorldClient("localhost", 50051);
try {
/* Access a service running on the local machine on port 50051 */
String user = "world";
if (args.length > 0) {
user = args[0]; /* Use the arg as the name to greet if provided */
}
client.greet(user);
} finally {
client.shutdown();
}
}
}