刨根问底系列之 grpc-java 入门
作者:零点999
- 2022-12-26 北京
本文字数:5963 字
阅读完需:约 20 分钟
介绍
google 开源的高性能且可以运行在任何环境的远程调用框架
gRPC-Java 支持 Java 8 及更高版本。
GPPC 背后的故事
是 google 出品
谷歌一直使用名为 Stubby 的单一通用 RPC 基础设施来连接在其数据中心内和跨数据中心运行的大量微服务
2015 年 3 月,决定构建下一代版本 Stubby 并且开源,改名为 grpc,
使用者
Square
Netflix
Core os
Juniper networks
cisco
优点
支持可插拔的身份验证、跟踪、负载平衡和健康检查
可以跨平台,支持多种语言(11 种语言)
基于 http/2 传输的双向流式传输
使用 proto3 生成指定语言的数据结构、服务端接口以及客户端 Stub;
缺点
grpc 生态相对于 RESTful 还是比较小,因为浏览器和移动端对 grpc 支持 依然在初级阶段
grpc 不太直接适合面向外部通信,强类型来说有更多约束,向外提供接口的解决方案是配合网关使用
参考 https://zhuanlan.zhihu.com/p/436034072
例子
mvn 定义
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.google.grpc</groupId> <artifactId>grpc-java-learning</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>grpc-java-learning</name> <url>http://maven.apache.org</url>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <os.detected.classifier>osx-x86_64</os.detected.classifier>
<protoc.version>3.21.7</protoc.version> <grpc.version>1.51.1</grpc.version>
<!-- required for JDK 8 --> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty-shaded</artifactId> <version>${grpc.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>${grpc.version}</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>${grpc.version}</version> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>3.21.7</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.9.0</version> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency>
</dependencies>
<build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.2</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} </protocArtifact> <clearOutputDirectory>false</clearOutputDirectory> <outputDirectory>src/main/java</outputDirectory> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} </pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.4.1</version> <executions> <execution> <id>enforce</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requireUpperBoundDeps/> </rules> </configuration> </execution> </executions> </plugin> </plugins> </build>
</project>复制代码
定义 protobuf 的协议类
syntax = "proto3";
option java_multiple_files = true;option java_package = "com.google.grpc.learning.helloworld";option java_outer_classname = "HelloWorldProto";option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.service Greeter { // Sends a greeting rpc 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;}
复制代码
生成 java 类
mvn -U clean compile
复制代码
服务提供者代码
package com.google.grpc.learning.helloworld.server;
import com.google.grpc.learning.helloworld.GreeterGrpc;import com.google.grpc.learning.helloworld.HelloReply;import com.google.grpc.learning.helloworld.HelloRequest;import io.grpc.Grpc;import io.grpc.InsecureServerCredentials;import io.grpc.Server;import io.grpc.stub.StreamObserver;
import java.io.IOException;import java.util.concurrent.TimeUnit;
/** * Server that manages startup/shutdown of a {@code Greeter} server. */public class HelloWorldServer {
private Server server;
private void start() throws IOException { /* The port on which the server should run */ int port = 50051; server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create()) .addService(new GreeterImpl()) .build() .start(); System.out.println("Server started, listening on " + port); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { // Use stderr here since the logger may have been reset by its JVM shutdown hook. System.err.println("*** shutting down gRPC server since JVM is shutting down"); try { HelloWorldServer.this.stop(); } catch (InterruptedException e) { e.printStackTrace(System.err); } System.err.println("*** server shut down"); } }); }
private void stop() throws InterruptedException { if (server != null) { server.shutdown().awaitTermination(30, TimeUnit.SECONDS); } }
/** * Await termination on the main thread since the grpc library uses daemon threads. */ private void blockUntilShutdown() throws InterruptedException { if (server != null) { server.awaitTermination(); } }
/** * Main launches the server from the command line. */ public static void main(String[] args) throws IOException, InterruptedException { final HelloWorldServer server = new HelloWorldServer(); server.start(); server.blockUntilShutdown(); }
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } }}
复制代码
消费者代码
package com.google.grpc.learning.helloworld.client;
import com.google.grpc.learning.helloworld.GreeterGrpc;import com.google.grpc.learning.helloworld.HelloReply;import com.google.grpc.learning.helloworld.HelloRequest;import com.google.grpc.learning.helloworld.server.HelloWorldServer;import io.grpc.Channel;import io.grpc.Grpc;import io.grpc.InsecureChannelCredentials;import io.grpc.ManagedChannel;import io.grpc.StatusRuntimeException;
import java.util.concurrent.TimeUnit;
/** * A simple client that requests a greeting from the {@link HelloWorldServer}. */public class HelloWorldClient {
private final GreeterGrpc.GreeterBlockingStub blockingStub;
/** Construct client for accessing HelloWorld server using the existing channel. */ public HelloWorldClient(Channel channel) { // 'channel' here is a Channel, not a ManagedChannel, so it is not this code's responsibility to // shut it down.
// Passing Channels to code makes code easier to test and makes it easier to reuse Channels. blockingStub = GreeterGrpc.newBlockingStub(channel); }
/** Say hello to server. */ public void greet(String name) { System.out.println("Will try to greet " + name + " ..."); HelloRequest request = HelloRequest.newBuilder().setName(name).build(); HelloReply response; try { response = blockingStub.sayHello(request); } catch (StatusRuntimeException e) { System.out.println( "RPC failed: "+ e.getStatus()); return; } System.out.println("Greeting: " + response.getMessage()); }
/** * Greet server. If provided, the first element of {@code args} is the name to use in the * greeting. The second argument is the target server. */ public static void main(String[] args) throws Exception { String user = "world"; // Access a service running on the local machine on port 50051 String target = "localhost:50051"; // Allow passing in the user and target strings as command line arguments if (args.length > 0) { if ("--help".equals(args[0])) { System.err.println("Usage: [name [target]]"); System.err.println(""); System.err.println(" name The name you wish to be greeted by. Defaults to " + user); System.err.println(" target The server to connect to. Defaults to " + target); System.exit(1); } user = args[0]; } if (args.length > 1) { target = args[1]; }
ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create()) .build(); try { HelloWorldClient client = new HelloWorldClient(channel); client.greet(user); } finally { // ManagedChannels use resources like threads and TCP connections. To prevent leaking these // resources the channel should be shut down when it will no longer be used. If it may be used // again leave it running. channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS); } }}
复制代码
代码位置:https://github.com/bee06/grpc-java-learning后面我们会根据例子的代码一步一步 debeg 看看内部的逻辑
参考资料
划线
评论
复制
发布于: 刚刚阅读数: 3
零点999
关注
还未添加个人签名 2018-01-19 加入
持续输出








评论