CS 清理接口特性

1. 功能需求

1.1 背景

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

1.2 目标

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

2. 总体设计

本次需求涉及ContextService下的cs-client、cs-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_time 和 access_time 由上游接口主动调用,在update接口中,update_time 和 access_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-cs cs-client 增加批量清理接口相关java sdk api接口
Linkis-ps-cs cs-server 增加批量清理接口相关restful接口
linkis-ps-cs cs-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 访问结束时间 query false string
accessTimeStart 访问开始时间 query false string
createTimeEnd 创建结束时间 query false string
createTimeStart 创建时间 query false string
pageNow 页码 query false string
pageSize 页面大小 query false string
updateTimeEnd 更新结束时间 query false string
updateTimeStart 更新时间 query false string

响应状态:

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

响应参数:

参数名称 参数说明 类型 schema
data 数据集 object
message 描述 string
method 请求url string
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集合 false String String

响应参数:

参数名称 参数说明 类型 schema
data 数据集 object
message 描述 string
method 请求url string
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 访问时间结束 false String String
accessTimeStart 访问时间开始 false String String
createTimeEnd 创建时间结束 false String String
createTimeStart 创建时间 false String String
updateTimeStart 更新开始时间 false String String

响应参数:

参数名称 参数说明 类型 schema
data 数据集 object
message 描述 string
method 请求url string
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>

9. # 代码参考如下

12. String createTimeStart = "2022-05-26 22:04:00";
13. String createTimeEnd = "2022-06-01 24:00:00";

16. ContextClient contextClient = ContextClientFactory.getOrCreateContextClient();

18. # 接口1 searchHAIDByTime
19. List<String> idList =
20. contextClient.searchHAIDByTime(
21. createTimeStart, createTimeEnd, null, null, null, null, 0, 0);

24. for (String id : idList) {
25. System.out.println(id);
26. }

29. System.out.println("Got " + idList.size() + " ids.");

32. if (idList.size() > 0) {
33. String id1 = idList.get(0);
34. System.out.println("will clear context of id : " + id1);
35. }

38. # 接口2 batchClearContextByHAID
39. List<String> tmpList = new ArrayList<>();
40. tmpList.add(id1);
41. int num = contextClient.batchClearContextByHAID(tmpList);
42. System.out.println("Succeed to clear  " + num + " ids.");

44. # 接口3  batchClearContextByTime
45. int num1 =
46. contextClient.batchClearContextByTime(
47. createTimeStart, createTimeEnd, null, null, null, null);
48. 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微服务本身的高可用能力。