Node.js RPC 介绍和半双工简单代码实现(新手版)

什么是 RPC

本篇是极客时间杨浩老师的概括总结。首先点开这篇文章的你肯定会疑惑,什么是RPC呢?既然有了HTTP协议为什么还需要RPC?

RPC 与 HTTP 作比较

  1. RPC本质上不算是协议,而是一种调用方式
  2. RPC的实现是基于Socket之上的
  3. HTTP是90年代才开始流行的,在TCP之上之前有很多替代的协议,这就包括RPC,也就说在没有HTTP协议的时代,很多人用RPC发送数据的。

那为什么现在有了 HTTP 我们还需要学习 RPC 呢?

有一个比较直观的理解就是在 c/s 架构下 (client/server), RPC 可以使用在公司内网,进行数据传输。

RPC 的技术不同点

  1. 不一定使用DNS作为寻址服务(在内网里互相请求)
  1. RPC应用层协议通常不使用HTTP,而是采用基于二进制的协议来替代HTTP

RPC传输二进制协议,相比HTTP

  1. 更小的数据包体积

  2. 更快的编解码速率

  1. 基于TCP或UDP协议

RPC 技术实现

二进制传输实现

使用 Node.js 中的 Buffer API 详情见官网文档Buffer | Node.js v18.17.1 Documentation (nodejs.org)

这里需要掌握两个创建 Buffer 的语法,用于二进制传输

  1. Buffer.from
  • 可以接受多种输入类型作为参数,包括字符串、数组、Buffer对象
  • 提供的数据可以直接填充到Buffer中,const bufferFromStr = Buffer.from('Hello');
  • 如果提供了字符串,则可以指定编码格式,例如'utf8'、'hex'等,默认为'utf8'。
  1. Buffer.alloc
  • 创建指定大小的新的Buffer对象,并将所有字节设置为零(初始化)。
  • 接受一个整数参数,表示要分配的字节数。

RPC 半双工代码

server 端

js 复制代码
const net = require('net')

const server = net.createServer((socket) => {
    socket.on('data', function (buffer) {
        const fruitId = buffer.readInt32BE()
        const fruitData = data[fruitId];
        if(fruitData !== undefined) {
            const bufferc = Buffer.from(fruitData);
            setTimeout(() => {
                socket.write(bufferc);
            }, 500);
        } else {
            console.log("fruitId: " + fruitId + " doesn't exist.")
        }
        
        console.log(buffer, buffer.toString())
    })
})

const data = {
    136797: "01 草莓",
    136798:"02 香蕉",
    136799: "03 西瓜",
    136808: "04 榴莲",
    136801: "05 菠萝蜜",
    136803: "06 香瓜",
    136804: "07 白兰瓜",
}

server.listen(4000)

client 端

js 复制代码
const net = require('net')

const socket = new net.Socket({})

socket.connect({
    host: '127.0.0.1',
    port: 4000
})

const id = [
    "136797",
    "136798",
    "136799",
    "136808",
    "136801",
    "136803",
    "136804",
]

// 请求第一次发送
let index = Math.floor(Math.random() * id.length)
socket.write(encode(index))

socket.on('data', (buffer) => {
    const fruitBuffer = buffer;
    console.log(fruitBuffer.toString())

    index = Math.floor(Math.random() * id.length)
    socket.write(encode(index))
})

function encode(index) {
    let buffer = Buffer.alloc(4)
    buffer.writeInt32BE(
        id[index]
    )
    console.log(id[index])
    return buffer
}
相关推荐
第五页的你2 分钟前
ElasticSearch结合本地消息表实现搜索功能
后端
谢亮_vipxieliang27 分钟前
ValidX分组验证详解:不同场景使用不同验证规则
java·spring boot·后端·spring cloud·eclipse·hibernate
超兔一体云35 分钟前
MySQL索引优化实战——从慢查询到索引调优
后端·mysql
默_笙1 小时前
🔥 让 AI 帮我写完整个 Next.js 博客:框架就是 AI 的"上下文 buff"
前端·javascript
. . . . .1 小时前
服务端监控
后端
牧艺1 小时前
登录页还在用渐变?我一口气做了 5 个能摸的背景动效:吹蒲公英、滴墨染水、点熔岩闷裂
前端·canvas·交互设计
陆枫Larry1 小时前
状态机简介
前端
凤山老林1 小时前
Spring Boot 集成 Spring Vault:集中式密钥管理与动态凭证轮换
spring boot·后端·spring·vault·集中式秘钥管理
雨夜之寂1 小时前
雨夜-现在有办法识别是不是ai文章么
后端·面试
2601_962071171 小时前
八. Spring Boot2 整合连接 Redis(超详细剖析)
spring boot·redis·后端