我使用带协议缓冲区的gRPC实现了API服务,然后使用grpc-gateway将其公开为一组REST Web服务。
现在我已经到了必须维护不同版本API的地步,而且我已经卡住了。
在我的proto文件中,我有一个像这样定义的处理程序
rpc MerchantGet (MerchantRequest) returns (MerchantResponse) {
option (google.api.http) = {
get: "/v1.1.0/myapi/merchant/{MerchantID}"
};
}
在我的Go代码中,我当然有一个函数MerchantGet
,GET
/v1.1.0/myapi/merchant/{MerchantID}
行动到MerchantGet
。
现在,让我们说我想为MerchantGet
方法添加更多功能并发布新版本。我打算按照Semantic Versioning Specification保持向后兼容性,所以如果我理解正确,这意味着我可以对我的MerchantRequest
方法进行基础更改并让它取代旧方法,只要它不需要不同的输入来自第三方(MerchantResponse
)或更改发送给第三方(rpc MerchantGet (MerchantRequest) returns (MerchantResponse) {
option (google.api.http) = {
get: "/v1.6.0/myapi/merchant/{MerchantID}"
additional_bindings {
get: "/v1.5.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.4.2/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.4.1/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.4.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.3.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.2.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.1.0/myapi/merchant/{MerchantID}"
}
};
}
)的响应,而不是在响应结尾添加其他字段。 (如果我在这个假设中错了,请纠正我。)
我的问题是,我如何编写proto处理程序来为不同版本的端点提供方法?想到的一个选项看起来如下:
additional_bindings
但这肯定不是实现这一目标的惯用方法吗?它当然不是很优雅,因为每个新的次要版本或补丁,我都必须将这些with cte (fromid, toid, groupkey, sortkey) as
(
select
fromid,
toid,
row_number() over (order by fromid) as groupkey,
1 as sortkey
from mytable
where toid not in (select fromid from mytable)
union all
select
m.fromid,
m.toid,
cte.groupkey,
cte.sortkey - 1
from mytable m
join cte on cte.fromid = m.toid
)
select fromid, toid
from cte
order by groupkey, sortkey;
扩展到我的每个方法(上面我只使用一种方法作为例子)。
答案 0 :(得分:3)
来自SemVer规范:
给定版本号MAJOR.MINOR.PATCH,增加:
- 当您进行不兼容的API更改时的MAJOR版本,
- 以向后兼容的方式添加功能时的MINOR版本,
当您进行向后兼容的错误修复时,- PATCH版本。
醇>预发布和构建元数据的附加标签可作为MAJOR.MINOR.PATCH格式的扩展。
与REST端点版本控制相关的唯一版本是MAJOR版本,因为所有MINOR和PATCH更改必须向后兼容。
回答你的问题:
仅使用REST URI中的主要版本号。从REST的角度来看,其余部分是一个实现细节。
所以,您的原型服务将是:
rpc MerchantGet (MerchantRequest) returns (MerchantResponse) {
option (google.api.http) = {
get: "/v1/myapi/merchant/{MerchantID}"
};
}