CS 清理接口特性

1. 功能需求

1.1 背景

1.1.3版本前,ContextService 统一上下文服务缺少清理机制,且缺少创建时间、更新时间字段以及批量清理的接口, 在长期累积情况下可能出现百万级数据,影响查询效率。

1.2 目标

  • 修改1ContextService底层库表,添加创建时间、修改时间、最后访问时间字段,完成ContextIDContextMap`相关数据的更新时间入库
  • 添加清理清理的restful接口,支持按照时间范围、按照id列表的批零清理接口
  • 添加对应的cs-clientjava sdk接口

2. 总体设计

本次需求涉及ContextService下的cs-clientcs-persistence以及cs-server模块。 在cs-persistence模块添加已有表的3个字段;在cs-server模块添加3个restful接口,在cs-client模块添加3个sdk api

2.1 技术架构

ContextService 整体架构可参考已有文档: ContextService架构文档

ContestService各模块访问关系如下图所示 linkis-contextservice-clean-01.png

表变更均在cs-persistence模块。此次变更涉及5张表context_id、 context_map 、context_id_listener 、context_key_listener 、 context_history表,均需要添加create_time,update_time,access_time 3个字段。其中context_id 、context_map 表已启用,其它3张表未启用。create_time 在persistence模块执行insert操作前,添加时间。update_timeaccess_time 由上游接口主动调用,在update接口中,update_timeaccess_time 互斥更新,即当access_time 存在(不为null)则不更新update_time,否则更新update_time。

update_time字段更新在cs-cache模块中,检测到从db加载新的context_id时的ADD消息,此时同步access_time 到db。 表中仅记录context_id 表的create_time、update_time、access_time。后续搜索清理,也是从context_id 表进行清理。

增加3个清理相关接口:searchContextIDByTime、clearAllContextByID、clearAllContextByTime

  • searchContextIDByTime按照3个时间起止范围搜索,返回contextID列表
  • clearAllContextByID清理输入的contextID列表中ID对应的context_map表和context_id表内容
  • clearAllContextByTime 按照3个时间起止范围搜索,并且清理所有搜索到的contextID对应的context_map表和context_id表的内容

2.2 业务架构 此次特性是给ContextService服务增加批量查询和清理的相关接口,以及增加底层数据表的更新时间等字段,便于根据访问情况清理过期数据。功能点涉及模块如下表。

一级模块二级模块功能点
linkis-ps-cscs-client增加批量清理接口相关java sdk api接口
Linkis-ps-cscs-server增加批量清理接口相关restful接口
linkis-ps-cscs-persistence增加底层表的3个时间相关字段

3. 模块设计 ###主要执行流程

  • 创建ContextID。用户创建ContextID时,会记录create_time,后期不更新这个字段
  • 更新ContextID。用户更新ContextID时,会更新update_time字段。注意此时更新如果是从cache中更新,则不会跟新access_time字段;如果从db加载到cache,再跟新contextID,则会先更新access_time,然后单独跟新update_time
  • 根据时间查询ContextID。用户查询对应时间范围的ContextID,仅会返回haid字符串列表。此接口有分页,默认仅限5000条数据
  • 批量清理ContextID。会批量清理传入的idList对应的所有contextMap数据和contextID数据。传入数组最大5000条
  • 查询并清理ContextID,先查询再批量清理

上述对应时序图如下: linkis-contextservice-clean-02.png

其中有两处需要额外注意: ①cs-server服务中restful api,会将请求封装成Job提交到队列并阻塞等待结果。新定义了CLEAR 的操作类型,便于匹配到清理相关接口。 ②处理①中Job的Service服务,需要将名称定义为不包含ContextID,来避免HighAvailable模块的动态代理转换,这个转换仅对于请求内只有一个ContextID的接口,对于批量清理和批量查询接口无意义且影响性能。

4. 数据结构

  1. # 主要涉及的context_id表结构如下,增加了create_time、update_time、expire_time字段
  2. CREATE TABLE `linkis_ps_cs_context_id` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT,
  4. `user` varchar(32) DEFAULT NULL,
  5. `application` varchar(32) DEFAULT NULL,
  6. `source` varchar(255) DEFAULT NULL,
  7. `expire_type` varchar(32) DEFAULT NULL,
  8. `expire_time` datetime DEFAULT NULL,
  9. `instance` varchar(128) DEFAULT NULL,
  10. `backup_instance` varchar(255) DEFAULT NULL,
  11. `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'update unix timestamp',
  12. `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time',
  13. `access_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'last access time',
  14. PRIMARY KEY (`id`),
  15. KEY `instance` (`instance`(128)),
  16. KEY `backup_instance` (`backup_instance`(191)),
  17. KEY `instance_2` (`instance`(128),`backup_instance`(128))
  18. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5. 接口设计 ###5.1 Restful接口

搜索文本Id执行时间

接口地址:/api/rest_j/v1/contextservice/searchContextIDByTime

请求方式:GET

请求数据类型:application/x-www-form-urlencoded

