基本概念
gRPC具有以下特点:
(1)基于 HTTP/2, 继而提供了连接多路复用、Body 和 Header 压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。
(2)支持主流开发语言(C, C++, Python, PHP, Ruby, NodeJS, C#, Objective-C、Golang、Java)
(3)IDL (Interface Definition Language) 层使用了 Protocol Buffers, 非常适合团队的接口设计
HelloWorld实例详解
gRPC的使用通常包括如下几个步骤:
通过protobuf来定义接口和数据类型
编写gRPC server端代码
编写gRPC client端代码
编写helloworld.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.manong.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;// The greeting service definition.service Greeter {// Sends a greetingrpc SayHello (HelloRequest) returns (HelloReply) {}
}// The request message containing the user's name.message HelloRequest {string name = 1;}// The response message containing the greetingsmessage HelloReply {string message = 1;}
Maven配置
3.12.03.12.01.31.1io.grpcgrpc-bom1.31.1pomimportio.grpcgrpc-protobufio.grpcgrpc-stubio.grpcgrpc-servicesio.grpcgrpc-netty-shadedruntimekr.motd.mavenos-maven-plugin1.6.2org.xolstice.maven.pluginsprotobuf-maven-plugin0.6.1com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}grpc-javaio.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}compilecompile-customorg.apache.maven.pluginsmaven-enforcer-plugin1.4.1enforceenforce
运行maven插件中下面命令,根据proto生成源代码
项目target下生成如下代码,实际项目上线后可以把该代码copy到对应src下面,把target下面的源码删除掉,这样也不用每次用maven中plugin去再生成代码。
Server端代码
import com.manong.grpc.helloworld.GreeterGrpc;
import com.manong.grpc.helloworld.HelloReply;
import com.manong.grpc.helloworld.HelloRequest;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HostnameServer extends GreeterGrpc.GreeterImplBase {private static final Logger logger = Logger.getLogger(HostnameServer.class.getName());
private final String serverName;
public HostnameServer(String serverName) {if (serverName == null) {
serverName = determineHostname();}this.serverName = serverName;}@Overridepublic void sayHello(HelloRequest req, StreamObserver responseObserver) {
HelloReply reply = HelloReply.newBuilder()
.setMessage("Hello , " + req.getName() + ", from " + serverName)
.build();responseObserver.onNext(reply);responseObserver.onCompleted();}private static String determineHostname() {try {return InetAddress.getLocalHost().getHostName();} catch (IOException ex) {logger.log(Level.INFO, "Failed to determine hostname. Will generate one", ex);}// Strange. Well, let's make an identifier for ourselves.return "generated-" + new Random().nextInt();}public void init() throws Exception {int port = 50051;String hostname = "0.0.0.0";
final Server server = ServerBuilder.forPort(port)
.addService(this)
.build()
.start();System.out.println("Listening on port " + port);Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {server.shutdown();
try {if (!server.awaitTermination(30, TimeUnit.SECONDS)) {server.shutdownNow();server.awaitTermination(5, TimeUnit.SECONDS);}
} catch (InterruptedException ex) {server.shutdownNow();}
}
});server.awaitTermination();}public static void main(String[] args) throws Exception {
HostnameServer hostnameServer = new HostnameServer("grpc server");hostnameServer.init();}
}
运行Server,出现如下输出表示Server已经正常启动
Client端代码
import com.manong.grpc.helloworld.GreeterGrpc;
import com.manong.grpc.helloworld.HelloReply;
import com.manong.grpc.helloworld.HelloRequest;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class HostnameClient {public static void main(String[] args) {
String target = "localhost:50051";ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build();
try {
GreeterGrpc.GreeterBlockingStub greeterBlockingStub = GreeterGrpc.newBlockingStub(channel);//传参HelloRequest defaultInstance = HelloRequest.newBuilder().setName("manong").build();HelloReply helloReply = greeterBlockingStub.sayHello(defaultInstance);System.out.println(helloReply.getMessage());} catch (Exception e) {
e.printStackTrace();}
}
}
运行client端代码,出现如下输出,表示调用server服务成功并获得返回值
到此为止,一个完整的基于Java的gRpc demo就完成了。想了解更多可以猛击https://grpc.io/