Node.js 使用 gRPC:从定义到实现

1. 概述:

gRPC(gRPC Remote Procedure Calls)是一个高性能、开源的远程过程调用(RPC)框架,由 Google 开发。它支持多种编程语言,旨在简化和优化分布式系统中的服务通信。

2. gRPC的优势:

高性能:使用 HTTP/2 和 protobuf 使得 gRPC 在性能和效率方面表现出色。二进制协议和 HTTP/2 的多路复用特性使其通信开销低,速度快。

简化开发:自动代码生成和多语言支持简化了微服务的开发和维护。通过 .proto 文件定义接口后,gRPC 工具会生成相应的客户端和服务器代码,大大减少了手动编码的工作量。

强类型:使用 protobuf 定义服务接口和消息类型,确保强类型检查和错误检测。开发人员可以在编译时捕捉到许多错误,提高代码的可靠性和可维护性。

灵活的流处理:支持多种通信模式(单次请求-响应、服务端流、客户端流、双向流),适应不同的使用场景。例如,可以用服务端流实现数据的实时推送,用双向流实现实时聊天功能。

高效的序列化:Protocol Buffers 是一种高效的二进制序列化格式,序列化和反序列化速度快,生成的数据体积小,适合高性能场景。

3. 实现逻辑:

  1. 定义一个服务,指定被调用的方法(包含参数和返回类型)。
  2. 运行 gRPC 服务器来处理客户端的调用。
  3. 在客户端拥有一个存根,能够像服务端一样的方法。

4. Node.js:

Node.js 库从运行时加载的 .proto 文件动态生成服务描述和客户端存根的定义,所以使用此语言时没必要生成任何特殊代码。而是在例子客户端和服务端里,我们 require gRPC 库,然后用它的 load() 方法,就可以去加载.proto文件。

5. 为什么 nodejs 推荐动态加载.proto文件?

使用 @grpc/proto-loader 库在运行时动态加载 .proto 文件。这是官方推荐的方法

优点:

  1. 开发便捷:不需要在每次修改 .proto 文件后重新生成代码,开发过程更加便捷
  2. 灵活性:适合快速迭代和频繁修改 .proto 文件的项目
  3. 减少依赖:不需要安装 protoc 编译器

缺点:性能:由于在运行时解析 .proto 文件,可能会有一些性能开销,但通常可以忽略不计

6. RPC 生命周期:

定义服务的四类方法:
  1. 单项 RPC:

    proto
    复制代码
    rpc SayHello(HelloRequest) returns (HelloResponse) {}
    
  2. 服务端流式 RPC:

    proto
    复制代码
    rpc SayHello(HelloRequest) returns (stream HelloResponse) {}
    
  3. 客户端流式 RPC:

    proto
    复制代码
    rpc SayHello(stream HelloRequest) returns (HelloResponse) {}
    
  4. 双向流式 RPC:

    proto
    复制代码
    rpc SayHello(stream HelloRequest) returns (stream HelloResponse) {}
    

截止时间:客户端可以设置响应的过期时间

RPC 终止

取消 RPC:同步调用不能被取消

元数据集:特殊 RPC 调用对应的信息(键值对形式)

流控制

配置

频道

同步、异步

7. 定义.proto 文件:

关于 Protocol Buffers 的语法教程请看主页对应文章

// 使用 proto3 语法,不指定的话默认 proto2
syntax = "proto3";// 是否需要生成的类拆分为多个
option java_multiple_files = true;
// 生成的类所属的层级
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";// 定义报名,并于避免命名冲突
package helloworld;// 定义服务
service Greeter {// 定义://   1. 参数//   2. 返回类型rpc SayHello (HelloRequest) returns (HelloReply) {}rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {}
}// 结构化数据:使用 message 定义。
message HelloRequest {string name = 1; // 字段类型 字段名 = 字段编号;
}message HelloReply {string message = 1;
}

8. 创建 nodejsgRPC 服务端:

