前端如何处理与 RabbitMQ 通讯时 protobuf 的序列化数据

文章首发于掘金,文章地址

背景

这次项目需求是要对接到 RabbitMQ 来实时接收数据,在浏览器将数据实时渲染在页面上。

特殊的是,这些数据是经过 protobuf 进行序列化编码的,前端接收到的是进制数据,所以需要对接收到的数据进行解码后才能使用。

工具

项目使用的是 StompJs 进行与 RabbitMQ 通讯:

npm install @stomp/stompjs

还需要用到两个工具,用来对接收到的数据进行解码,我们先进行全局安装:

npm i protobufjs protobufjs-cli -g

生成用来解码的 JS 文件

在对数据解码之前,后端人员会事先定义好了PB协议,字段内容都在 .proto 文件中,可能会有很多个 .proto 文件,找他们拿到这些文件。

举个例子:

// User.proto
syntax = "proto3";  

message User
{
    string username = 1;
    uint32 age = 2;
}

等号后的值是唯一的标识号,不用管它。

拿到这些 .proto 文件后,在项目 src 目录下新建 proto 文件夹,把所有 .proto 文件都放到文件夹里。

接着在项目根目录执行命令:

pbjs -t json-module -w commonjs -o src/proto/base.js src/proto/*.proto

这条命令会根据目录下的 .proto 文件,输出一个 base.js 的文件,这个 JS 文件就是用来解码的。

成功生成后,大概是长这样子:

"use strict";

var $protobuf = require("protobufjs/light");

var $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $protobuf.Root()))
.addJSON({
  User: {
    fields: {
      username: {
        type: "string",
        id: 1
      },
      age: {
        type: "uint32",
        id: 2
      }
    }
  }
});

module.exports = $root;

到此,前期工作准备完毕!

连接 RabbitMQ

import { Client } from '@stomp/stompjs'

const client = new Client({
  // URL地址
  brokerURL: 'ws://localhost:15674/ws',
  connectHeaders: {
    // 你的账号
    login: 'user',
    // 你的密码
    passcode: 'password'
  }
})
// 注意!!!要记得调用 activate 方法来初始化连接
client.activate()

接着打开控制台,到 NetworkWS下刷新页面,选中 ws 可以看到连接成功了!

这里默认发送是数据是心跳机制,就是让对方知道自己还活着,以确保连接的有效性的机制。

image.png

订阅消息队列,接收数据

client.onConnect = function(frame) {
  // 连接成功后,在这里订阅消息
  // 举个例子,订阅 test 队列的消息,实时接收数据
  const subscription = client.subscribe(
    '/queue/test',
    (message) => {
      if (message.headers['content-type'] === 'application/octet-stream') {
        // 这里接收 进制 数据
        // 使用 message.binaryBody
      } else {
        // 这里接收文本数据
        // 使用 message.body
      }
    },
    {} // 这个参数是 headers,根据场景需要填写,默认为空
  )
}

当接收到数据,发现是这样的:

image.png

这时候就需要用到解码的文件 base.js,先导入,定义所需的 message,这里是 User

import protoRoot from '@/proto/base'
const User = protoRoot.lookup('User')

接着就可以进行解码数据:

client.onConnect = function(frame) {
  // 连接成功后,在这里订阅消息
  // 举个例子,订阅 test 队列的消息,实时接收消息
  const subscription = client.subscribe(
    '/queue/test',
    (message) => {
      if (message.headers['content-type'] === 'application/octet-stream') {
        // 这里接收 进制 数据
        // 使用 message.binaryBody
        const data = User.decode(message.binaryBody)
        console.log(data)
      } else {
        // 这里接收文本数据
        // 使用 message.body
      }
    },
    {} // 这个参数是 headers,根据场景需要填写,默认为空
  )
}

打印数据,发现已经自动转成了对象,格式就是 User.proto 文件中定义的那样,现在就可以正常使用接收的数据了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值