记一次黑名单方案设计引发的设计思考
背景
接到需求: 某些ECS规格族天然不具备宕机迁移的能力, 例如某些软件License与硬件ID绑定, 或者加密信息与硬件绑定, 宕机迁移会导致License失效或者加密信息无法解密.
而在正常宕机迁移流程里默认所有规格族都会无差别执行.
因此需要代码改造下, 识别这些规格族, 然后跳过执行流程.
解决方案1: 黑名单模式
即在配置项里维护一个黑名单List, 伪代码如下:
blackList = getFromConf();
if(flavorFamily in blackList) {
return;
}
down_migration_execute();
- 优点: 开发起来简便, 灵活. 也是第一反应想到的方案.
- 缺点: 使用该方案, 后续发现问题很多:
- 代码容易踩坑:
- 如果配置项是用数据库字段存储, 那么一定要注意字段的类型&size, 如果太小会导致后续如果名单扩容, 字段溢出, 从而无法实现效果.
- 运维成本过高:
- 因为黑名单与实例规格族本身属性是分散开来的.
- 如果后续新增规格族, 需要有个地方来通知产品的同学,
规格族需要有是否宕机迁移这个属性
, 然后需要他们跑到另外一个地方去维护下这个黑名单. - 尤其是在不同类别的规格族由不同产品同学负责且人员流动性大时, 没办法通知到每位同学.
- 但一旦遗漏, 可能会导致线上问题.
- 代码容易踩坑:
解决方案2: 属性模式
即
- 是否宕机迁移作为一个天然属性/字段, 添加在规格族/规格表上.
- 该属性作为必填属性, 在新规格族上线时, 对应产品在填写其他属性时(例如cpu/mem配比等), 该属性也需要一并填写.
伪代码如下:
flavorDef = getFlavorDef(flavor)
if(!flavorDef.canDownMigration) {
return;
}
down_migration_execute();
- 优点:
- 后续运维成本极低, 新规格族/规格上线时, 该字段与其他属性类似, 作为一个必填选项, 让产品同学统一维护.
- 代码整体也更面向对象一些, 即更加高内聚, 低耦合.
- 缺点:
- 前期改造量&风险较大:
- 表里需要增加字段, 尤其是针对大表且访问频发的表, 有可能锁表, 导致线上问题.
- 如果有存量大量的规格族数据, 需要进行一波批量订正.
- 前期改造量&风险较大:
适用场景探讨
总的来说,
- 黑白名单只适合作为一个短期内临时的方案/开关, 且在不久之后, 黑白名单需要全部清空.
- 例如上述例子中, 某些规格需要 临时 禁止宕机迁移, 但一周之后, 这些规格需要重新enable.
- 这个时候临时使用黑白名单机制凑合下还行.
- 而属性方案, 就更适合作为一个常态化的机制.
- 例如上述例子中, 某些规格需要的
是否禁止宕机迁移
是天然的一个属性, 规格一旦设定为禁止宕机迁移
就不会再修改了.
- 例如上述例子中, 某些规格需要的
总结
更加推荐使用”属性模式”, 这也是一次之前自己错误设计的反思, 也吃到了很大的苦果.
后续在使用”黑/白名单”作为方案前, 一定要再想下是否是临时方案, 如果不是, 那么尽量能作为实体上的一个属性来维护.
虽然属性方案, 前期改造量可能较大, 但长期来看, 优点是远远大于缺点的.