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

时间:2015-01-05 14:57:27

标签: versioning thrift

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

service Api {
  void invoke()
}

它做了些什么。我想更改行为以执行其他操作,但仍然保留旧行为的客户端的旧行为。

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

2 个答案:

答案 0 :(得分:5)

软版本化

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

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

由于新添加的参数在技术上是可选的,因此任意客户端请求可能包含也可能不包含它们,或者可能只包含部分请求(例如,指定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
}

required永远是

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

这不是普通字段或optional字段的问题,因为Thrift旨在跳过未知字段(类型ID包含在线数据中),只是忽略缺少的字段。相反,对required字段应用其他检查以确保它们出现在有线数据中。

端点

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

或者,Thrift 0.9.2引入的multiplex protocol可用于在同一端点上提供多个服务和/或服务版本(即套接字,http URI,......)

答案 1 :(得分:0)

对于您的特定场景,您可以添加一个新方法(命名为其他方式)来执行新操作。将来,出于这个原因,我会避免命名方法invoke或类似方法。您的服务现在将有一个方法invoke执行一些未知的操作,另一个方法(希望更好地命名)可以完成它所说的功能。这可能会导致您的用户感到困惑,但一切仍然有效。