响应数据类型:*/*

接口描述:

搜索文本Id执行时间

请求参数:

参数名称参数说明请求类型是否必须数据类型schema
accessTimeEnd访问结束时间queryfalsestring
accessTimeStart访问开始时间queryfalsestring
createTimeEnd创建结束时间queryfalsestring
createTimeStart创建时间queryfalsestring
pageNow页码queryfalsestring
pageSize页面大小queryfalsestring
updateTimeEnd更新结束时间queryfalsestring
updateTimeStart更新时间queryfalsestring

响应状态:

状态码说明schema
200OKMessage
401Unauthorized
403Forbidden
404Not Found

响应参数:

参数名称参数说明类型schema
data数据集object
message描述string
method请求urlstring
status状态integer(int32)integer(int32)

响应示例:

  1. {
  2. "method": "/api/contextservice/searchContextIDByTime",
  3. "status": 0,
  4. "message": "OK",
  5. "data": {
  6. "contextIDs": [
  7. "8-8--cs_1_devcs_2_dev10493",
  8. "8-8--cs_1_devcs_2_dev10494",
  9. "8-8--cs_1_devcs_2_dev10495",
  10. "8-8--cs_1_devcs_2_dev10496",
  11. "8-8--cs_1_devcs_2_dev10497",
  12. "8-8--cs_2_devcs_2_dev10498"
  13. ]
  14. }
  15. }

清理指定ID

接口地址:/api/rest_j/v1/contextservice/clearAllContextByID

请求方式:POST

请求数据类型:application/json

响应数据类型:*/*

接口描述:

通过ID清除所以上下文

请求参数:

参数名称参数说明是否必须请求类型数据类型schema
idList上下文id集合falseStringString

响应参数:

参数名称参数说明类型schema
data数据集object
message描述string
method请求urlstring
status状态integer(int32)integer(int32)

响应示例:

  1. {
  2. "method": "/api/contextservice/clearAllContextByID",
  3. "status": 0,
  4. "message": "OK",
  5. "data": {
  6. "num": "1"
  7. }
  8. }

通过时间清除所以上下文

接口地址:/api/rest_j/v1/contextservice/clearAllContextByTime

请求方式:POST

请求数据类型:application/json

响应数据类型:*/*

接口描述:

通过时间清除所以上下文

请求参数:

参数名称参数说明是否必须请求类型数据类型schema
accessTimeEnd访问时间结束falseStringString
accessTimeStart访问时间开始falseStringString
createTimeEnd创建时间结束falseStringString
createTimeStart创建时间falseStringString
updateTimeStart更新开始时间falseStringString

响应参数:

参数名称参数说明类型schema
data数据集object
message描述string
method请求urlstring
status状态integer(int32)integer(int32)

输入参数示例

  1. {
  2. "createTimeStart": "2022-06-01 00:00:00",
  3. "createTimeEnd": "2022-06-30 00:00:00"
  4. }

响应示例:

  1. {
  2. "method": "/api/contextservice/clearAllContextByTime",
  3. "status": 0,
  4. "message": "OK",
  5. "data": {
  6. "num": "1"
  7. }
  8. }

5.2 JAVA SDK API

  1. # 引入pom
  2. <dependency>
  3. <groupId>org.apache.linkis</groupId>
  4. <artifactId>linkis-cs-client</artifactId>
  5. <version>1.1.3</version>
  6. </dependency>
  7. # 代码参考如下
  8. String createTimeStart = "2022-05-26 22:04:00";
  9. String createTimeEnd = "2022-06-01 24:00:00";
  10. ContextClient contextClient = ContextClientFactory.getOrCreateContextClient();
  11. # 接口1 searchHAIDByTime
  12. List<String> idList =
  13. contextClient.searchHAIDByTime(
  14. createTimeStart, createTimeEnd, null, null, null, null, 0, 0);
  15. for (String id : idList) {
  16. System.out.println(id);
  17. }
  18. System.out.println("Got " + idList.size() + " ids.");
  19. if (idList.size() > 0) {
  20. String id1 = idList.get(0);
  21. System.out.println("will clear context of id : " + id1);
  22. }
  23. # 接口2 batchClearContextByHAID
  24. List<String> tmpList = new ArrayList<>();
  25. tmpList.add(id1);
  26. int num = contextClient.batchClearContextByHAID(tmpList);
  27. System.out.println("Succeed to clear " + num + " ids.");
  28. # 接口3 batchClearContextByTime
  29. int num1 =
  30. contextClient.batchClearContextByTime(
  31. createTimeStart, createTimeEnd, null, null, null, null);
  32. System.out.println("Succeed to clear " + num1 + " ids by time.");

6. 非功能性设计

6.1 安全

resultful接口需要登录认证,且需要管理员才能操作,管理员用户配置在properties文件中

6.2 性能

  • 查询ID接口searchContextIDByTime有分页,无性能影响
  • 清理指定ID接口clearAllContextByID限制操作数据量,无性能影响
  • 根据时间清理接口clearAllContextByTime,如果查询时间范围过大,可能会有查询超时,但不会任务失败。并且清理操作是单个操作,不会影响其他查询

6.3 容量

本需求提供了时间范围查询和批量清理接口,需要上层使用ContextService的应用主动清理数据。

6.4 高可用

接口复用ContextService微服务本身的高可用能力。