协议变更和蓝绿发布
在开发新版本接口时,经常会出现协议的变更,这会重新生成 ServiceProto 然后同步到客户端项目。 这里牵扯出重要的一个问题:新生成的 ServiceProto 与旧的能保持兼容吗? 如果贸然更新服务端,是否会引发旧版协议客户端的异常?
通常有几种情况。
类型兼容的情况
新协议的在类型层面兼容旧协议,这种情况下新旧协议是兼容的,可以无缝切换,例如:
旧协议
export interface ReqSubmit {
name: string
}
export interface ResSubmit {
id: number
}
新协议
export interface ReqSubmit {
name: string,
age?: number
}
export interface ResSubmit {
id: number,
time: Date
}
- 新协议的请求虽然多了一个
age
字段,但由于是可选的,所以旧版协议的请求也能够兼容 - 新协议的响应虽然多了一个
time
字段,对于旧版协议它是一个多余字段,会被自动剔除
类型不兼容的情况
例如:
旧协议
export interface ReqSubmit {
name: string
}
export interface ResSubmit {
id: number
}
新协议
export interface ReqSubmit {
name: string,
age: number
}
export interface ResSubmit {
newId: number
}
- 新协议的请求多了必需的
age
字段,如此旧协议的请求便会收到 “缺少必需字段age
” 的报错 - 新协议的响应缺少了旧协议必需的
id
字段,如此旧协议的响应便会收到 “缺少必需字段id
”的报错
这种情况下新旧协议类型不兼容,如果贸然更新服务端版本,可能导致旧协议的客户端出现报错。
这种情况下,也有一些解决方案,例如:
- 旧接口不变,而是写一个新的接口
Submit_1
,如此就变成了类型兼容的情况,可以无缝切换 - 蓝绿发布
蓝绿发布
无论哪种情况,你都可以使用蓝绿发布来避免因协议变更导致的问题。
- 先发布服务端,发布到不同的 URL 下
- 例如旧版
/api/v1/
,新版/api/v2/
- 例如旧版
- 再发布客户端,客户端切换到新版 URL
- 发布完成后,等待一段时间,再弃用旧版接口
- 因为可能仍有部分用户停留在旧版应用中没有刷新
已知问题
如果你新增的字段中包含了索引签名,例如:
// 旧协议
export interface ResXXX {
a: string
}
// 新协议
export interface ResXXX {
a: string,
b: { [key: string]: number }
}
此时可能由于编码机制原因,导致旧协议的客户端无法兼容。
这个问题出现概率极小,会在 TSRPC 4.0 中解决。
目前,你可以通过把新字段类型改为 any
临时解决:
// 新协议
export interface ResXXX {
a: string,
b: any
}
当然,还是更推荐使用 万能的蓝绿发布。