概述

在Request-Response模式下,网关需要将后端模块返回的数据在返回给客户端即Response,此时需要网关与客户端约定一套数据结构,方便客户端解析

客户端与网关是长连接,因此不同的mqtt包会交叉传递

示例时序图

sequenceDiagram participant 客户端 participant 网关 participant 后端模块 客户端 ->> 网关:Request01(topic=HelloWord/HD_Say/001) 网关 ->> 后端模块:RPC01 客户端 ->> 网关:Request02(topic=HelloWord/HD_Login/002) 网关 ->> 后端模块:RPC02 后端模块 -->> 网关:RPC01 网关 -->> 客户端:Response01(topic=HelloWord/HD_Say/001) 客户端 ->> 网关:Request03(topic=HelloWord/HD_Say/003) 网关 ->> 后端模块:RPC03 后端模块 -->> 网关:RPC03 网关 -->> 客户端:Response03(topic=HelloWord/HD_Say/003) 后端模块 -->> 网关:RPC02 网关 -->> 客户端:Response02(topic=HelloWord/HD_Login/002)

主题(topic)

Response时,网关发送给客户端的topic跟Request时完全一致,因此客户端可通过唯一topic确定返回数据是哪个请求的。

消息体(body)

mqant默认封装规则

mqant默认封装为json结构体,具体结构如下

{
        Error string
        Result interface{}
}

Result

代表hander函数执行正确时返回的结果

类型

  1. bool
  2. int32
  3. int64
  4. long64
  5. float32
  6. float64
  7. []byte
  8. string
  9. map[string]interface{}

Error

代表hander函数执行错误时返回的错误描述

类型

  1. string
  2. error

自定义返回格式

mqant默认规则使用json来封装,但实际情况下不同的应用场景可能需要的封装数据格式有所不同,例如有些场景倾向于用protobuf封装。 且默认的封装规则不支持自定义数据类型。

app.SetProtocolMarshal(func(Result interface{},Error string)(module.ProtocolMarshal,string){
            //下面可以实现你自己的封装规则(数据结构)
            r := &resultInfo{
                Error:  Error,
                Result: Result,
            }
            b,err:= json.Marshal(r)
            if err == nil {
                //解析得到[]byte后用NewProtocolMarshal封装为module.ProtocolMarshal
                return app.NewProtocolMarshal(b),""
            } else {
                return nil,err.Error()
            }
})

ProtocolMarshal

如下 mqant默认返回值是这样的 result map[string][string], err string

func (m *Login) login(session gate.Session, msg map[string]interface{}) (result map[string][string], err string) {
        。。。
        return map[string][string]{
            "info":"login success"
        }, ""
}

rpc通信编码/解密流程: map—>[]byte ——— []byte—>map—>[]byte—> client

最终发送给客户端的是[]byte类型,中间经历一次 []byte—>map—>[]byte 的无用编解码流程

如何省掉无效的编解码流程呢?

答案: 在后端模块提前编码为[]byte类型,如何实现见以下代码:

func (this *Login) login(session gate.Session, msg map[string]interface{}) (result module.ProtocolMarshal, err string) {
        return this.App.ProtocolMarshal("","login success","")
}

实现原理:

返回值用 this.App.ProtocolMarshal 函数封装一遍即可,返回值改为了module.ProtocolMarshal类型

Copyright © 梁大帅 2020 all right reserved,powered by Gitbook该文件修订时间: 2020-05-05 22:55:13

results matching ""

    No results matching ""