// Protocol Buffers 文件
let PROTO_PATH = __dirname + './helloworld.proto';// 用户实现 gRPC 服务和客户端的核心库
let grpc = require('@grpc/grpc-js');
// 加载 .proto 文件
let protoLoader = require('@grpc/proto-loader');
/*** protoLoader.loadSync(PROTO_PATH, { ... }) 方法* 从指定的 .proto 文件加载定义,并根据选项配置进行解析。* 使用到 protoLoader 一个 Node.js 模块*/
let packageDefinition = protoLoader.loadSync(PROTO_PATH,{keepCase: true, // 保持字段名称的大小写longs: String, // 将 Protocol Buffers 中的 long 类型字段解析为 JavaScript 字符串enums: String, // 将枚举类型转换为字符串defaults: true, // 为所有字段设置默认值oneofs: true // 支持 oneof 字段,这是一种在 Protocol Buffers 中定义的互斥字段});
/*** grpc.loadPackageDefinition(packageDefinition) 方法* 将 @grpc/proto-loader 生成的描述加载到 gRPC 库中,* 将加载的 Protocol Buffers 描述转换为 gRPC 服务端可以使用的 JavaScript 对象。* 以创建客户端和服务端。*/
let hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;/*** 定义 RPC 的方法*/
function sayHello(call, callback) {callback(null, { message: 'Hello ' + call.request.name });
}function main() {// 1. 创建 gRPC 服务器实例let server = new grpc.Server();// 2. 将 Greeter 服务和实现方法添加到 gRPC 服务器中server.addService(hello_proto.Greeter.service, { sayHello: sayHello });/*** 3. 绑定服务器到指定的地址和端口,并使用不安全的凭据(没有 SSL/TLS)*    grpc.ServerCredentials.createInsecure(): 创建不安全的服务器凭据*/server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), (err, port) => {if (err != null) {return console.error(err);}console.log(`gRPC listening on ${port}`)});
}main();

9. 创建 nodejsgRPC 客户端:

let PROTO_PATH = __dirname + './helloworld.proto';// 用户实现 gRPC 服务和客户端的核心库
let grpc = require('@grpc/grpc-js');
// 加载 .proto 文件
let protoLoader = require('@grpc/proto-loader');
// 加载 .proto 文件,并且根据配置项进行解析
let packageDefinition = protoLoader.loadSync(PROTO_PATH,{keepCase: true, // 保持字段名称的大小写longs: String, // 将 Protocol Buffers 中的 long 类型字段解析为 JS 字符串enums: String, // 将枚举类型转换为字符串defaults: true, // 为所有字段设置默认值oneofs: true // 支持 oneof 字段});
// 将生成的描述添加到 gRPC 库中,并输入可以使用的 JS 对象,来创建服务端和客户端
let hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;function main() {// 定义 gRPC 服务器的地址和端口let target = 'localhost:50051';// 创建一个客户端存根,存根(抽象层):hello_proto.Greeter,来调用远程服务let client = new hello_proto.Greeter(target,grpc.credentials.createInsecure());let user = 'world';// 调用远程服务方法client.sayHello({ name: user }, function (err, response) {console.log('Greeting:', response.message);});
}main();

10. 核心特点

  1. 多语言支持:gRPC 支持多种编程语言,包括 C++, Java, Python, Go, Ruby, Node.js 等,使得跨语言的微服务之间可以无缝通信。
  2. 基于 HTTP/2:gRPC 使用 HTTP/2 协议,这带来了许多优点,如多路复用、流量控制、头部压缩和双向流。
  3. 使用 Protocol Buffers:gRPC 使用 Protocol Buffers(protobuf)作为接口定义语言(IDL)和消息交换格式。这种二进制格式既高效又便于跨语言。
  4. 自动生成代码:通过使用 .proto 文件定义服务和消息类型,gRPC 工具链可以自动生成客户端和服务器端的代码,大大简化了开发工作。
  5. 全双工流式处理:gRPC 支持双向流式处理,这意味着客户端和服务器可以在单个连接上独立地发送和接收多个消息。

11. 典型应用场景

  1. 微服务通信:gRPC 非常适合在微服务架构中用来实现高效的服务间通信。
  2. 实时通信:通过双向流处理,gRPC 可以用于实时聊天、数据流和其他需要低延迟的应用。
  3. 跨语言通信:gRPC 的多语言支持使其成为异构系统中不同语言组件之间通信的理想选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/866449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIGC | 在机器学习工作站安装NVIDIA cuDNN 深度学习库

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 0x03.初识与安装 cuDNN 深度学习库 什么是cuDNN? cuDNN(CUDA Deep Neural Network library)是由英伟达(NVIDIA)开发的深度学习库,专门用…

昇思学习打卡-5-基于Mindspore实现BERT对话情绪识别

本章节学习一个基本实践–基于Mindspore实现BERT对话情绪识别 自然语言处理任务的应用很广泛,如预训练语言模型例如问答、自然语言推理、命名实体识别与文本分类、搜索引擎优化、机器翻译、语音识别与合成、情感分析、聊天机器人与虚拟助手、文本摘要与生成、信息抽…

LLMs之gpt_academic:gpt_academic的简介、安装和使用方法、案例应用之详细攻略

LLMs之gpt_academic:gpt_academic的简介、安装和使用方法、案例应用之详细攻略 目录 gpt_academic的简介 1、版本更新历史 版本: 1、新增功能及其描述 新界面(修改config.py中的LAYOUT选项即可实现“左右布局”和“上下布局”的切换) 所…

Linux shell编程学习笔记62: top命令 linux下的任务管理器

0 前言 top命令是Unix 和 Linux下常用的性能分析工具,提供了一个动态的、交互式的实时视图,显示系统的整体性能信息,以及正在运行的进程的相关信息,包括各个进程的资源占用状况,类似于Windows的任务管理器。 1 top命令…

鸿蒙:1.入门

概述 简介 鸿蒙操作系统(HarmonyOS)是华为公司发布的一款智能终端系统,是基于微内核的面向全场景的分布式操作系统。它致力于提供更加安全、高效、低延迟、低功耗的操作体验,可通过技术手段对应用程序和设备进行智能协同&#xf…

mac鼠标键盘共享:ShareMouse for Mac 激活版

hareMouse 是一款 Windows 和 macOS 操作系统上的共享和切换鼠标和键盘的实用工具。这款软件允许用户在多台计算机之间无缝地共享鼠标和键盘,使得在不同设备之间进行工作和操作变得更加便捷。占用资源少: ShareMouse 设计轻量,占用系统资源较…

JVM原理(十五):JVM虚拟机静态分配与动态分配

1. 分派 本节讲解的分派调用过程将会揭示多态性特征的一-些最基本的体现,如“重载”和“重写”在Java虚拟机之中是如何实现的。 1.1. 静态分派 案例: 我们先来看一段代码: Human mannew Man(); 我们把上面代码中的“Human"称为变量的“静态类型…

alibabacloud学习笔记10

讲解微服务链路追踪系统的作用 讲解什么Sleuth链路追踪系统 注释掉我们的网关过滤器。 注释掉断言。 网关服务,视频服务,订单服务,我们都给这段依赖添加进来。 调用一个请求。 我们可以看到控制台上会有输出。 讲解zipkin介绍和部署实战 访问…

Vite: 实现 no-bundle 开发服务 (2)

概述 基于前文 Vite: 实现 no-bundle 开发服务 (1) 我们基于下面的导图继续实现 no-bundle 构建服务 接下来我们需要完成如下的模块: CSS 编译插件静态资源加载插件模块依赖图开发,并在 transform 中间件中接入HMR 服务端代码开发HMR 客户端代码开发 CSS 编译插件…

泰国内部安全行动司令部数据泄露

BreachForums 论坛的一名成员宣布发生一起重大数据泄露事件,涉及泰国内部安全行动司令部 (ISOC),该机构被称为泰国皇家武装部队的政治部门。 目前,我们无法准确确认此次泄露的真实性,因为该组织尚未在其网站上发布有关该事件的任…

数据库管理-第217期 Oracle的高可用-02(20240704)

数据库管理217期 2024-07-04 数据库管理-第217期 Oracle的高可用-02(20240704)1 GDS简介2 GDS架构2.1 全局数据服务池2.2 全局数据服务域2.3 全局服务管理2.4 全局数据服务目录2.5 Oracle通知服务 3 GDS简图3.1 负载均衡3.2 只读服务失败转移3.3 多主复制…

项目基础知识

1.JDBC编程和MySQL数据库 数据库的连接(以前写qq项目时的代码) package com.wu.Util; import java.sql.*; public class JDBCUtil {private static JDBCUtil jdbcUtil null;private JDBCUtil() {}public static JDBCUtil getJdbcUtil() {if (jdbcUtil…

剧本杀小程序:助力商家发展,提高游戏体验

近几年,剧本杀游戏已经成为了当下年轻人娱乐的游戏社交方式。与其他游戏相比,剧本杀游戏具有强大的社交性,玩家在游戏中既可以推理玩游戏,也可以与其他玩家交流互动,提高玩家的游戏体验感。 随着互联网的发展&#xf…

Vue通过Key管理状态

Vue通过Key管理状态 Vue 默认按照“就地更新”的策略来更新,通过 v-for 渲染的元素列表。当数据项的顺序改变时,Vue 不会随之移动 DOM 元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。为了给 Vue 一个提示…

VIO(Virtual_Input_Output) IP 使用笔记

VIO(Virtual Input/Output)IP 核,即虚拟输入输出 IP,可以通过调试界面模拟 IO 的变化,这可以在板子没有按键等外设、或外设不足的情况下,来模拟外部输入。然而网上关于 VIO 的教程都说的不是很清楚&#xf…

html高级篇

1.2D转换 转换(transform)你可以简单理解为变形 移动:translate 旋转:rotate 缩放:sCale 移动:translate 1.移动具体值 /* 移动盒子的位置: 定位 盒子的外边距 2d转换移动 */div {width…

【python】OpenCV—Nighttime Low Illumination Image Enhancement

文章目录 1 背景介绍2 代码实现3 原理分析4 效果展示5 附录np.ndindexnumpy.ravelnumpy.argsortcv2.detailEnhancecv2.edgePreservingFilter 1 背景介绍 学习参考来自:OpenCV基础(24)改善夜间图像的照明 源码: 链接&#xff1a…

Linux 文件系统以及日志管理

一、inode 与block 1. inode 与block详解 在文件存储硬盘上,硬盘的最小存储单位叫做“扇区”,每个为512字节。 操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取…

PyMuPDF 操作手册 - 09 API - Page属性方法和简短说明

文章目录 一、Page属性方法和简短说明一、Page属性方法和简短说明 https://pymupdf.readthedocs.io/en/latest/page.html Method/Attribute属性方法Short Description简短说明Page.add_caret_annot()仅限 PDF:添加插入符号注释Page.add_circle_annot()仅限 PDF:添加圆圈…

微服务粒度难题:找到合适的微服务大小

序言 在微服务架构风格中,微服务通常设计遵循SRP(单一职责原则),作为一个独立部署的软件单元,专注于做一件事,并且做到极致。作为开发人员,我们常常倾向于在没有考虑为什么的情况下尽可能地将服…