当前位置: 首页 > news >正文

【RPC 协议】序列化与反序列化 | lua-cjson | lua-protobuf

文章目录

    • RPC 协议
      • gRPC
      • JSON-RPC
    • 数据序列化与反序列化
      • lua-cjson
      • lua-protobuf

RPC 协议

在分布式计算,远程过程调用(英语:Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。RPC 是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统。

RPC 协议根据所使用的数据格式,可以分为有模式(schema)和无模式(schema-less)。

  • 有模式(schema)

通讯双方需要提前定义协议模板,在数据传输过程中只传输值,无需传输数据结构,节省流量。典型的有模式 RPC 协议是基于 Protobuf 接口描述语言来实现的,例如 gRPC。
优点是协议结构明确,解析效率高;缺点是不够灵活,协议变更需要重新定义。


  • 无模式(schema-less)

没有预定义数据结构,支持动态语言。无需协议模板,数据传输过程中需要带上数据结构。典型的无模式 RPC 协议是基于 JSON 来实现的, 例如 JSON-RPC 。
优点是协议灵活、易于扩展;缺点是解析效率较低。

通常我们会在数据序列化格式(如 Protobuf、JSON)的基础上,定制符合自己要求的 RPC 协议,灵活的在服务器和客户端之间通信。而不是采用通用的 RPC 框架,对于不需要的功能,增加了通信的开销。

gRPC

https://doc.oschina.net/grpc

JSON-RPC

https://wiki.geekdream.com/Specification/json-rpc_2.0.html


数据序列化与反序列化

lua-cjson

采用的 json for lua 库:https://github.com/cloudwu/lua-cjson

lua CJSON 网站: https://www.kyne.com.au/~mark/software/lua-cjson.php

安装步骤:

  1. git clone https://github.com/cloudwu/lua-cjson.git
  2. cd lua-cjson && sudo vim Makefile

修改如下:(版本 5.4,lua 文件前缀 /home/cauchy/.luaver/lua/5.4.6

由于我使用 luaver 来管理,所以这里 lua 的路径可能不同。

在这里插入图片描述

  1. make

执行完 Makefile,成功后会生成 cjson.so,我们只需要这个动态库。

在这里插入图片描述

  1. mv cjson.so ../ && cd .. && sudo rm -rf lua-cjson

这一步可不执行,只需要 cjson.sorequire "cjson" 时能找到即可,自己可以放置它的位置。


示例代码:

协议格式:

{"fid": "c2s_hello","msg": "world"
}
{"fid": "s2c_hello","succ": true, "msg": "hello " .. "${msg}"
}

fid 用于映射 RPC 协议处理的函数名,fd 用于标识网络连接的文件描述符,JS_data 标识序列化后的 JSON 数据,data 是反序列化后的数据。


创建三个文件:libnet.luaserver.luaclient.lua

在这里插入图片描述

  • libnet.lua

模拟网络库,简易实现网络数据的收发过程。提供三个接口,发送消息给服务端,发送消息给客户端,连接服务器。

local M = {}local server, clientfunction M.send_to_server(fd, JS_data)if not server then server = require "server"end server.dispatch(fd, JS_data)
endfunction M.send_to_client(fd, JS_data)if not client then client = require "client"end client.dispatch(fd, JS_data)
endlocal fd = 0
function M.connect_server()fd = fd + 1return fd
end return M 
  • server.lua

模拟服务器业务逻辑,实现处理客户端的请求。

local cjson = require "cjson"
local libnet = require "libnet"local M = {}
local RPC = {}function RPC.c2s_hello(data)return {fid = "s2c_hello",succ = true, msg = "hello " .. data.msg}
end function M.dispatch(fd, JS_data)local data = cjson.decode(JS_data)local f = assert(RPC[data.fid], "Not exists Func: " .. data.fid)local ok, r = pcall(f, data)if ok then libnet.send_to_client(fd, cjson.encode(r))end return ok 
end return M
  • client.lua

模拟客户端业务逻辑,实现处理服务端的请求。

local cjson = require "cjson"
local libnet = require "libnet"local M = {}
local RPC = {}function RPC.s2c_hello(data)print(data.succ, data.msg)
end function M.dispatch(fd, JS_data)local data = cjson.decode(JS_data)local f = assert(RPC[data.fid], "Not exists Func: " .. data.fid)local ok, r = pcall(f, data)return ok 
end return M 

新建 main.lua,测试逻辑。

local cjson = require "cjson"
local libnet = require "libnet"local function main()local fd = libnet.connect_server()local data = {fid = "c2s_hello",msg = "world"}local JS_data = cjson.encode(data)libnet.send_to_server(fd, JS_data)
endmain()

在这里插入图片描述


lua-protobuf

lua-protobuf 库:https://github.com/starwing/lua-protobuf

  1. luaver use 5.4.6
  2. luaver use-luarocks 3.9.2
  3. luarocks install lua-protobuf

使用 luarocks 来管理安装 lua 包:

在这里插入图片描述
安装完后,可以查看需要的 pb.soprotoc.lua 两个文件的路径:

在这里插入图片描述

  • pb.so:Protocol Buffers 的 Lua 语言动态库文件,通过在 Lua 中 require("pb") 来加载该库。

  • protoc.lua:Protocol Buffers 的 Lua 描述文件编译器,将 .proto 文件编译生成对应的 Lua 代码,生成的 Lua 代码依赖 pb.so 库来实现序列化和反序列化。

示例代码:

local pb = require "pb"
local protoc = require "protoc"-- 直接载入schema (这么写只是方便, 生产环境推荐使用 protoc.new() 接口)
assert(protoc:load [[message Phone {optional string name        = 1;optional int64  phonenumber = 2;}message Person {optional string name     = 1;optional int32  age      = 2;optional string address  = 3;repeated Phone  contacts = 4;} ]])-- lua 表数据
local data = {name = "ilse",age  = 18,contacts = {{ name = "alice", phonenumber = 12312341234 },{ name = "bob",   phonenumber = 45645674567 }}
}-- 将Lua表编码为二进制数据
local bytes = assert(pb.encode("Person", data))
print(pb.tohex(bytes))-- 再解码回Lua表
local data2 = assert(pb.decode("Person", bytes))
print(data2.name, data2.age, data2.contacts[1].name, data2.contacts[1].phonenumber, data2.contacts[2].name, data2.contacts[2].phonenumber)

在这里插入图片描述


使用 protoc.new() 创建一个编译器实例,加载 .proto 文件:

  • addressbook.proto
syntax = "proto3"; package cauchy; message Person {string name = 1; int32 age = 2; enum PhoneType {MOBILE = 0; HOME = 1;WORK = 2;}message PhoneNumber {string number = 1;PhoneType type = 2; }repeated PhoneNumber phones = 3;
}
  • main.lua
local protoc = require "protoc"
local pb = require "pb"local data = {name = "cauchy",age  = 20,phones = {{ number = "1234567890", type = 1 },{ number = "0987654321" }}
}local p = protoc.new()local addressbook = io.open("addressbook.proto"):read("a")
p:load(addressbook)local bytes = assert(pb.encode("cauchy.Person", data))
local data2 = assert(pb.decode("cauchy.Person", bytes))
print(data2.name, data2.age, data2.phones[1].number, data2.phones[1].type)for name, id, types in pb.fields("cauchy.Person") do print(name, id, types)
end 

在这里插入图片描述

由于我是通过 luaver 管理 luarockslua,使用 luarocks 分发 lua 模块,安装的 lua-protobuf。所以上述路径下,没有 pb.soprotoc.lua,直接找到安装路径下的,需要 luaver 使用 lualuarocks
在这里插入图片描述

不过使用者也可以直接拉取到执行脚本的路径下。

上述操作是在 lua 代码中,直接通过导入 protoc.lua 文件,来在运行时加载 .proto 文件的,无需提前编译,但是这样转换性能可能比较慢。


下面我们来安装 protoc 编译器:

  1. sudo apt update
  2. sudo apt install -y protobuf-compiler

protoc 默认安装在 /usr/bin/ 下。

执行 protoc -o addressbook.pb addressbook.proto 生成 .pb 文件。

在这里插入图片描述

.proto 文件:以 Protocol Buffers 语言编写的接口定义文件,用来定义数据结构、服务接口等。

.pb 文件:从 .proto 接口定义文件生成的目标语言代码文件,而没有指定目标语言,生成通用的二进制文件,包含了编码后的 Protocol Buffers 数据。

local pb = require "pb"pb.loadfile("./addressbook.pb")local data = {name = "cauchy",age  = 20,phones = {{ number = "1234567890", type = 1 },{ number = "0987654321"}}
}local bytes = pb.encode("cauchy.Person", data)
print(pb.tohex(bytes))local data2 = pb.decode("cauchy.Person", bytes)
print(data2.phones[2].number, data2.phones[2].type)for name, id, types in pb.fields("cauchy.Person") do print(name, id, types)
end 

在这里插入图片描述

更多具体的 API 操作,参考官方 GitHub:https://github.com/starwing/lua-protobuf

相关文章:

【RPC 协议】序列化与反序列化 | lua-cjson | lua-protobuf

文章目录 RPC 协议gRPCJSON-RPC 数据序列化与反序列化lua-cjsonlua-protobuf RPC 协议 在分布式计算,远程过程调用(英语:Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调…...

Flutter的Timer类

文章目录 一、Timer简介Timer类的详细介绍导入dart:async包创建一个定时器取消定时器定时器的周期性执行注意事项 二、Semantics简介Flutter Semantics 的详细介绍SemanticsNode语义标签和标签形状语义属性自定义语义行为通过语义树导航 一、Timer简介 Flutter的Timer类是Dart…...

Chrome小恐龙快跑小游戏——Python实现

目录 视频演示 代码实现 视频演示 Chrome小恐龙快跑小游戏——Python实现 代码实现 import pygame import os import random pygame.init()# Global Constants SCREEN_HEIGHT 600 SCREEN_WIDTH 1100 game_over False SCREEN pygame.display.set_mode((SCREEN_WIDTH, SCR…...

Web网站服务器

目录 一、什么是Apache? 二、虚拟目录是什么? 三、Apcahe相关配置文件 四、httpd.conf主配置文件的常用配置参数 五、Web网站配置案例 5.1搭建基于用户的个人主页网站 5.2、配置虚拟目录 5.3、配置虚拟主机 5.3.1搭建两个基于IP地址的虚拟主机 5.3.2搭建两个基于域…...

Docker consul 容器服务自动发现和更新

目录 一、什么是服务注册与发现 二、Docker-consul集群 1.Docker-consul consul提供的一些关键特性 2.registrator 3.Consul-template 三、Docker-consul实现过程 以配置nginx负载均衡为例 先配置consul-agent ,有两种模式server和client 四、Docker-cons…...

CentOS 8 执行yum命令报错:Failed to set locale, defaulting to C.UTF-8

今天Docker新搞了一个CentOS镜像,在运行基于该镜像的容器,执行yum命令时,遇到了如下报错: [rootGC Administrator]# yum install -y yum-utils Failed to set locale, defaulting to C.UTF-8 CentOS Linux 8 - AppStream …...

8. 损失函数与反向传播

8.1 损失函数 ① Loss损失函数一方面计算实际输出和目标之间的差距。 ② Loss损失函数另一方面为我们更新输出提供一定的依据。 8.2 L1loss损失函数 ① L1loss数学公式如下图所示,例子如下下图所示。 import torch from torch.nn import L1Loss inputs torch.tens…...

Angular安全专辑之四 —— 避免服务端可能的资源耗尽(NodeJS)

express-rate-limit是一个简单实用的npm包,用于在Express应用程序中实现速率限制。它可以帮助防止DDoS攻击和暴力破解,同时还允许对API端点进行流控。 express-rate-limit及其主要功能 express-rate-limit是Express框架的一个流行中间件,它允许根据IP地址或其他标准轻松地对请求…...

Servlet学习总结(Request请求与转发,Response响应,Servlet生命周期、体系结构、执行流程等...)

Override 是Java中的注解(Annotation),它用于告诉编译器该方法是覆盖(重写)父类中的方法。当我们使用Override注解时,编译器会检查当前方法是否正确地覆盖了父类中的方法,如果没有覆盖成功&…...

雅思写作 三小时浓缩学习顾家北 笔记总结(二)

目录 饥饿网一百句翻译 Using government funds for pollution cleanup work can create a comfortable environment. "Allocating government funds to pollution cleanup work can contribute to the creation of a comfortable environment." Some advertise…...

Element Plus 日期选择器的使用和属性

element plus 日期选择器如果如果没有进行处理 他会返回原有的属性值data格式 如果想要获取选中的日期时间就需要通过以下的代码来实现选中的值 format"YYYY/MM/DD" value-format"YYYY-MM-DD" <el-date-pickerv-model"formInline.date" type&…...

中国五百强企业用泛微为合同加速,提升数字化办公水平

华谊集团借力泛微&#xff0c;融合企业微信、SAP、WPS、电子签章等多种系统&#xff0c;构建了业务集成、场景驱动的全程数字化合同管理平台。 上海华谊&#xff08;集团&#xff09;公司是由上海市政府国有资产监督管理委员会授权&#xff0c;通过资产重组建立的大型化工企业…...

Vue3 QRCode生成

一. 依赖安装 npm install vue-qr --save 二. 引用与使用 引用 <script> // import vueqr from vue-qr vue2的引入 import vueqr from vue-qr/src/packages/vue-qr.vue // vue3的引入 export default {components: {vueqr} } </script> 使用 <template>&…...

2023年8月随笔之有顾忌了

1. 回头看 日更坚持了243天。 读《发布&#xff01;设计与部署稳定的分布式系统》终于更新完成 选读《SQL经典实例》也更新完成 读《高性能MySQL&#xff08;第4版&#xff09;》开更&#xff0c;但目前暂缓 读《SQL学习指南&#xff08;第3版&#xff09;》开更并持续更新…...

正中优配:红筹股是啥意思?

随着我国经济的高速开展&#xff0c;越来越多的人开始参加到股票出资中。其中&#xff0c;红筹股作为一种特别类型的股票&#xff0c;备受一些出资者的关注&#xff0c;但对于一般出资者来说&#xff0c;红筹股详细含义还不是特别清楚。本文将从多个角度探讨红筹股的含义、特征…...

《Linux从练气到飞升》No.19 进程等待

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…...

OpenCV

文章目录 OpenCV学习报告读取图片和网络摄像头1.1 图片读取1.2 视频读取1.1.1 读取视频文件1.1.2读取网络摄像头 OpenCV基础功能调整、裁剪图像3.1 调整图像大小3.2 裁剪图像 图像上绘制形状和文本4.1 图像上绘制形状4.2图像上写文字 透视变换图像拼接颜色检测轮廓检测人脸检测…...

hadoop解决数据倾斜的方法

分析&回答 1&#xff0c;如果预聚合不影响最终结果&#xff0c;可以使用conbine&#xff0c;提前对数据聚合&#xff0c;减少数据量。使用combinner合并,combinner是在map阶段,reduce之前的一个中间阶段,在这个阶段可以选择性的把大量的相同key数据先进行一个合并,可以看做…...

打造坚不可摧的代码堡垒 - 搭建GitLab私有仓库完全指南

在现代软件开发中&#xff0c;版本控制是一个不可或缺的环节。GitLab是一个流行的版本控制平台&#xff0c;允许开发团队协同工作并管理他们的代码。在某些情况下&#xff0c;您可能希望将您的代码托管在一个私有仓库中&#xff0c;以确保代码的安全性和机密性。在本文中&#…...

linux把文件压缩/解压成.tar.gz/tar/tgz等格式的命令大全

linux把文件压缩/解压成.tar.gz/tar/tgz等格式的命令大全 linux压缩命令常用的有&#xff1a;tar&#xff0c;tgz&#xff0c;gzip&#xff0c;zip&#xff0c;rar 一&#xff0c;tar&#xff08;一&#xff09; tar压缩命令#说明&#xff1a;#举例&#xff1a; &#xff08;二…...

学术研究加速器:OpenClaw+千问3.5-27B自动整理参考文献

学术研究加速器&#xff1a;OpenClaw千问3.5-27B自动整理参考文献 1. 为什么需要自动化文献管理 作为一名经常需要阅读大量论文的研究者&#xff0c;我过去每周要花至少3小时手动整理参考文献。从下载PDF、提取元数据到生成BibTeX条目&#xff0c;这些重复性工作不仅枯燥&…...

零欧姆电阻特性与应用全解析

1. 零欧姆电阻的本质与特性零欧姆电阻&#xff0c;这个看似矛盾的名字在电子工程领域却有着广泛的应用。作为一名硬件工程师&#xff0c;我在多年的电路设计实践中发现&#xff0c;这个小元件远比表面看起来要复杂得多。1.1 零欧姆电阻的真实特性零欧姆电阻并非真正的零阻值&am…...

Python错误和异常处理完全指南:从小白到高手的详细教程

本文全面讲解Python中的错误和异常处理机制,从基础概念到高级用法,帮你构建健壮的Python程序。 1. 为什么需要异常处理? 在编程中,错误是不可避免的。想象一下:你写了一个读取文件的程序,但文件不存在;或者计算用户输入的数据,但用户输入了字母而不是数字。没有异常处…...

2026届学术党必备的六大AI学术神器推荐榜单

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 基于自然语言处理以及深度学习算法的AI论文查重技术&#xff0c;经过对文本的语义结构、句式…...

谐波注入抑制永磁同步电机转矩脉动的复现研究

提取特定谐波注入抑制永磁同步电机转矩脉动【复现】 [1]复现文献&#xff1a;《用谐波注入抑制永磁同步电机转矩脉动_廖勇》 [2]控制思路&#xff1a;以抑制电机电流中较大的 5、7 次谐波分量为目的&#xff0c;实时提取谐波电流&#xff0c;注入谐波电压来抵消电机运行时电机电…...

免死金牌: OpenClaw + keepalived

文章目录背景解决方案查看IP检测脚本keepalived 配置演练故障openclaw-gateway.service背景 问题来自 小龙虾自杀, 当我让 OpenClaw 更新一些配置时, 它执行了一条 openclaw gateway stop 命令, 导致 OpenClaw 服务停止, 然后我就干瞪眼了, 还在傻等, 它甚至一句分别的话都没有…...

ViGEmBus技术指南:构建跨平台游戏控制器兼容解决方案

ViGEmBus技术指南&#xff1a;构建跨平台游戏控制器兼容解决方案 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 如何解决游戏控制器的跨平台兼容性难题&…...

终极指南:Spinnaker资源生命周期管理的完整流程与最佳实践

终极指南&#xff1a;Spinnaker资源生命周期管理的完整流程与最佳实践 【免费下载链接】spinnaker Spinnaker is an open source, multi-cloud continuous delivery platform for releasing software changes with high velocity and confidence. 项目地址: https://gitcode.…...

基于python的安全信息隐藏技术在数字图像和文本中的应用

一、系统概述 随着信息技术的快速发展&#xff0c;数据泄露与隐私保护问题日益严重。传统的加密技术虽然能有效保护数据的机密性&#xff0c;但在某些特定场合下&#xff0c;数据的“隐蔽性”同样至关重要。隐写术&#xff08;Steganography&#xff09;作为一种安全信息隐藏技…...

LeaguePrank:英雄联盟客户端个性化引擎完全指南

LeaguePrank&#xff1a;英雄联盟客户端个性化引擎完全指南 【免费下载链接】LeaguePrank 项目地址: https://gitcode.com/gh_mirrors/le/LeaguePrank 1. 价值定位&#xff1a;重新定义游戏界面体验 1.1 产品核心价值 LeaguePrank作为开源的英雄联盟客户端个性化引擎…...