基于事务处理的vpp管控面agent
问题背景
vpp作为vrouter,类似物理交换机,各配置项依赖关系复杂。以下为vpp配置abf策略路由的例子:
typedef abf_policy
{
u32 policy_id;
u32 acl_index; //依赖acl
u8 n_paths;
vl_api_fib_path_t paths[n_paths];
};
autoreply define abf_policy_add_del
{
option status="in_progress";
u32 client_index;
u32 context;
bool is_add;
vl_api_abf_policy_t policy;
};
typedef abf_itf_attach
{
u32 policy_id;
vl_api_interface_index_t sw_if_index; //依赖interface,interface又会依赖其他资源
u32 priority;
bool is_ipv6;
};
可以看到,策略路由首先依赖acl规则,之后将abf绑定至接口时需要依赖对应interface的index,且创建interface又需要依赖其他资源(绑定vrf等)。
除此之外,vpp配置写入存在中间状态与崩溃的问题,且无法避免。“崩溃”类似数据库写入的概念。数据必须要成功写入磁盘、磁带等持久化存储器后才能拥有持久性,只存储在,内存中的数据,一旦遇到应用程序忽然崩溃,或者数据库、操作系统一侧的崩溃,甚至是机器突然断电宕机等情况就会丢失,这些意外情况都统称为“崩溃”。
因此,为了解决vpp(物理交换机也适用)各配置项的依赖关系,以及保证原子性和持久性,实现崩溃恢复,需要在管控面agent侧处理好上述问题。
事务处理
本人对分布式事务领域涉及不深,以下摘自于
本地事务(也可称为局部事务),是单个服务使用单个数据源场景,也就是最基本的本地数据落盘的事务。本地事务要求底层数据源需要支持事务的开启、终止、提交、回滚、嵌套等。在数据库领域(ARIES理论,基于语义的恢复与隔离),感兴趣的可以研究下commiting logging机制(OceanBase)和shadow paging
全局事务,是单个服务多个数据源场景。主要目的是为了解决事务一致性问题,并做到统一提交,统一回滚的功能。例如我有一个全局事务需要在A表中写入记录a(本地事务A),再在B表中写入记录b(本地事务B),A表和B表分别在两台物理机的磁盘上。在数据存储领域由X/Open XA对此发布了一个事务处理架构,且当前很多分布式事务处理框架都是基于此来设计的。主要核心如下:
- 全局事务管理器(Transaction Manager,TM):协调全局事务
- 局部资源管理器(Resource Manaeger,RM):驱动本地事务
- 模型:XA,TCC,SAGA,AT 。。。
感兴趣的可以研究下阿里的seata。
事务处理视角看待vpp管控面
本地事务
- vpp的配置是内存上的配置,不需要落盘。
- vpp的每个资源的api可视为一个数据源
- 数据源没有实现事务的开启、终止、提交、回滚、嵌套、设置隔离级别等能力,只提供了下发,删除,读取接口
- 上述数据源未提供的能力需要agent来补齐
全局事务
- agent暴露给上层的接口可视为全局事务
- 有些全局事务只涉及单个数据源,有些全局事务涉及多个数据源
- agent内部需要实现TM,将全局事务转为有序的本地事务列表
- agent内部需要实现RM,调用vpp api,驱动本地事务的执行
举例: