gRpc是google开源的一个高性能、跨语言的rpc框架,基于HTTP2协议,基于protobuf 3.x;对于开发者,使用gRpc需要做的事情:
1>使用protobuf定义接口,即.proto文件
2>compile生成特定语言的代码,比如JAVA,Python等,解决跨语言的问题。
3>服务端实现上述生成的接口,然后启动,等待客户端进行连接;
4>启动一个或者多个客户端,与service建立连接并发送请求;request和response都被封装成Http2的stream Frame,通过channel进行交互;
SpringBoot提供了grpc-spring-boot-starter对gRpc进行集成;具体的代码地址https://github.com/xiaoguangtouqiang/grpc-demo.git
项目目录结构如图
grpc-lib存放定义的proto文件,作为公共的依赖,给grpc-client和grpc-server调用;
1>创建grpc-lib文件夹,新建目录src/main/proto,再下面新建helloworld.proto文件,代码如下
syntax = "proto3";
option java_multiple_files = true;
//定义输出的目录,生成的目录就是“net/devh/examples/grpc/lib”下面
option java_package = "net.devh.examples.grpc.lib";
//定义输出的文件名称,生成在lib下的就是HelloWorldProto.class
option java_outer_classname = "HelloWorldProto";
// The greeting service definition.
//定义的接口的类,这里会生成一个SimpleGrpc.class,服务端需要来实现的
service Simple {
//定义接口方法
rpc SayHello (HelloRequest) returns (HelloReply) {
}
}
//请求参数
message HelloRequest {
string name = 1;
}
//返回结果
message HelloReply {
string message = 1;
}
然后创建build.gradle,需要添加protobuf将上面的文件编译成java代码,具体内容如下
apply plugin: 'java'
apply plugin: 'com.google.protobuf'
apply plugin: 'idea'
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
compile "io.grpc:grpc-netty:1.10.0"
compile "io.grpc:grpc-protobuf:1.10.0"
compile "io.grpc:grpc-stub:1.10.0"
}
protobuf {
protoc {
// The artifact spec for the Protobuf Compiler
artifact = 'com.google.protobuf:protoc:3.0.0'
}
plugins {
// Optional: an artifact spec for a protoc plugin, with "grpc" as
// the identifier, which can be referred to in the "plugins"
// container of the "generateProtoTasks" closure.
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2'
}
}
generateProtoTasks {
ofSourceSet('main')*.plugins {
// Apply the "grpc" plugin whose spec is defined above, without
// options. Note the braces cannot be omitted, otherwise the
// plugin will not be added. This is because of the implicit way
// NamedDomainObjectContainer binds the methods.
grpc { }
}
}
}
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.4'
}
}
然后执行gradle compileJava生成对应的java代码,生成的结果如图所示
2>服务端实现
通过start.spring.io生成springBoot的服务端,build.gradle文件添加依赖项,代码如下
buildscript {
ext {
springBootVersion = '2.0.2.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile 'net.devh:grpc-server-spring-boot-starter:1.4.0.RELEASE'
//注意,需要依赖grpc-lib项目
compile project(':grpc-lib')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
buildscript {
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:0.8.4")
}
}
然后创建GrpcServerService实现上面的接口,代码如图所示
package com.example.gRpc;
import io.grpc.stub.StreamObserver;
import net.devh.examples.grpc.lib.HelloReply;
import net.devh.examples.grpc.lib.HelloRequest;
import net.devh.examples.grpc.lib.SimpleGrpc;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;
@GrpcService(SimpleGrpc.class)
public class GrpcServerService extends SimpleGrpc.SimpleImplBase{
@Override
public void sayHello(HelloRequest req, StreamObserver responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello =============> " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
另外,需要配置rpc服务端的名称,端口等信息,application.properties配置如图
#服务端名称
spring.application.name=local-grpc-server
#服务端运行端口
server.port=8888
#grpc通信端口
grpc.server.port=9898
3>客户端
与服务端类似,build.gradle文件添加依赖
buildscript {
ext {
springBootVersion = '2.0.2.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile project(':grpc-lib')
compile("net.devh:grpc-client-spring-boot-starter:1.4.0.RELEASE")
compile('org.springframework.boot:spring-boot-starter-web')
}
然后创建GrpcClientService,调用服务端提供的接口,代码如下
package com.example.gRpcclient;
import io.grpc.Channel;
import net.devh.examples.grpc.lib.HelloReply;
import net.devh.examples.grpc.lib.HelloRequest;
import net.devh.examples.grpc.lib.SimpleGrpc;
import net.devh.springboot.autoconfigure.grpc.client.GrpcClient;
import org.springframework.stereotype.Service;
@Service
public class GrpcClientService {
@GrpcClient("local-grpc-server")
private Channel serverChannel;
public String sendMessage(String name) {
SimpleGrpc.SimpleBlockingStub stub = SimpleGrpc.newBlockingStub(serverChannel);
HelloReply response = stub.sayHello(HelloRequest.newBuilder().setName(name).build());
return response.getMessage();
}
}
application.properties中配置grpc服务端的信息
server.port=8080
spring.application.name=local-grpc-client
grpc.client.local-grpc-server.host=127.0.0.1
grpc.client.local-grpc-server.port=9898
grpc.client.local-grpc-server.enableKeepAlive=true
grpc.client.local-grpc-server.keepAliveWithoutCalls=true
最后写个简单的请求来测试下
package com.example.gRpcclient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GrpcClientController {
@Autowired
private GrpcClientService grpcClientService;
@RequestMapping("/")
public String printMessage(@RequestParam(defaultValue = "Michael") String name) {
return grpcClientService.sendMessage(name);
}
}
运行结果如图所示
参考内容:
https://github.com/yidongnan/grpc-spring-boot-starter/blob/master/README-zh.md
https://blog.csdn.net/qq_28423433/article/details/79108976
https://blog.csdn.net/lyjshen/article/details/52238234
protobuf-gradle-plugin