当前位置: 首页 > 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;二…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...