IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 1、Google Grpc 框架源码解析 之 Hello World -> 正文阅读

[网络协议]1、Google Grpc 框架源码解析 之 Hello World

由于最近换了一份工作,新公司使用 RPC 框架使用的是 Google 开源的 RPC 框架 grpc。对于 grpc 之前只是听说过,在真实的项目当中并没有使用过。为了能够更好的使用 grpc (当遇到问题,能够快速发现并解决问题),所以准备写一个系列来研究 grpc 。

gRPC是一个现代的开源高性能远程过程调用(RPC)框架,可以在任何环境中运行。它可以有效地连接数据中心内和跨数据中心的服务,支持负载均衡、跟踪、健康检查和身份验证。它也适用于分布式计算的最后一英里,将设备、移动应用程序和浏览器连接到后端服务。

主要使用场景:

  • 在微服务风格的体系结构中有效地连接多语言服务
  • 连接移动设备、浏览器客户端到后端服务
  • 生成高效的客户端库

核心功能

  • 11种语言的常用客户端库
  • 高效的在线服务和简单的服务定义框架
  • 基于http/2传输的双向流
  • 可插拔认证、跟踪、负载均衡和健康检查

1、概述

在gRPC中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像它是本地对象一样,这使得创建分布式应用程序和服务更加容易。与许多RPC系统一样,gRPC基于定义服务的思想,指定可以通过参数和返回类型远程调用的方法。在服务器端,服务器实现这个接口,并运行一个gRPC服务器来处理客户端调用。在客户端,客户端有一个 stub (在某些语言中称为客户端),它提供与服务器相同的方法。

在这里插入图片描述
gRPC 客户机和服务器可以在各种环境中彼此运行和通信。从谷歌内部的服务器到您自己的桌面,并且可以用 gRPC 支持的任何语言编写。例如,你可以很容易地用Java 创建一个 gRPC 服务器,用Go、Python 或 Ruby 创建客户端。此外,最新的谷歌 api 将拥有其接口的gRPC版本,可以很轻松地将谷歌功能构建到您的应用程序中。

2、Protocol Buffers

默认情况下,gRPC 使用 Protocol Buffers ,这是谷歌成熟的用于序列化结构化数据的开源机制(尽管它也可以用于其他数据格式,如JSON)。下面是它如何工作的一个快速介绍。如果您已经熟悉了协议缓冲区,可以直接跳到下一节。

使用协议缓冲区时,第一步是为你想要在原型文件中序列化的数据定义结构:这是一个扩展名为.proto的普通文本文件。协议缓冲区数据的结构是消息,其中每个消息是一个小的信息逻辑记录,包含一系列名为字段的 名称-值 对。下面是一个简单的例子:

message Person {
  string name = 1;
  int32 id = 2;
  bool has_ponycopter = 3;
}

然后,一旦指定了数据结构,就可以使用 protocol buffer 编译器协议从原型定义中以你的编程语言生成数据访问类。它们为每个字段提供了简单的访问器,比如name()set_name(),以及将整个结构序列化/解析为原始字节的方法。例如,如果您选择的语言是 c++,在上面的示例中运行编译器将生成一个名为 Person 的类。然后,您可以在应用程序中使用这个类来填充、序列化和检索 Personprotocol buffer 消息。

你在 .proto 文件中定义 gRPC 服务,使用 RPC 方法参数和返回类型指定为协议缓冲区消息:

// The greeter 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 greetings
message HelloReply {
  string message = 1;
}

gRPC使用带有特殊gRPC插件的protoc从你的原型文件中生成代码:你会生成gRPC客户机和服务器代码,以及用于填充、序列化和检索你的消息类型的 protocol buffer代码。

如果想要了解更多关于 protocol buffers 的信息,包括如何在你的编码语言中使用 gRPC 插件安装 protoc。可以查看 protocol buffers documentation.

3、核心组件

在高层次抽象上,grpc 有三个不同的层:StubChannelTransport

3.1 Stub

Stub 层是向大多数开发人员公开的,并提供类型安全的绑定到您正在适应的任何数据模型/IDL/接口。gRPC 附带了一个 protocol-buffers 编译器的插件,它可以从 .proto 文件生成Stub 接口,并且绑定到其他数据模型/IDL很容易。

3.2 Channel

Channel 是传输处理之上的一个抽象,它适合于拦截/修饰,并且比 Stub 层向应用程序暴露更多的行为。应用程序框架可以很容易地使用这一层来处理横切问题,如日志记录、监视、认证等。

3.3 Transport

