社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
gRPC是一个高性能、开源和通用的 RPC 框架,面向HTTP/2设计目前 提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持。
gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。
gRPC 官方文档中文版
在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
2 protocol buffers
gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。正如你将在下方例子里所看到的,你用 proto files 创建 gRPC 服务,用 protocol buffers 消息类型来定义方法参数和返回类型。
protoc-Java插件
3.HTTP/2 特性
1、写helloworld.proto文件
syntax = "proto3";
option java_multiple_files = true;
option java_package = "demo";
option java_outer_classname = "HelloWorldProto";
//option java_generic_services = true; // 可以生成rpc接口
package helloworld;
service GreetHelloWorld {
rpc SayHello (HelloWorldRequest) returns (HelloWorldResponse);
}
message HelloWorldRequest {
string name = 1;
}
message HelloWorldResponse {
string message = 1;
}
注:
proto文件编译命令
1、在protoc编辑器的bin目录下增加protoc-Java插件,实例是把proto文件放在bin目录下实践的
2、cmd命令行下操作
3、先编译生成model,命令protoc –java_out=D:workspacegPRC-RPCsrcmainjava ./helloworld.proto
4、在编译生成service,命令protoc –plugin=protoc-gen-grpc-java=E:/develop/gRPC/protoc-3.0.0-win32/bin/protoc-gen-grpc-java-1.10.0-windows-x86_64.exe –grpc-java_out=D:workspacegPRC-RPCsrcmainjava ./helloworld.proto
5、建议使用proto3进行文件编写
2、生成文件目录列表
3、服务端实现
package demo.end;
import io.grpc.Server;
import java.io.IOException;
import io.grpc.ServerBuilder;
import demo.HelloWorldRequest;
import demo.HelloWorldResponse;
import io.grpc.BindableService;
import io.grpc.stub.StreamObserver;
import demo.GreetHelloWorldGrpc.GreetHelloWorldImplBase;
public class HelloWorldServer {
private int port = 8851;
private Server server;
private void start() throws IOException {
server = ServerBuilder.forPort(port)
.addService((BindableService) new GreeterHelloWorldImpl())
.build()
.start();
System.out.println("service start...");
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");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
final HelloWorldServer server = new HelloWorldServer();
server.start();
server.blockUntilShutdown();
}
// 实现 定义一个实现服务接口的类
private class GreeterHelloWorldImpl extends GreetHelloWorldImplBase {
public void sayHello(HelloWorldRequest req, StreamObserver<HelloWorldResponse> responseObserver) {
// 具体其他丰富的业务实现代码
System.err.println("service:" + req.getName());
HelloWorldResponse reply = HelloWorldResponse.newBuilder().setMessage(("Hello: " + req.getName())).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
4、客户端实现
package demo.end;
import java.util.concurrent.TimeUnit;
import demo.GreetHelloWorldGrpc;
import demo.GreetHelloWorldGrpc.GreetHelloWorldBlockingStub;
import demo.HelloWorldRequest;
import demo.HelloWorldResponse;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class HelloWorldClient {
private final ManagedChannel channel;
private final GreetHelloWorldBlockingStub blockingStub;
public HelloWorldClient(String host,int port){
channel = ManagedChannelBuilder.forAddress(host,port)
.usePlaintext(true)
.build();
blockingStub = GreetHelloWorldGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public void greet(String name){
HelloWorldRequest request = HelloWorldRequest.newBuilder().setName(name).build();
HelloWorldResponse response = blockingStub.sayHello(request);
System.out.println(response.getMessage());
}
public static void main(String[] args) throws InterruptedException {
HelloWorldClient client = new HelloWorldClient("127.0.0.1", 8851);
for(int i=0;i<5;i++){
client.greet("world:"+i);
}
}
}
5、pom.xml配置文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>gRPC</groupId>
<artifactId>gPRC-RPC</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.10.0</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.6.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.10.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
6、运行结果展示
优点:
1)protobuf二进制消息,性能好/效率高(空间和时间效率都很不错)
2)proto文件生成目标代码,简单易用
3)序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射(XML,JSON都是这种方式)
4)支持向前兼容(新加字段采用默认值)和向后兼容(忽略新加字段),简化升级
5)支持多种语言(可以把proto文件看做IDL文件)
6)Netty等一些框架集成
缺点:
1)GRPC尚未提供连接池,需要自行实现
2)尚未提供“服务发现”、“负载均衡”机制
3)因为基于HTTP2,绝大部多数HTTP Server、Nginx都尚不支持,即Nginx不能将GRPC请求作为HTTP请求来负载均衡,而是作为普通的TCP请求。(nginx1.9版本已支持)
4) Protobuf二进制可读性差
5)默认不具备动态特性(可以通过动态定义生成消息类型或者动态编译支持)
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!