Google高性能开源框架gRPC:快速搭建及HTTP/2抓包

一、什么是gRPC

gRPC是google发起的一个*远程过程调用(rpc)*开源框架,可以在任何语言中,用任何编程语言编写。gRPC基于HTTP/2协议,使用Protocol Buffers作为序列化工具。

gRPC官网:grpc.io/

RPC

Remote Procedure Call,远程过程调用协议,一种通过网络调用远程计算机上服务,并且无需关注交互细节。可以理解为,服务A调用另一个服务B中的某段程序,底层实现对于开发者无感知,可以是基于HTTP/1.1也可以基于HTTP/2,可以序列化成json,xml,Protocol Buffers这些都不需要关心。像Dubbo就是一个RPC框架,仅关心业务编程即可。

Protocol Buffers

Protocol Buffers是一个跨语言,跨平台可扩展的数据结构序列化的一个工具语言,和JSON类似,但比JSON更小,更高效。需要通过工具编译成指定语言的代码,相当于你定义的对象需要由工具生成。

HTTP/2

HTTP协议第二个版本,兼容HTTP/1.1(目前广泛使用的仍然是HTTP/1.1),基于SPDY协议,于2015年2月17日被批准。

特性如下:

  1. 头部压缩:使用HPACK算法对头部进行压缩
  2. 对数据传输采用多路复用,让多个请求合并在同一TCP连接内。
  3. 服务端主动推送消息

二、简单实践

文件生成

因为gRPC基于Protocol Buffers,需要通过工具来生成。

一种完全无依赖的方式是自己下载软件,如果要使用gRPC需要额外下载protoc-gen-grpc-java

proto地址:github.com/protocolbuf...

protoc-gen-grpc-java地址:repo.maven.apache.org/maven2/io/g...

配置了好久没有配置成功,然后用了其他方案,maven插件的方式

xml 复制代码
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.21.5:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.48.1:exe:${os.detected.classifier}</pluginArtifact>
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                    <!-- 生成的Java文件目录 -->
                    <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
                    <clearOutputDirectory>false</clearOutputDirectory>

                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>

服务端实现

生成的文件部分就不占用过多篇幅了

仓库地址:gitee.com/Nortyr/alli...

这个是服务端实现,其中doubleStream我测试接收stream,返回stream

java 复制代码
public class ServiceImpl extends GreeterGrpc.GreeterImplBase{
  //...略
    @Override
    public StreamObserver<Helloworld.HelloRequest> doubleStream(StreamObserver<Helloworld.HelloReply> responseObserver) {
        return new StreamObserver<Helloworld.HelloRequest>() {
            AtomicInteger integer=new AtomicInteger();

            @Override
            public void onNext(Helloworld.HelloRequest helloRequest) {
                System.out.println(helloRequest.getMessage());

                Helloworld.HelloReply response = Helloworld.HelloReply.newBuilder()
                        .setMessage("瞅你咋地~~"+integer.incrementAndGet())
                        .build();
                responseObserver.onNext(response);
            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println("error: " + throwable.getMessage());

            }

            @Override
            public void onCompleted() {
                System.out.println("Server completed");
                responseObserver.onCompleted();
            }
        };
    }
}
  • 服务端代码:
java 复制代码
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        int port = 9091;
        Server server = ServerBuilder
                .forPort(port)
                .addService(new ServiceImpl())
                .build()
                .start();
        System.out.println("server started, port : " + port);
        server.awaitTermination();
    }
}
  • 客户端代码:
java 复制代码
     private static void testDoubleStream() throws InterruptedException {
            String host = "127.0.0.1";
            int port = 9091;
            ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();

    //        client接收一个对象
            GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);


            StreamObserver<Helloworld.HelloRequest> doubleStream = stub.doubleStream(new StreamObserver<Helloworld.HelloReply>() {

                @Override
                public void onNext(Helloworld.HelloReply helloReply) {
                    System.out.println("Received: " + helloReply.getMessage());
                }

                @Override
                public void onError(Throwable throwable) {
                    System.out.println("error: " + throwable);
                }

                @Override
                public void onCompleted() {
                    System.out.println("Client completed");
                }
            });
            doubleStream.onNext(Helloworld.HelloRequest.newBuilder().setMessage("你瞅啥~~ 1").build());
            doubleStream.onNext(Helloworld.HelloRequest.newBuilder().setMessage("你瞅啥~~ 2").build());
            doubleStream.onNext(Helloworld.HelloRequest.newBuilder().setMessage("你瞅啥~~ 3").build());
            doubleStream.onCompleted();
            Thread.sleep(10000);
            channel.shutdown();
        }
  • 启动结果如下:

抓包分析

还没见过HTTP/2报文,想看下,发现全是TCP

需要修改下,使用http2解析

如果想要看到内容需要配置下ProtoBuf文件位置 Wireshark>Perferences>Protocols>ProtoBuf

至此over~~~

结尾

相关推荐
Leo2824 小时前
异步任务链路如何不断链:基于 OpenTelemetry 的 Trace 设计
后端
技术长镜头4 小时前
别再死记 Record、Gap、Next-Key:沿一条 SQL 看懂 InnoDB 锁
后端·mysql
晚安code4 小时前
Java四大函数式接口一篇讲透:配上Stream流式计算处理集合
后端
晴殇i4 小时前
最近在 Github 名字叫“马尾辫”,这个真的很有趣看到头像
前端·后端·开源
IT_陈寒4 小时前
Vite打包时静态资源404?加个斜杠就能解决
前端·人工智能·后端
evans在进步4 小时前
LeetCode 17:电话号码的字母组合——Java DFS 回溯法详解
java·leetcode·深度优先
2401_850481174 小时前
UVA10391
java
程序员爱钓鱼4 小时前
Go 输入输出详解
后端·面试·go
UQR4 小时前
一、Java基础高频面试题
java·开发语言
AC赳赳老秦4 小时前
网页公开附件自动采集:OpenClaw 批量下载页面内嵌 Word/Excel 附件,统一格式后结构化入库
java·python·word·php·excel·deepseek·openclaw