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

从json到protobuf,接口效率的提升

在express开发的前后端调用中,express作为服务端是不二之选,它有一些很好用的body解析器来解析传入数据;而作为请求发起方,axios是非常方便的,这是一个很好的选择,它可以传输多种类型的数据给接收方。
通常我们用urlencoded和json传一些数据量小的信息是蛮不错的,但是如果数据量大的话,或者感觉编码效率低的话,可以考虑用blob或者arraybuffer,当然如果某些属性就是blob或者arrbuffer,直接传就好了,但是如果类似一些较大的json对象数组,类似数据库宽表的一页或者几页信息,真是占空间,自己设计转码还挺麻烦,有没有什么好的办法呢?
这里要推荐一下protobuf,Protobuf 就是Protocol Buffer,它是一种由 Google 开发的二进制序列化格式和相关的技术,它用于高效地序列化和反序列化结构化数据,大名鼎鼎的gRPC里用的就是这个。当然在本文里,我不是让你放弃express+axios,彻底转向gRPC的怀抱,而是利用protobuf来提高我们接口的传输效率。
首先,需要定义下接口数据格式,用proto定义比json更为精准,每条数据的各属性类型顺序,如果支持一个请求里传输多条数据,只需要来一个repeated定义即可。

//dgiij.proto
package dgiijpackage;
syntax = "proto3";message welcomeMessage {string id = 1;int64 timecount = 2;string url = 3;
}message msgs
{repeated welcomeMessage msg = 1;
}

在原接口请求方和服务方简单增加两句,用于在数据发送前和收到后,进行转码和解码即可
下面是node客户端代码

//sender.js
const axios = require('axios');
var protobuf = require("protobufjs");
const root=protobuf.loadSync("dgiij.proto");
const dgiijMessage = root.lookupType("dgiijpackage.msgs");let dataset=[{ "id": "dgiij","timecount":202407271054,"url":"https://blog.csdn.net/dgiij" },{ "id": "dgiij1","timecount":202407271134,"url":"https://blog.csdn.net/dgiij1" }];var messageout = dgiijMessage.create({"msg":dataset});
var buffer = dgiijMessage.encode(messageout).finish();axios.post('http://localhost:3000/sendmsg',buffer,{ headers: {'Content-Type': 'application/octet-stream'}}).then(res=>console.log(res.data))axios.get('http://localhost:3000/getmsg',{responseType:'arraybuffer'}).then(res=>{let messagein = dgiijMessage.decode(res.data);console.log("解码数据为:");console.log(messagein.msg)messagein.msg.forEach(item=>{item.pasrelong=item.timecount.toNumber()})console.log("long类型转数字后数据为:");console.log(messagein.msg)})

下面是node服务端代码

//receiver.js
const protobuf = require("protobufjs");
const root=protobuf.loadSync("dgiij.proto");
const dgiijMessage = root.lookupType("dgiijpackage.msgs");const express = require('express');
const app = express();app.use("/", express.static("./"));app.post('/sendmsg',express.raw(), (req, res)=> {let message = dgiijMessage.decode(req.body);console.log("解码数据为:");console.log(message.msg)message.msg.forEach(item=>{item.pasrelong=item.timecount.toNumber()})console.log("long类型转数字后数据为:");console.log(message.msg)res.json({"msg":"got"});
})app.get('/getmsg', (req, res)=> {let dataset=[{ "id": "dgiij","timecount":202407271054,"url":"https://blog.csdn.net/dgiij" },{ "id": "dgiij1","timecount":202407271134,"url":"https://blog.csdn.net/dgiij1" }];var message = dgiijMessage.create({"msg":dataset});
var buffer = dgiijMessage.encode(message).finish();res.set('Content-Type', 'arrarbuffer');
res.write(buffer);
res.end();
})app.listen(3000, ()=> {console.log("Server is listening");
});

运行结果如下

在这里插入图片描述
在这里插入图片描述
下面这个是浏览器端测试网页

<html>
<head>
<script src="axios.min.js"></script>
<script src="protobuf.js"></script>
</head>
<body>
<div>protobuf test</div>
<script>
protobuf.load("./dgiij.proto").then(root=>{const dgiijMessage = root.lookupType("dgiijpackage.msgs");let dataset=[{ "id": "dgiij","timecount":202407271054,"url":"https://blog.csdn.net/dgiij" },{ "id": "dgiij1","timecount":202407271134,"url":"https://blog.csdn.net/dgiij1" }];
let messageout = dgiijMessage.create({"msg":dataset});
let buffer = dgiijMessage.encode(messageout).finish();axios.post('http://localhost:3000/sendmsg',buffer,{ headers: {'Content-Type': 'application/octet-stream'}}).then(res=>console.log(res.data));axios.get('http://localhost:3000/getmsg',{responseType:'arraybuffer'}).then(res=>{let messagein = dgiijMessage.decode(new Uint8Array(res.data));console.log(messagein.msg)})
});
</script>
</body>
</html>

效果如下
在这里插入图片描述
提醒注意下:浏览器端调用发送数据跟后端没有区别,但是接收数据的话要将返回数据按Uint8Array来解码,否则会报错,另外解码后的long型数字也不用转换了。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 领略诗词之妙,发觉生活之美。
  • 机器学习课程学习周报五
  • 初学Mybatis之 Lombok 篇
  • 微信小程序安装vant组件库和使用
  • Python3网络爬虫开发实战(6)异步爬虫
  • 速盾:cdn加速能不能防御攻击?
  • 掀桌子了!原来是咱们的大屏设计太酷,吓着前端开发老铁了
  • 02 Redis安装与启动
  • 【c++刷题笔记-图论】day52: 101.孤岛的总面积 、102.沉没孤岛 、103.水流问题 、104.建造最大岛屿
  • C# 多线程Paralle使用
  • LangChain4j-RAG高级-核心概念
  • 区块链——代码格式检查(prettier、solhint)
  • OD C卷 - 密码输入检测
  • Linux操作系统 -socket网络通信
  • 深入理解计算机系统 CSAPP 家庭作业11.10
  • Angular2开发踩坑系列-生产环境编译
  • leetcode讲解--894. All Possible Full Binary Trees
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • PaddlePaddle-GitHub的正确打开姿势
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • 阿里云前端周刊 - 第 26 期
  • 树莓派 - 使用须知
  • 用element的upload组件实现多图片上传和压缩
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • #if和#ifdef区别
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (4)logging(日志模块)
  • (C++20) consteval立即函数
  • (二) 初入MySQL 【数据库管理】
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (理论篇)httpmoudle和httphandler一览
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (三) diretfbrc详解
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (四) 虚拟摄像头vivi体验
  • (算法)区间调度问题
  • (限时免费)震惊!流落人间的haproxy宝典被找到了!一切玄妙尽在此处!
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转载)Linux网络编程入门
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .ai域名是什么后缀?
  • .apk 成为历史!
  • .NET C# 配置 Options
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET Reactor简单使用教程
  • .NET 服务 ServiceController
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .sys文件乱码_python vscode输出乱码
  • @Autowired 和 @Resource 区别的补充说明与示例
  • @JsonFormat与@DateTimeFormat注解的使用
  • [Android Studio 权威教程]断点调试和高级调试