Thrift文件(api)版本控制的最佳实践是什么?

Ali*_*aka 4 versioning thrift

我有一个用thrift编写的API.例:

service Api {
  void invoke()
}
Run Code Online (Sandbox Code Playgroud)

它做了一些事情.我想改变行为以做其他事情,但仍然保留旧行为的客户端的旧行为.

处理新API版本的最佳做法是什么?

Jen*_*nsG 5

软版本

Thrift支持软版本控制,因此完成您的服务版本2是完全有效的,如下所示:

service Api {
   void invoke(1: string optional_arg1, 2: i32 optional_arg2) throws (1: MyError e)
   i32 number_of_invokes()
}
Run Code Online (Sandbox Code Playgroud)

由于新添加的参数在技术上是可选的,因此任意客户端请求可能包含也可能不包含它们,或者可能只包含其中的一部分(例如,指定arg1但不包含arg2).例外情况有点不同,旧客户端会引发某种通用意外异常或类似情况.

甚至可以完全删除过时的函数,在这种情况下,旧客户端在尝试调用(现在不存在的)已删除函数时将获得异常.

对于向成员,异常等添加成员字段,所有上述情况都是如此.建议不要从IDL文件中删除声明,而是注释掉旧的已删除成员字段和函数以防止人们重新使用旧字段更高版本中的ID,旧函数名称或旧枚举值.

struct foobar {
  // API 1.0 fields
  1: i32 foo
  //2: i32 bar   - obsolete with API 2.0

  // API 2.0 fields
  3: i32 baz
}
Run Code Online (Sandbox Code Playgroud)

required 永远

您需要注意的是使用关键字required.一旦使用包含required成员的结构发布API ,您将需要携带此结构,直到删除整个结构.required稍后添加新字段也是如此.否则你冒着破坏性变化的风险,因为混合新旧客户端和服务器迟早会产生一种情况,即一端绝对需要某个required成员字段,但另一端无法提供,只是因为它对此一无所知.

这不是普通或optional字段的问题,因为Thrift旨在跳过未知字段(类型ID包含在线数据中),并且只是忽略丢失的字段.相反,对required字段应用附加检查以确保它们存在于有线数据中.

端点

虽然软版本控制是一个很好的工具,但它的代价是由于需要兼容而累积负担.此外,在某些情况下,您的API将进行重大更改,故意不会向后兼容.在这种情况下,建议将新服务设置在不同的端点.

或者,Thrift 0.9.2引入的Multiplex协议可用于在同一端点上提供多个服务和/或服务版本(即socket,http URI,...)