找回密码
 立即注册
查看: 246|回复: 0

Protobuf的field_mask功能

[复制链接]
发表于 2022-6-4 13:51 | 显示全部楼层 |阅读模式
这两天看到netflix的技术博客,有两篇关于protobuf的field_mask功能使用。简单研究了下具体功能。这里做一下笔记。
背景

中台服务(Production service)管理着工作室的产品。对外提供了GetProduction接口,通过production_id返回商品的详细信息(format, schedule dates, scripts等等)。但是像产品的schedule和scripts信息,需要访问远端服务进行获取(也就是说schedule和scripts的获取成本很高,需要远端服务访问)。但对于有些请求,不关心schedule和scripts信息,此时对于Production service没必要访问远端。
问题

如何设计一个接口,能够同时满足:
1. 接口Pb结构简单明了
2. 对于调用方不感知的字段,可以跳过(减少服务压力)
解决

通过引入field_mask
import "google/protobuf/field_mask.proto";

// 产品的细节字段
message Production {
  string id = 1;
  string title = 2;
  ProductionFormat format = 3;
  repeated ProductionScript scripts = 4;
  ProductionSchedule schedule = 5;
  // ... more fields
}

// 请求的Pb结构
message GetProductionRequest {
  string production_id = 1;  // 调用方想要获取的商品id
  google.protobuf.FieldMask field_mask = 2;  // 调用方关注的商品字段名
}举例:调用方只关注title信息
客户端代码
GetProductionRequest CreateReq() {
    GetProductionRequest req;
    req.set_production_id("123321");

    auto* field_mast_ptr = req.mutable_field_mask();
    field_mast_ptr->add_paths("title");  // 设置只关注title字段

    return req;
}
服务端
Production GetProduction(GetProductionRequest& req) {
    auto& production_id = req.production_id();
    Production ret = GetFromLocalDb(production_id);  // 获取 title,format等基础信息

    auto schedule_iter = std::find(req.field_mask().begin(),
                                    req.field_mask().end(),
                                    "schedule");
    // 关注schedule,就进行远端调用
    if (schedule_iter != req.field_mask().end()) {

    }

    // 因为ret中可能还有一些调用方不关注的字段
    // 通过这个删除掉
    // 由于field_mask里只有title,其他字段都会清空。也达到了节省带宽
    FieldMaskUtil::TrimMessage(req.field_mask(), &ret);  
}限制

很明显,其实就是强依赖字段名,如果涉及修改,字段名不能随意修改。否在就会失效。文章中提了几个解决办法,但其实最终的意思就是新建一个字段,并标记老字段废弃(pb提供了deprecated)。
message Production {
  string id = 1;
  string title = 2 [deprecated = true];  // use "title_name" field instead
  ProductionFormat format = 3;
  repeated ProductionScript scripts = 4;
  ProductionSchedule schedule = 5;
  string title_name = 6;
}

参考文档

1. protobuf的文档:
2. netflix博客两篇
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-6-17 03:53 , Processed in 0.151072 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表