一.gRPC 是个啥,能干啥?
在java的世界里,gRPC就类似于微服务中的@FeignClient一样,调用另一台机器上的服务接口,就像调用本地方法一样的效果。but grpc 有这独有的优势:1.跨语言 2.由于使用Protocol Buffers(使用二进制流传输)通过序列化和反序列化,提升传输效率。
截取官网上的图,可形象得看出来grpc的好处。
二.使用java spring 示例:
1.新建spring工程,添加pom依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.12.0</version>
</dependency>
2.引入打包插件
<build>
<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.0.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
3.新建proto文件,定义交换数据的接口,请求参数,相应参数
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.grpc";
option java_outer_classname = "MyGrpc";
option objc_class_prefix = "QB";
package grpc;
//定义服务接口
service Greeter {
//注意:这里是returns 不是return
rpc remoteMethod (Request) returns (Response) {
}
}
//定义参数类型
message Request {
string sendMessage = 1;
}
message Response {
string backMessage = 1;
}
备注:proto文件需要在java同级目录下
4.客户端代码(模拟请求)
package com.grpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
public class Client {
private static final Logger logger = LoggerFactory.getLogger(Client.class);
private final ManagedChannel channel;
private final GreeterGrpc.GreeterBlockingStub greeterBlockingStub;
private static final String IP = "127.0.0.1";
private static final int PORT = 13000;
public static void main(String[] args) throws Exception {
Client client = new Client(IP, PORT);
for (int i = 0; i <= 10; i++) {
client.requestServer("client->" + i);
logger.info("我是客户端,我正在发送第【 {} 】条消息", i);
Thread.sleep(3000);
}
client.shutdown();
}
public Client(String ip, int port) {
//channel 表示通信通道
channel = ManagedChannelBuilder.forAddress(ip, port).usePlaintext().build();
greeterBlockingStub = GreeterGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(10, TimeUnit.SECONDS);
}
public void requestServer(String sendMessage) {
Request request = Request.newBuilder().setSendMessage(sendMessage).build();
Response response = greeterBlockingStub.remoteMethod(request);
logger.info("服务端返回消息:{}", response.getBackMessage());
}
}
5.服务端代码(模拟相应)
package com.grpc;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class Server {
private static final Logger logger = LoggerFactory.getLogger(Server.class);
private static final int PORT = 13000;
private io.grpc.Server grpcServer;
public static void main(String[] args) throws IOException, InterruptedException {
final Server server = new Server();
server.start();
server.blockUntilShutdown();
}
//启动服务
private void start() throws IOException {
grpcServer = ServerBuilder.forPort(PORT).addService(new MyGrpcImpl()).build().start();
System.out.println("--------gRPC 服务启动完毕-------");
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.err.println("------ gRPC 服务器正在关闭 -------");
Server.this.stop();
System.err.println("------ gRPC 已经关闭 ------");
}
});
}
//stop服务
private void stop() {
if (grpcServer != null) {
grpcServer.shutdown();
}
}
//阻塞到程序退出
private void blockUntilShutdown() throws InterruptedException {
if (grpcServer != null) {
grpcServer.awaitTermination();
}
}
//服务接口
private class MyGrpcImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void remoteMethod(Request request, StreamObserver<Response> responseObserver) {
String backMsg = "服务端已经收到消息:" + request.getSendMessage();
Response build = Response.newBuilder().setBackMessage(backMsg).build();
logger.info("服务端接受消息 : {} ", request.getSendMessage());
logger.info("服务端返回消息: {}", backMsg);
//客户端返回结果
responseObserver.onNext(build);
//结束本次调用
responseObserver.onCompleted();
}
}
}
6.idea 装protobuf插件
7.maven 编译工程。
8.先启动服务端,再启动客户端,进行通信
客户端:
服务端: