secretpad icon indicating copy to clipboard operation
secretpad copied to clipboard

secretpad 集成mysql 8.0后调用接口超时

Open ougyou opened this issue 8 months ago • 8 comments

Issue Type

Others

Have you searched for existing documents and issues?

Yes

OS Platform and Distribution

centos 7

All_in_one Version

0.11.x

Kuscia Version

0.7.0

What happend and What you expected to happen.

我们将secretpad从sqllite切换成了mysql8.0,但调用结果表接口的时候超时,超时刚好是5s,为future.get设置的超时时间5s NodeServiceImpl#listAllNodeResults

Image

Image

在future 进行get的时候超时 Image

我把这段处理改成串行化的,不适用future的异步池化处理的话接口就很快可以响应了

Image

ougyou avatar May 08 '25 08:05 ougyou

问一下最新版本集成MySQL需要那些操作那,我看其他回答需要补字段补表,麻烦解答一下,感谢

Bossama777 avatar May 09 '25 01:05 Bossama777

1.方便给一下你改造后的代码吗,我们看下;以及异步场景下,超时是必现的吗? 2.可以参考这里

zimu-yuxi avatar May 09 '25 02:05 zimu-yuxi

1.方便给一下你改造后的代码吗,我们看下;以及异步场景下,超时是必现的吗? 2.可以参考这里

是根据参考文档中的操作来的,目前结果表接口是必现的,而且接口的超时时间是根据future.get设置的那个时间来的,调整后的代码就完全没有阻塞,我看了下future使用的executor也只是一个普通的线程池 `

public AllNodeResultsListVO listAllNodeResults(ListNodeResultRequest request) {

    List<String> nodeIds = new ArrayList<>();
    if (envService.isAutonomy()) {
        nodeIds.addAll(nodeManager.listReadyNodeByIds(InstServiceImpl.INST_ID, request.getNodeNamesFilter()));
    } else {
        nodeIds.add(request.getOwnerId());
    }

    List<NodeAllResultsVO> nodeAllResultsVOList = new ArrayList<>();
    int totalNodeResultNum = 0;
    Map<String, String> errorMap = new HashMap<>();

    for (String nodeId : nodeIds) {
        try {
            // 1. 创建请求并获取结果
            ListNodeResultRequest nodeResultRequest = createNodeRequest(request, nodeId);
            NodeResultsListVO nodeResultsListVO = listResults(nodeResultRequest);

            // 2. 查询节点信息
            NodeDO nodeDO = nodeRepository.findByNodeId(nodeId);
            if (nodeDO == null) {
                String errorMsg = "Cannot find node by nodeId " + nodeId;
                LOGGER.error(errorMsg);
                errorMap.put(nodeId, errorMsg);
                continue;
            }

            // 3. 处理结果数据
            totalNodeResultNum += nodeResultsListVO.getTotalResultNums();
            for (NodeResultsVO nodeResultsVO : nodeResultsListVO.getNodeResultsVOList()) {
                nodeAllResultsVOList.add(NodeAllResultsVO.builder()
                        .nodeResultsVO(nodeResultsVO)
                        .nodeId(nodeId)
                        .nodeName(nodeDO.getName())
                        .build());
            }
        } catch (Exception ex) {
            // 4. 异常处理
            LOGGER.error("Error processing nodeId {}: {}", nodeId, ex.getMessage(), ex);
            errorMap.put(nodeId, ex.getMessage());
        }
    }

    List<NodeAllResultsVO> rangeVOList = PageUtils.rangeList(nodeAllResultsVOList, request.getPageSize(), request.getPageNumber());

    //fill datatable info
    List<Domaindata.DomainData> domainDataList = datatableManager.findByIdGroup(rangeVOList.stream().map(it -> DatatableDTO.NodeDatatableId.from(it.getNodeId(), it.getNodeResultsVO().getDomainDataId())).toList(), (currentNodeId, extra) -> currentNodeId);
    Map<String, Domaindata.DomainData> dataIdMap = domainDataList.stream().collect(Collectors.toMap(it -> it.getDomaindataId(), Function.identity()));

    //multi thread datasource
    Set<DatasourceDTO.NodeDatasourceId> datasourceIds = domainDataList.stream().map(data -> DatasourceDTO.NodeDatasourceId.from(data.getDomainId(), data.getDatasourceId())).collect(Collectors.toSet());
    Map<String, String> datasourceIdTypeMap = datasourceIds.stream()
            .map(sourceId -> {
                Optional<DatasourceDTO> result = datasourceManager.findById(sourceId);
                return result.isPresent() ? result.get() : null;
            }).filter(Objects::nonNull)
            .collect(Collectors.toMap(dto -> dto.getDatasourceId(), dto -> dto.getType(), (a, b) -> a));

    rangeVOList.stream().forEach(vo -> {
        String domainDataId = vo.getNodeResultsVO().getDomainDataId();
        Domaindata.DomainData domainData = dataIdMap.get(domainDataId);
        if(domainData!=null){
            vo.getNodeResultsVO().setRelativeUri(domainData.getRelativeUri());
            vo.getNodeResultsVO().setDatasourceId(domainData.getDatasourceId());
            vo.getNodeResultsVO().setDatatableType(domainData.getType());
            vo.getNodeResultsVO().setDatasourceType(DataSourceTypeEnum.kuscia2platform(datasourceIdTypeMap.get(domainData.getDatasourceId())));
        }
    });


    return AllNodeResultsListVO.builder()
            .nodeAllResultsVOList(rangeVOList)
            .totalNodeResultNums(totalNodeResultNum)
            .build();
}

`

ougyou avatar May 09 '25 03:05 ougyou

核心不在mysql,在kuscia 的 domiandata 接口,这个接口在数据量大时会很慢「已知问题」后续我们会主要解决的是这个问题,可以清理下不用的domaindata后再验证下

zimu-yuxi avatar May 09 '25 10:05 zimu-yuxi

核心不在mysql,在kuscia 的 domiandata 接口,这个接口在数据量大时会很慢「已知问题」后续我们会主要解决的是这个问题,可以清理下不用的domaindata后再验证下

你意思这个executor底层是调用了kuscia 的domaindata接口?也没在那个方法的调用栈中有看到关于kuscia的调用;我们换成sqllite就可以很快返回,并且kuscia是新部署的,是没有任何数据的,如果kuscia慢那么应该就不应该是由sqllite切换成mysql导致的这个问题

1、基于sqllite的异步调用是ok,改成mysql就会出现future.get的timeout问题出现,不管timeout设置成多少都是雷打不动的超时 2、我们改成串行化的执行方式是否可以,除性能考虑外是否对整理逻辑有什么影响

ougyou avatar May 09 '25 10:05 ougyou

1.可以看下mysql的max_execution_time配置,是否有配置 2.可以的,没有影响

zimu-yuxi avatar May 12 '25 02:05 zimu-yuxi

可以解答一下如何最新版本切换数据源吗?

Bossama777 avatar May 13 '25 10:05 Bossama777

可以看下这里官网文档

zimu-yuxi avatar May 13 '25 10:05 zimu-yuxi