# grpc
**Repository Path**: 502959937/grpc
## Basic Information
- **Project Name**: grpc
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 1
- **Created**: 2016-01-11
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 关于 grpc , proto3 的实践分享
## 前言
> 互联网+ , 微服务化---服务模块化,它们之间的数据交互协作方式TCP/IP自定义协议 ,Restful风格,RPC(远程调用)等
> RPC (远程过程调用,远程方法调用)----允许一台电脑上的程序调用另一台电脑的程序,它有标准化的沟通机制,
为了能够实现跨平台,大都采用接口描述性语言(Interface Description Language,IDL),无需关注底层实现,专注业务需求开发
### [facebook 开发的 apache thrift](https://thrift.apache.org/)
> 它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,
如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk等创建高效的、无缝的服务,
其传输数据采用二进制格式 [thrift应用实践demo](https://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/)
### [google开发的GRPC](http://www.grpc.io/)
> gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,
基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。
+ apache thrift 和 grpc 都采用 IDL来作为沟通机制,[IDL详细介绍请参考第4期序列化方案选择](https://git.suweia.net/chenlei/suwei-talks/tree/master/talks/4)
# GRPC 构建
### 支持多种语言
> 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. 便于各方面扩展的分层设计,如认证、负载均衡、日志记录、监控等
### gRPC是什么
> 使用gRPC,一个客户端应用程序可以直接调用另一台机器上的服务端应用程序的方法,就好像调用本地方法一样。这使得更容易创建分布式应用程序和服务。
正如很多RPC系统,gRPC是基于定义服务,指定可以远程调用方法的参数和返回类型的概念。在服务器侧,服务端实现该接口并且返回gRPC的客户端来处理客户端调用请求。
在客户端侧,客户端打桩,提供跟服务端一样的方法。

## [proto3 编译安装 ](https://github.com/google/protobuf)
1. 编译基础需求
+ autoconf
+ automake
+ libtool
+ curl (used to download gmock)
2. 构建
```
#注意配置依赖 gmock --- (被墙)
./autogen.sh
./configure --prefix=/usr
make && make check && make install
```
3. 编写IDL文件
```
syntax = "proto3";
option java_multiple_files = true;
package pb;
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloResponse){}
}
service Test {
// 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;
}
```
4. 依赖maven,构建GRPC的编译器

```
4.0.0
3.0.0-beta-2
0.9.0
//grpc需求依赖的模块
io.grpc
grpc-core
${grpc.version}
io.grpc
grpc-stub
${grpc.version}
io.grpc
grpc-protobuf
${grpc.version}
io.grpc
grpc-netty
${grpc.version}
com.google.protobuf
protobuf-java
${protobuf.version}
com.google.protobuf.nano
protobuf-javanano
3.0.0-alpha-5
never
false
central
Central Repository
https://repo.maven.apache.org/maven2
protoc-plugin
https://dl.bintray.com/sergei-ivanov/maven/
kr.motd.maven
os-maven-plugin
1.4.0.Final
com.google.protobuf.tools
maven-protoc-plugin
0.4.4
grpc-java
com.google.protobuf:protoc:3.0.0-beta-2:exe:${os.detected.classifier}
io.grpc:protoc-gen-grpc-java:0.9.0:exe:${os.detected.classifier}
compile
compile-custom
```
### 生成的对象解析
```
/**
服务端实现接口
*/
public static interface Greeter {
public void sayHello(pb.HelloRequest request,
io.grpc.stub.StreamObserver responseObserver);
}
/**
* 客户端实现接口
*/
public static interface GreeterBlockingClient {
public pb.HelloResponse sayHello(pb.HelloRequest request);
}
/**
调用方法
*/
@java.lang.Override
public void sayHello(pb.HelloRequest request,
io.grpc.stub.StreamObserver responseObserver) {
asyncUnaryCall(
getChannel().newCall(METHOD_SAY_HELLO, getCallOptions()), request, responseObserver);
}
}
/*
绑定服务 ---
*
/
public static io.grpc.ServerServiceDefinition bindService(
final Greeter serviceImpl) {
return io.grpc.ServerServiceDefinition.builder(SERVICE_NAME)
.addMethod(
METHOD_SAY_HELLO,
asyncUnaryCall(
new io.grpc.stub.ServerCalls.UnaryMethod<
pb.HelloRequest,
pb.HelloResponse>() {
@java.lang.Override
public void invoke(
pb.HelloRequest request,
io.grpc.stub.StreamObserver responseObserver) {
serviceImpl.sayHello(request, responseObserver);
}
})).build();
}
}
```
## 关键代码片段分解

### 服务器端
1.服务端包含2个模块:网络模块,服务绑定模块
>ServerBuilder(基于netty构建的HTTP/2)

>网络模块

```
/**
* handle logic thread pool
* 用于执行业务逻辑
*/
private static final ExecutorService executorService =
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()
, new NamedThreadFactory("logic-handler"));
/**
* 启动服务
*
* @throws Exception
*/
public void startGrpc() throws Exception {
//init builder
initServerBuilder();
//bind service
server = nettyServerBuilder.build().start();
//register hook
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may has been reset by its JVM shutdown hook.
logger.debug("*** shutting down gRPC server since JVM is shutting down");
if (server != null) {
server.shutdown();// shut down
}
executorService.shutdown();
logger.debug("*** server shut down");
}
});
if (logger.isDebugEnabled()) {
logger.debug("grpc_server bind service port:" + port);
}
}
/**
* 挂起服务,提供持久的对外服务
* @throws InterruptedException
*/
public void awaitTermination() throws InterruptedException {
server.awaitTermination();
}
```
>绑定服务模块
[服务绑定抽象类](pic/bind_service.png)
> 简单的逻辑实现(对外服务)

### 客户端
>发送的channel ----ManagedChannel,grpc-java 内建根据权重选择对应的channel实现(netty,okhttp,inprocess)

#### 初始化chanel
```
if (PlatformDependent.isAndroid()) {// android 平台
channel = OkHttpChannelBuilder.forAddress(host, port)
.usePlaintext(true)
.build();
} else {
ManagedChannelBuilder managedChannelBuilder = ManagedChannelBuilder.forAddress(host, port);
if (managedChannelBuilder instanceof NettyChannelBuilder) {
NettyChannelBuilder nettyChannelBuilder = (NettyChannelBuilder) managedChannelBuilder;
//default is TLS
// nettyChannelBuilder.negotiationType(NegotiationType.TLS);
// try {
// nettyChannelBuilder.sslContext(GrpcSslContexts.forClient().build());
// } catch (SSLException e) {
// e.printStackTrace();
// }
channel = nettyChannelBuilder
.usePlaintext(true)
.build();
} else if (managedChannelBuilder instanceof InProcessChannelBuilder) {
InProcessChannelBuilder inProcessChannelBuilder =
(InProcessChannelBuilder) managedChannelBuilder;
channel = inProcessChannelBuilder
.usePlaintext(true)
.build();
}
}
```
#### 简单使用
```
/**
* 作为单例对象
*/
HelloWorldClient client = new HelloWorldClient("localhost", 50051);
//build blocking stub (client)----
GreeterGrpc.GreeterBlockingClient greeterBlockingClient =
GreeterGrpc.newBlockingStub(grpcClient.getChannel());
//builder send data
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
grpcClient.shutdown();
```
#### 演示