gRPC

2 篇文章 0 订阅

什么是gRPC

RPC框架的目的:让调用方感觉就像是调用本地函数一样调用远程函数、让服务提供方感觉就像实现一个本地函数一样来实现服务。

PRC(Remote Procedure Call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信。

背景

对于一些大项目,越来越大,代码难以维护和管理,产生了微服务架构,多个微服务共同完成应用功能,许多相似或一样的模块被抽离出来作为底层服务,来分割项目,然后独立的服务之间可以相互调用。

对于socket和http等以往的通信方式,简单的client和server的模式,可以解决服务之间的相互调用,但是针对以下几个问题,却不是容易:

  • 语法互通性
  • 参数传递
  • 服务端如何确定进行了哪些远程调用
  • 针对发生的错误、性能等问题如何解决

而RPC就是能够解决以上问题,不用考虑底层是如何实现的、用了什么语言来实现和完全独立的服务来实现我们想要的功能。

概念

RPC:Remote Procedure Call,它是一种通过网络从远程计算机上请求服务,而不需要理解底层网络技术的思想。

通过RPC,可以实现不同的微服务也可以根据不同的场景选择最适合的开发语言和技术架构。

RPC协议部分包括:序列化、反序列化、协议编码解码和网络传输。

RPC核心功能有5个部分:客户端、客户端stub、网络传输模块、服务端stub、服务端。

  • 客户端(client): 服务调用方
  • 客户端存根(client stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络信息,再通过网络传输层发送给服务端。
  • 服务端存根(server stub):接受客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理。
  • 服务端(server):服务的真正提供者。
  • 网络传输层(Network Service): 底层传输,可以是TCP或HTTP2

RPC采用客户端-服务端的工作模式。

  • 客户端发起远程调用,将调用的接口、方法和参数通过约定协议规范,通过本地的RPCRuntime进行传输,将调用网络包发送到服务器;
  • 服务端的RPCRuntime收到请求后,调用服务端的方法,返回结果,发送给客户端;
    在这里插入图片描述
gRPC

gRPC:google开发,一款高性能、语言中立、平台中立、开源的RPC框架。
gRPC里客户端应用可以像本地对象一样直接调用另一台不同机器上服务端应用的方法,使得能够更容易创建分布式应用和服务。

基于Http2.0协议标准设计开发,默认采用Protocol Buffers数据序列化协议,支持多种开发语言。

定义一个服务,指定其能够被远程调用的方法(参数和返回类型),在服务端实现这个接口,并允许一个gRPC服务器来处理客户端调用, 在客户端拥有一个存根能够像服务端一样的方法。
在这里插入图片描述

特性
基于Http/2:
    HTTP/2提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。
    可节省带宽、降低TCP链接次数、节省CPU,帮助移动设备延长电池寿命等。
    
IDL使用ProtoBuf:
    gRPC使用ProtoBuf定义服务,ProtoBuf由Google开发的一种数据序列化协议,能够将数据进行序列化,
    并广泛应用在数据存储、通信协议等方面
    压缩和传输效率高,语法简单,表达力强。
    
多语言支持:
    C、C++、Node、Python、Rubuy、Objective-C、PHP和C#
应用场景
低延迟、高扩展性、分布式的系统
同云服务器进行通信的引动应用客户端
涉及语言独立、高效、精确的新协议
便于各方面扩展的分层涉及,如认证、负载均衡、日志记录、监控等
优点
protobuf二进制编码,大幅减少需要传输的数据量,性能好、效率高
proto文件生成目标代码,简单易用
protobuf定义接口,更加严格的接口约束条件
grpc可以方便的支持流式通信
序列化反序列化直接对应程序中的数据类,不需要解析后再进行映射
支持向前兼容(新加字段采用默认值)和向后兼容(忽略新加字段),简化升级
支持多种语言
Netty等一些框架集成
缺点
grpc尚未实现连接池,需要自行实现
尚未提供“服务发现”、“负载均衡”机制
Nginx不能讲Grpc请求作为http请求来负载均衡,而是作为普通的TCP请求
protobuf二进制可读写差
基础
.proto文件定义服务
protocol buffer编译器生成服务器和客户端代码
使用grpc的NodeJS API为服务实现一个简单的客户端和服务器
为什么使用gRPC?
允许客户端获取路由特性的信息,生成路由的总结,及交互路由信息
四种通信方式
Simple RPC
    一个请求对象对应一个返回对象
    
Server-side streaming RPC
    服务端流式rpc,一个请求对象,服务端返回多个结果对象
    
Client-side streaming RPC
    客户端流式rpc,客户端传入多个请求对象,服务端返回一个相应结果
    
Bidirectional streaming RPC
    双向流式rpc,结合客户端流式rpc和服务端流式rpc,可以传入多个对象,返回多个响应对象
Getting Started
  1. cd examples/node-test

  2. Installing

	cnpm i grpc --save
	cnpm i grpc-tools --save-dev
	cnpm i grpc_tools_node_protoc_ts --save-dev
	cnpm i google-protobuf --save 
  1. 定义服务:
    使用protocol buffers去定义gRPC service和方法request及response类型;

  2. .proto文件:
    .proto文件也包含了所有请求的protocol buffer消息类型定义及在服务方法中使用的响应类型。

    syntax = "proto3"; // 指定使用proto3语法,默认是proto2,且放在proto文件的非空非注释的第一行。

    package helloworld;

    // 指定service
    service Greeter {
    	// 服务中的方法
    	
        // 一个简单的rpc, 客户端使用存根发送请求到服务器并等待响应返回;
        // SayHello方法
        // HelloRequest/HelloReply消息结构
        rpc SayHello (HelloRequest) returns (HelloReply) {}
        
        // 一个服务端流式rpc 客户端发送请求到服务器,拿到一个流去读取返回的消息序列。
        // 客户端读取返回的流,直到里面没有任何消息。
        rpc ListFeatures(Rectangle) returns (stream Feature) {}

        // 一个客户端流式rpc 客户端写入一个消息序列并将其发送到服务器,同样适用流
        // 一旦客户端完成写入信息,它等待服务器完成读取返回它的响应
        rpc RecordRoute(stream Point) returns (RouteSummary) {}

        // 一个双向流式rpc 双方适用读写流去发送一个消息序列。两个流独立操作,因此客户端和服务端可以任曦喜欢的顺序读写
        rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
    }

	// 定义请求结构
    message HelloRequest {
        string name = 1;
    }

	// 定义响应结构
    message HelloReply {
        string message = 1;
    }
    
  1. 编译proto文件
	cd protos
    
    grpc_tools_node_protoc --js_out=import_style=commonjs,binary:../protos --grpc_out=../protos --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` helloword.proto
  

生成两个文件:
    helloword_pb.js
    helloword_grpc_pb.js

  1. 创建服务器:
    const grpc = require('grpc');

    const messages = require('./helloworld_pb');
    const services = require('./helloworld_grpc_pb');

    /**
    * Implements the SayHello RPC method.
    */
    function sayHello(call, callback) {
        const reply = new messages.HelloReply();
        reply.setMessage('Hello ' + call.request.getName());
        // 第一个参数为null,表示没有错误       callback(null, reply);
    }

    // 启动服务器
    function main() {
        const server = new grpc.Server();
        server.addService(services.GreeterService, {sayHello: sayHello});
        server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
        server.start();
    }
    
    main();
    
  1. client
    const grpc = require('grpc');

    const messages = require('./helloworld_pb');
    const services = require('./helloworld_grpc_pb');

    function main() {
        const client = new services.GreeterClient('localhost:50051', grpc.credentials.createInsecure());
        const request = new messages.HelloRequest();
        const user;
        if (process.argv.length >= 3) {
            user = process.argv[2];
        } else {
            user = 'world';
        }
        request.setName(user);
        client.sayHello(request, function (err, response) {
            console.log('Greeting:', response.getMessage());
        });
    }

    main();
    
  1. 启动
  	cd ../node-test

    node ./static-codegen/test_server.js

    node ./static-codegen/test_client.js
    

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值