谷歌开源远程进程调用框架,支持多语言系统间通信,适用于各种分布式系统,使用http2协议并使用protobuf系列化通信数据,高性能。nacos2开始也集成了grpc,用于nacos server与nacos client间通信。grpc还支持了client-server双向流,两个流可独立不阻塞进行连续读写。
如果只是protobuf作为序列化方案,建议使用protostuff(基于protobuf),不用写proto文件。grpc官方的quickstart都是直接使用protobuf,故这里暂不研究是否有grpc+protostuff方案。Java 有maven插件进行proto文件生成Java文件,故不用单独去安装proto了,但proto基本语法还得了解。
官方的quickstart不是基于springboot的,故这里就参考这位大佬的JAVA使用gRPC
,为方便使用,这里server,client都在同一个工程里。如果要分开,则在独立项目中引入grpc-client-spring-boot-starter
等依赖并,并copy需要的类com.example.demo.protogen.UserServiceGrpc,com.example.demo.protogen.User
等。
proto里放file.proto,message.proto
文件如下
syntax = "proto3";
package protogen;
option java_package = "com.example.demo.protogen";
message File {
string name = 1;
int32 size = 2;
}
syntax = "proto3";
package protogen;
import "file.proto";
option java_multiple_files = true;
option java_package = "com.example.demo.protogen";
message User {
reserved 6 to 7;
reserved "userId2";
int32 userId = 1;
string username = 2;
oneof msg {
string error = 3;
int32 code = 4;
}
string name = 8;
UserType userType = 9;
repeated int32 roles = 10;
protogen.File file = 11;
map hobbys = 12;
}
enum UserType {
UNKNOW = 0;
ADMIN = 1;
BUSINESS_USER = 2;
};
service UserService {
rpc getUser (User) returns (User) {}
rpc getUsers (User) returns (stream User) {}
rpc saveUsers (stream User) returns (User) {}
}
service FileService {
rpc getFile(User) returns(File) {}
}
protogen里文件都是生成的,插件配置了读取这个目录,并生成到protogen文件夹里。通过点击如图插件按钮实现,protobuf:compile
实际是通过proto.exe将.proto文件生成Java文件,除了FileServiceGrpc,UserServiceGrpc
是protobuf:compile-custom
生成的,其余都是protobuf:compile
生成的。
UserServiceImpl.java
package com.example.demo.grpc.server;
import com.example.demo.protogen.User;
import com.example.demo.protogen.UserServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
/**
* @author Kone
* @date 2022/1/29
*/
@GrpcService
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
@Override
public void getUser(User request, StreamObserver<User> responseObserver) {
System.out.println(request);
User user = User.newBuilder()
.setName("response name")
.build();
responseObserver.onNext(user);
responseObserver.onCompleted();
}
@Override
public void getUsers(User request, StreamObserver<User> responseObserver) {
System.out.println("get users");
System.out.println(request);
User user = User.newBuilder()
.setName("user1")
.build();
User user2 = User.newBuilder()
.setName("user2")
.build();
responseObserver.onNext(user);
responseObserver.onNext(user2);
responseObserver.onCompleted();
}
@Override
public StreamObserver<User> saveUsers(StreamObserver<User> responseObserver) {
return new StreamObserver<User>() {
@Override
public void onNext(User user) {
System.out.println("get saveUsers list ---->");
System.out.println(user);
}
@Override
public void onError(Throwable throwable) {
System.out.println("saveUsers error " + throwable.getMessage());
}
@Override
public void onCompleted() {
User user = User.newBuilder()
.setName("saveUsers user1")
.build();
responseObserver.onNext(user);
responseObserver.onCompleted();
}
};
}
}
springboot3有点问题,暂用2.7.9版本springboot
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.7.9
com.example
demo
0.0.1-SNAPSHOT
demo
Demo project for Spring Boot
17
3.23.4
1.26.0
com.google.protobuf
protobuf-java
${protobuf.version}
net.devh
grpc-server-spring-boot-starter
2.14.0.RELEASE
net.devh
grpc-client-spring-boot-starter
2.14.0.RELEASE
org.projectlombok
lombok
1.18.22
true
org.springframework.boot
spring-boot-starter-test
kr.motd.maven
os-maven-plugin
1.6.2
org.xolstice.maven.plugins
protobuf-maven-plugin
0.6.1
com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
grpc-java
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
${project.basedir}/src/main/java/com/example/demo/proto
${project.basedir}/src/main/java
false
compile
compile-custom
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
org.apache.maven.plugins
maven-compiler-plugin
17
package com.example.demo;
import com.example.demo.protogen.User;
import com.example.demo.protogen.UserServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import java.util.Iterator;
public class FramelessGrpcClient {
public static void main(String[] args) {
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9090).usePlaintext().build();
UserServiceGrpc.UserServiceBlockingStub userService = UserServiceGrpc.newBlockingStub(managedChannel);
User user = User.newBuilder()
.setUserId(100)
.putHobbys("pingpong", "play pingpong")
.setCode(200)
.build();
System.out.println("get response-------->");
System.out.println(userService.getUser(user));
Iterator<User> users = userService.getUsers(user);
}
}
package com.example.demo;
import com.example.demo.protogen.User;
import com.example.demo.protogen.UserServiceGrpc;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Iterator;
/**
* TODO
*
* @author majun
* @version 1.0
* @since 2023-08-02 20:19
*/
@Component
@EnableScheduling
public class SpringbootGrpcClient {
@GrpcClient("userClient")
private UserServiceGrpc.UserServiceBlockingStub userService;
@Scheduled(fixedDelay = 10000)
public void test() {
User user = User.newBuilder()
.setUserId(100)
.putHobbys("pingpong", "play pingpong")
.setCode(200)
.build();
System.out.println("get response-------->");
System.out.println(userService.getUser(user));
Iterator<User> users = this.userService.getUsers(user);
while (users.hasNext()) {
System.out.println(users.next());
}
}
}