文件名称 | 版本号 | 作者 | 版本 | |
---|---|---|---|---|
问道gRPC | v1.0.0 | 学生宫布 | 8416837 | net-devh-grpc.version 2.7.0.RELEASE grpc.version 1.29.0 protobuf.version 3.4.0 |
Google的孩子
进程通信
go version
protoc --version
数据格式Protobuf
查看我写的protobuf教程
一个简单的proto文件
syntax = 'proto3';
package proto;
message Human {
int32 age = 1;
string name = 2;
int32 sex = 3;
}
安装编译插件
go get -u github.com/golang/protobuf/protoc-gen-go
进入该文件目录使用gitbash编译该文件
protoc --go_out=. --python_out=. fruit.proto
编译完毕,说明插件安装成功:
grpc提供的原生接口服务无法被http模式访问
<plugin>
<groupId>org.xolstice.maven.pluginsgroupId>
<artifactId>protobuf-maven-pluginartifactId>
<version>0.5.0version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
protocArtifact>
<pluginId>grpc-javapluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}pluginArtifact>
<protoSourceRoot>${project.basedir}/src/main/protoprotoSourceRoot>
<outputDirectory>${project.basedir}/src/main/javaoutputDirectory>
<clearOutputDirectory>falseclearOutputDirectory>
configuration>
<executions>
<execution>
<goals>
<goal>compilegoal>
<goal>compile-customgoal>
goals>
execution>
executions>
plugin>
<properties>
<grpc.version>1.29.0grpc.version>
<os.detected.classifier>windows-x86_64os.detected.classifier>
<net-devh-grpc.version>2.7.0.RELEASEnet-devh-grpc.version>
properties>
syntax = "proto3"; // 版本号。与proto2差别不大
option java_package = "test.pro.domain";
option java_outer_classname = "HumanDomain";
// 简单定义一个rpc服务和一个接口 定义了接口的输入输出 而输入输出都在下述结构体
service TheFirstRpc {
rpc SayHello ( HelloParams) returns ( Human ) {}
}
message HelloParams { // 类结构体
string name = 1;
}
message Human { // 类结构体
int32 id = 1; // 结构体属性
int32 sex = 2; // 数字作为key,省空间。不一定要连续
string age = 3;
}
<properties>
<protobuf.version>3.4.0protobuf.version>
... ...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.protobufgroupId>
<artifactId>protobuf-javaartifactId>
<version>${protobuf.version}version>
dependency>
<dependency>
<groupId>io.grpcgroupId>
<artifactId>grpc-allartifactId>
<version>${grpc.version}version>
dependency>
子项目
<dependency>
<groupId>com.google.protobufgroupId>
<artifactId>protobuf-javaartifactId>
dependency>
<dependency>
<groupId>io.grpcgroupId>
<artifactId>grpc-allartifactId>
dependency>
grpc:
server:
port: 9080 # 不配置默认9090
服务端引入依赖包
<net-devh-grpc.version>2.7.0.RELEASEnet-devh-grpc.version>
<dependency>
<groupId>net.devhgroupId>
<artifactId>grpc-client-spring-boot-starterartifactId>
<version>${net-devh-grpc.version}version>
dependency>
<dependency>
<groupId>net.devhgroupId>
<artifactId>grpc-server-spring-boot-starterartifactId>
<version>${net-devh-grpc.version}version>
dependency>
前提是服务端和客户端都引入RPC相关Java类
上一步只是编译了RPC结构,并未实现它。因此,可以在服务端(提供者)编写实现代码,以备客户端(消费者)调用。
注意:有些类的名字改成你自己的。这些类主要与proto关联。
package test.rpc;
/**
* 功能:rpc实现
*
* @author: cc
* @qq: 8416837
* @date: 2020/5/17 15:48
*/
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import test.pro.domain.HumanDomain;
import test.pro.domain.TheFirstRpcGrpc;
@Slf4j
@GrpcService
public class HelloService extends TheFirstRpcGrpc.TheFirstRpcImplBase {
@Override
public void sayHello(HumanDomain.HelloParams request, StreamObserver<HumanDomain.Human> responseObserver) {
String name = request.getName();
log.debug("{} === {}", "[请求参数]", request);
final HumanDomain.Human.Builder replyBuilder = HumanDomain.Human.newBuilder().setSex(1).setAge(18).setName(name);
responseObserver.onNext(replyBuilder.build());
responseObserver.onCompleted();
}
}
# grpc
grpc:
client:
TheFirstRpc: # 服务名称
address: static://localhost:9080
negotiationType: plaintext
# 服务
# GLOBAL:
# address: static://localhost:9080 // 服务端的端口号
# negotiation-type: plaintext
@GrpcClient("TheFirstRpc")
private TheFirstRpcGrpc.TheFirstRpcBlockingStub theFirstRpcBlockingStub;
@GetMapping("/grpc/{name}")
public Object sayHello(@PathVariable("name") String name) throws InterruptedException {
// 服务端默认ip是微服务ip,端口是9090
HumanDomain.Human response = theFirstRpcBlockingStub.sayHello(HumanDomain.HelloParams.newBuilder().setName(name).build());
String resStr = response.toString();
return resStr;
}
使用REST API触发客户端调用服务端RPC,即可完成调用,原理见上述代码
把RPC调用结果toString后再返回,避免REST Json返回响应时报错。按上述代码,实操调用成功。
报错:
io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:244) ~[grpc-stub-1.29.0.jar:1.29.0]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
解决办法:开启服务