谷歌开源的,RPC框架
定义方法名,方法参数 和 返回类型
client 去 proto Request
server proto Response 响应
运行环境无关性,和 开发语言 无关性
C++ Java Python Go C# Node.js PHP Ruby
service HelloService{
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequset{
string greetiong=1;
}
message HelloResponse{
string reply=1;
}
一元 RPC
rpc SayHello (HelloRequest) returns (HelloResponse){
}
//单个请求,单个响应。像本地的方法一样
服务端 流式 RPC
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
//响应是 流
}
//客户端发送一个请求,获取一个流,从流中读取消息,直到读取完毕
客户端 流式RPC
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse){
//请求式 流
}
//客户端 使用服务端提供的流写入,一旦写入完成,客户端等待服务端给出响应
双向流式RPC
rpc BidHello(stream HelloRequest) returns (stream HelloResponse){
}
//双方使用流发送,
protocol
英 /ˈprəʊtəkɒl/ 美 /ˈproʊtəkɑːl/ 全球(澳大利亚)
n. 协议;草案;礼仪
vt. 拟定
vi. 拟定
protocol buffers 简称 protobuf
高效 轻便 易用的
结构化 数据存储格式
用于 通信协议 和 数据存储 领域
比 xml 解析速度快了 20—100倍
比 json 快了 3—5倍
序列化非常紧凑,是 xml 数据体积 的 10% —30%
不仅包括:接口定义语言 IDL
还要: 编译组件的支持
maven : 会自动 安装编译组件
<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
然后安装 Protocol Buffers 的maven 插件。网址:https://www.xolstice.org/protobuf-maven-plugin/
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier}</protocArtifact>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<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.1.0:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
另一个配置
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension> 1.4.1不报错
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>0.5.0不报错
<configuration>
<protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
<!--默认值-->
<!--<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>-->
<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>
<!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
<clearOutputDirectory>true</clearOutputDirectory>
<protocArtifact>
com.google.protobuf:protoc:3.5.1:exe:${os.detected.classifier}
</protocArtifact> 3.1.0不报错
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
syntax = "proto3";
option java_package = "cn.springcloud.proto";
option java_outer_classname = "PersonModel";
message Person { //定义了一个消息
int32 id = 1;
string name = 2;
string email = 3;
}
/**
* Created by forezp on 2018/6/9.
*/
public class PersonUseCase {
public static void main(String[] args) {
PersonModel.Person forezp= PersonModel.Person.newBuilder()
.setId(1)
.setName("forezp")
.setEmail("miles02@163.com").build();
for(byte b : forezp.toByteArray()){
System.out.print(b);
}
System.out.println("\n" + "bytes长度" + forezp.toByteString().size());
System.out.println("===== forezp Byte 结束 =====");
System.out.println("===== forezp 反序列化生成对象开始 =====");
PersonModel.Person forezpCopy = null;
try {
forezpCopy = PersonModel.Person.parseFrom(forezp.toByteArray());
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
System.out.print(forezpCopy.toString());
System.out.println("===== forezp 反序列化生成对象结束 =====");
}
}
运行 main方法 ,即可做 序列化 ,反序列化
输出
8118610211111410112211226151091051081011154850644954514699111109
bytes长度27
===== forezp Byte 结束 =====
===== forezp 反序列化生成对象开始 =====
id: 1
name: "forezp"
email: "miles02@163.com"
===== forezp 反序列化生成对象结束 =====
采用 Proto Buffer 序列化 可读性很差,但是数据 体积很小
Netty:JBoss开源 的 一个 异步事件驱动的 Java 网络应用框架,协议服务器。
JBoss 是 J2EE的开放源代码的应用服务器
gRpc 的 Java版本 用 Netty 作为 NIO 框架
Netty 提高数据传输性能,因为:
早期 网络编程框架中,使用 阻塞 IO 来处理网络请求
while( (request = in.readLine())!= null ){
//XXXX
}
只能同时处理一个连接,要想处理多个客户端,要创建多个 ServeSocket
还要 重新创建一个线程 去处理 该请求,该线程会处于 阻塞状态
大多数 情况下,这些线程 处于阻塞状态。
NIO
<?xml version="1.0" encoding="UTF-8"?>
<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>cn.springcloud.book</groupId>
<artifactId>ch19-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>ch19-2</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- grpc版本 -->
<grpc.version>1.11.0</grpc.version>
<os.plugin.version>1.5.0.Final</os.plugin.version>
<!-- protobuf版本 -->
<protobuf.plugin.version>0.5.1</protobuf.plugin.version>
<protoc.version>3.5.1</protoc.version>
</properties>
<modules>
<module>grpc-lib-1</module>
<module>grpc-simple-server</module>
<module>grpc-simple-client</module>
</modules>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
</dependency><!-- netty -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency><!-- protobuf -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency><!-- stub -->
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os.plugin.version}</version>
</plugin><!-- os Maven 插件 -->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf.plugin.version}</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<overWriteReleases>false</overWriteReleases>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!--<plugin>-->
<!--<groupId>com.spotify</groupId>-->
<!--<artifactId>dockerfile-maven-plugin</artifactId>-->
<!--<version>1.2.2</version>-->
<!--<configuration>-->
<!--<repository>${docker.image.prefix}/${project.artifactId}</repository>-->
<!--<tag>latest</tag>-->
<!--</configuration>-->
<!--<executions>-->
<!--<execution>-->
<!--<phase>package</phase>-->
<!--<goals>-->
<!--<goal>build</goal>-->
<!--</goals>-->
<!--</execution>-->
<!--</executions>-->
<!--</plugin>-->
</plugins>
</pluginManagement>
</build>
</project>
<!-- grpc版本 -->
<grpc.version>1.11.0</grpc.version>
<os.plugin.version>1.4.1.Final</os.plugin.version>
<!-- protobuf版本 -->
<protobuf.plugin.version>0.5.0</protobuf.plugin.version>
<protoc.version>3.1.0</protoc.version> #不报错的版本
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
syntax = "proto3";
package cn.springcloud.grpc;
option java_multiple_files = true;
message HelloRequest {
string name = 1;
int32 age = 2;
repeated string hobbies = 3;
map<string, string> tags = 4;
}
message HelloResponse {
string greeting = 1;
}
service HelloService {
rpc hello(HelloRequest) returns (HelloResponse);
}
文件 创建了 helloRequest 和 HelloResponse 两个试题
创建了 helloService 服务,有 hello 服务
执行 mvn clean install 命令
<parent>
<groupId>cn.springcloud.book</groupId>
<artifactId>ch19-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>cn.springcloud.book</groupId>
<artifactId>grpc-lib-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
/**
* Email miles02@163.com
*
* @author fangzhipeng
* create 2018-06-11
**/
public class HelloService extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void hello(cn.springcloud.grpc.HelloRequest request,
io.grpc.stub.StreamObserver<cn.springcloud.grpc.HelloResponse> responseObserver) {
//打印request
System.out.println( request );
String greeting = "Hi " + request.getName() + " you are " + request.getAge() + " years old" +
" your hoby is " + (request.getHobbiesList()) + " your tags " + request.getTagsMap();
//生成 response
HelloResponse response = HelloResponse.newBuilder().setGreeting( greeting ).build();
//执行
responseObserver.onNext( response );
responseObserver.onCompleted();
}
}
public class HelloService extends HelloServiceGrpc.HelloServiceImplBase
public class MyGrpcServer {
static public void main(String[] args) throws IOException, InterruptedException {
//server 监听的端口为 8082 。并将 HelloServe 注册到里面去
Server server = ServerBuilder.forPort( 8082 )
.addService( new HelloService() )
.build();
System.out.println( "Starting server..." );
server.start();
System.out.println( "Server started!" );
server.awaitTermination();
}
}
public class MyGrpcClient {
public static void main(String[] args) throws InterruptedException {
//本地 8082端口,
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8082)
.usePlaintext()
.build();
//HelloService的通道
HelloServiceGrpc.HelloServiceBlockingStub stub =
HelloServiceGrpc.newBlockingStub(channel);
//请求为这些
HelloResponse helloResponse = stub.hello(
HelloRequest.newBuilder()
.setName("forezp")
.setAge(17)
.addHobbies("football").putTags( "how?","wonderful" )
.build());
//相依为:服务端的输出
System.out.println(helloResponse);
channel.shutdown();
}
}
greeting: "Hi forezp you are 17 years old your hoby is [football] your tags {how?=wonderful}"