Transport 完成了将字节从线路上移除的繁重工作。它的接口是抽象的,刚好允许插入不同的实现。注意,Transport API被认为是gRPC内部的,它的API保证比 io.grpc 包下的核心API要弱。

gRPC有三种传输实现:

  • 基于 Netty 的传输是基于 Netty 的主要传输实现。它对客户机和服务器都适用。
  • 基于 OkHttp 的传输是一种基于 OkHttp 的轻量级传输。它主要用于 Android 和客户端。
  • 进程内传输适用于服务器和客户端处于同一进程中的情况。它对测试很有用,同时对生产使用也很安全。

4、Hello World

4.1 安装插件 Protobuf Support

在这里插入图片描述

4.2 创建项目

创建一个 maven 项目,包结构如下:
在这里插入图片描述
注意:proto 目录需要与 src/main/java 目录平级。

4.3 定义 hello.proto 文件

syntax = "proto3";

option java_multiple_files = true;
option java_package = "cn.carl.grpc.demo.proto";
option java_outer_classname = "HelloServiceProto";

package cn.carl.grpc.demo;

// 定义服务
service HelloService {
  // 注意 : 这里是 returns 不是 return
  rpc sayHello (HelloRequest) returns (HelloResponse) {
  }
}
// 定义消息类型
message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
}

4.4 编译项目

使用命令行 mvn clean install 对项目进行编译,在 target 目录会生成 grpc 文件。也就是开发人员关心的 Stub 文件。
在这里插入图片描述

4.5 暴露 GRPC 服务

继承 HelloServiceGrpc.HelloServiceImplBase ,并且把服务添加到 grpc 中绑定端口的 io.grpc.internal.ServerImpl当中,然后启动暴露服务。

GrpcServer.java

public class GrpcServer {
    // 定义端口
    private final int port = 50051;
    // 服务
    private io.grpc.Server server;

    // 启动服务,并且接受请求
    private void start() throws Exception {
        server = ServerBuilder.forPort(port).addService(new HelloServiceImpl()).build().start();
        System.out.println("服务开始启动-------");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.err.println("------shutting down gRPC server since JVM is shutting down-------");
                GrpcServer.this.stop();
                System.err.println("------server shut down------");
            }
        });
    }

    // stop服务
    private void stop() {
        if (server != null) {
            server.shutdown();
        }
    }

    // server阻塞到程序退出
    private void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }

    //实现服务接口的类
    private class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
        @Override
        public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
            HelloResponse build = HelloResponse.newBuilder().setMessage(request.getName()).build();
            // onNext()方法向客户端返回结果
            responseObserver.onNext(build);
            // 告诉客户端这次调用已经完成
            responseObserver.onCompleted();
        }
    }

    public static void main(String[] args) throws Exception {
        final GrpcServer server = new GrpcServer();
        server.start();
        server.blockUntilShutdown();
    }
}

服务启动如下:

在这里插入图片描述

4.6 客户端远程调用

使用 ManagedChannelBuilder 绑定远程服务器,然后使用 .proto 生成的 stub 类进行远程调用。

GrpcClient.java

public class GrpcClient {
    private final ManagedChannel channel;
    private final HelloServiceGrpc.HelloServiceBlockingStub blockingStub;
    private static final String host = "127.0.0.1";
    private static final int ip = 50051;

    public GrpcClient(String host, int port) {
        // usePlaintext表示明文传输,否则需要配置ssl
        // channel  表示通信通道
        channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
        //存根
        blockingStub = HelloServiceGrpc.newBlockingStub(channel);
    }

    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    public void testGrpc(String name) {
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloResponse response = blockingStub.sayHello(request);
        System.out.println(response.getMessage());
    }

    public static void main(String[] args) {
        GrpcClient client = new GrpcClient(host, ip);
        for (int i = 0; i <= 5; i++) {
            client.testGrpc("<<<<<result>>>>>:" + i);
        }
    }
}

调用结果如下:
在这里插入图片描述
服务端实现服务所需要的接口,并且启动服务接受请求。客户端连接上服务端会有一个stub,然后拿着 stub 和请求参数,去请求某个服务下的某个方法。

相对于服务端实现接口时是继承了 HelloServiceGrpc.HelloServiceImplBase 这个抽象类,而这个类是我们用 proto 工具生成的,并非基于反射实现的。

参考文章

  • https://www.grpc.io/about/
  • https://www.grpc.io/docs/languages/
  • https://www.grpc.io/docs/what-is-grpc/introduction/
  • https://blog.csdn.net/weixin_43770545/article/details/90786544
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:59:55  更:2022-02-28 16:00:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:44:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码