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

news/2024/7/10 20:35:43 标签: 开源, rpc, java

一、什么是gRPC

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

gRPC官网:https://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地址:https://github.com/protocolbuffers/protobuf/releases/tag/v24.3

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

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

        <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>

服务端实现

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

仓库地址:https://gitee.com/Nortyr/allinone

这个是服务端实现,其中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();
    }
}
  • 客户端代码:
 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~~~

结尾

  • 仓库地址:https://gitee.com/Nortyr/allinone/tree/main/grpc_demo
  • 参考资料
    • https://grpc.io/
    • https://protobuf.dev/
    • https://zh.wikipedia.org/wiki/HTTP/2
    • https://blog.csdn.net/luo15242208310/article/details/122909827

http://www.niftyadmin.cn/n/5033597.html

相关文章

ElasticSearch 因为索引字段改变,平滑迁移索引

问题&#xff1a; 某个索引创建时&#xff0c;没有按照想要的mapping,进行创建。 有个字段是text&#xff0c;不是想要的keyWord 此时需要重新按照mapping创建新索引&#xff0c;并迁移数据&#xff0c; 一、不使用别名的方式迁移 1. 创建新索引&#xff1a; 使用 Elastics…

SadTalker 让图片说话

参考&#xff1a;https://github.com/OpenTalker/SadTalker 其他类似参考&#xff1a;https://www.d-id.com/ 输入图片加音频产生2d视频 安装使用 1、拉取github&#xff0c;下载对应安装库 2、下载对应模型baidu网盘 新建checkpoints&#xff0c;把下载sadtalker里模型拷贝进…

Python文件操作指南:从基础到高级

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 文件操作是Python编程中…

中外超市纷争“到家”13年 永辉盒马山姆谁也不服谁

59岁的侯毅&#xff0c;需要一次机会&#xff0c;向刘强东、向张勇&#xff0c;还有马云证明盒马的可能。 日前&#xff0c;盒马香港IPO意外“搁置”&#xff0c;无形之中给国内零售市场再次增添了一丝寒意。 近几年国内线下商超市场一片低气压&#xff0c;不续租、关店、亏损…

寄存器与内存详解

目录 CPU、寄存器、内存之间的关系 寄存器 通用寄存器 EAX寄存器 EBX寄存器 ECX寄存器 EDX寄存器 EBP寄存器 ESP寄存器 ESI寄存器 EDI寄存器 总结 段寄存器 分段内存管理机制 段与段寄存器 指令指针寄存器EIP 标志寄存器 内存 虚拟内存 大端存储与小端存储…

rancher容器内获取真实客户端请求IP地址【超简洁步骤】

背景 web程序经常会获取真实客户端请求IP地址,web程序直接部署在物理机上很容易获取到真实请求IP地址。如果web程序部署在docker下&#xff0c;用host模式也能直接获取到客户端真实IP地址。那rancher下如何获取客户端真实请求IP地址呢&#xff1f;很简单&#xff0c;只需一步配…

学习pytorch10 神经网络-最大池化的作用

神经网络-最大池化的作用 官方文档参数说明运算演示公式最大池化 代码code 1执行结果code2执行结果 B站小土堆学习视频 https://www.bilibili.com/video/BV1hE411t7RN?p19&spm_id_frompageDriver&vd_source9607a6d9d829b667f8f0ccaaaa142fcb 官方文档 https://pytorch…

【八大经典排序算法】堆排序

【八大经典排序算法】堆排序 一、概述二、思路解读三、代码实现&#xff08;大堆为例&#xff09; 一、概述 堆排序是J.W.J. Williams于1964年提出的。他提出了一种利用堆的数据结构进行排序的算法&#xff0c;并将其称为堆排序。堆排序是基于选择排序的一种改进&#xff0c;通…