【Golang】动态路由 WebSocket 消息到 gRPC 服务 - 【Invoke】

动态路由 WebSocket 消息到 gRPC 服务 - 【Invoke】

有时候,我们需要将通过 WebSocket 收到的消息动态路由到不同的 gRPC 服务。需要支持动态删减服务,动态删减rpc方法。

这篇博客将介绍如何使用 Go 实现这一功能。我们将重点解析 CallInvoke 方法,该方法接受一个消息类型和数据,然后将其转发到相应的 gRPC 服务并返回结果。

代码解析

以下是 CallInvoke 方法的实现:

func CallInvoke(ttype string, datas []byte) ([]byte, string, error) {
    var err error
    array := strings.Split(ttype, ".")
    servername := array[0]
    method := array[1]
    rpcConn := getRpcConnect(servername)
    if st != nil {
        req := &Common.Empty{}
        ack := &Common.Empty{}
        if err = proto.Unmarshal(datas, req); err != nil {
            goto endFunc
        }
        ctx, cancel := context.WithTimeout(context.Background(), time.Second30)
        defer cancel()
        funcName := strings.Replace(method, "Req", "", -1)
        fullPath := fmt.Sprintf("/%s.%sService/%s", servername, servername, funcName)
        log.Printf("invoke req : %s", fullPath)
        err = rpcConn.Invoke(ctx, fullPath, req, ack)
        if err != nil {
            goto endFunc
        }
        data, err := proto.Marshal(ack)
        if err != nil {
            goto endFunc
        }
        log.Printf("invoke ack : success", ack)
        return data, servername + "." + funcName + "Ack", nil
    }
endFunc:
    if err != nil {
        log.Printf("invoke ttype:%s err:", ttype, err.Error())
        return []byte(servername), "", err
    }
    return nil, "", nil
}

主要步骤解析

  1. 解析消息类型

    array := strings.Split(ttype, ".")
    servername := array[0]
    method := array[1]
    

    将通过 WebSocket 收到的消息类型(例如 “Service.MethodReq”)分解为服务名和方法名。

  2. 建立 gRPC 连接

    rpcConn := getRpcConnect(service)
    

    调用 getRpcConnect 函数获取gRPC 连接。

  3. 初始化请求和响应对象

    req := &Common.Empty{}
    ack := &Common.Empty{}
    if err = proto.Unmarshal(datas, req); err != nil {
        goto endFunc
    }
    

    Common.Empty为空proto结构体,将通过 WebSocket 接收到的数据反序列化为请求对象 req。如果反序列化失败,跳转到 endFunc 标签。

  4. 设置上下文和超时

    ctx, cancel := context.WithTimeout(context.Background(), time.Second30)
    defer cancel()
    

    创建一个上下文,并设置一个 30 秒的超时时间。

  5. 构造 gRPC 方法全路径并调用

    funcName := strings.Replace(method, "Req", "", -1)
    fullPath := fmt.Sprintf("/%s.%sService/%s", servername, servername, funcName)
    log.Printf("invoke req : %s", fullPath)
    err = rpcConn.Invoke(ctx, fullPath, req, ack)
    if err != nil {
        goto endFunc
    }
    

    构造 gRPC 方法的全路径(例如 /Service.ServiceService/Method),并通过 Invoke 方法调用该 gRPC 服务。如果调用失败,跳转到 endFunc 标签。

  6. 处理响应

    data, err := proto.Marshal(ack)
    if err != nil {
        goto endFunc
    }
    log.Printf("invoke ack : success", ack)
    return data, servername + "." + funcName + "Ack", nil
    

    将响应对象 ack 序列化为字节数组,并返回给调用者。如果序列化失败,跳转到 endFunc 标签。

  7. 错误处理

    endFunc:
    if err != nil {
        log.Printf("invoke ttype:%s err:", ttype, err.Error())
        return []byte(servername), "-1", err
    }
    return nil, "", nil
    

    在错误处理部分,记录错误日志并返回错误信息。

总结

通过这段代码,我们展示了如何将 WebSocket 消息动态路由到 gRPC 服务。该方法不仅处理了请求的反序列化和响应的序列化,还包括了上下文管理和超时设置。这样,你就可以在后端灵活地处理来自不同客户端的请求,并将它们路由到合适的 gRPC 服务进行处理。

希望这篇博客能帮助你理解如何实现消息的动态路由!如果你有任何疑问,请随时留言。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值