[Doris Stream Load 超时问题排查1] - stream load源码排查定位- timeout by txn manager

数据存储,数据分析

2021-04-04

206

0

原文: [Doris Stream Load 超时问题排查1] - stream load源码排查定位- timeout by txn manager

问题现象

  • doris 现象: timeout by txn manager

  • nginx现象

    <html>
    <head><title>504 Gateway Time-outtitle>head>
    <body bgcolor="white">
    <center><h1>504 Gateway Time-outh1>center>
    <hr><center>nginxcenter>
    body>
    html>
    

问题分层怀疑、定位

在分层定位问题前需要先知道Doris的整体部署结构, 方便定位问题. 部署结构如下:

由错误信息可以做如下猜测:

    1. nginx本身在请求超时时间是60s, 小于doris本身的超时时间
    1. doris本身的超时时间是60s
    1. 用户指定了超时时间是60s
    1. Load Blance (LB)本身超时时间是60s

通过排查,

  • 首先否定4. 原因: “timeout by txn manager”是doris任务执行时间太长被主动结束了. 和LB没关系
  • 其次check nginx各种超时配置后, 否定1
  • check doris配置后, 否定2, 默认是Config.stream_load_default_timeout_second, 应该为300s

具体朝3的方向分析

问题分析

    1. 查看Doris Stream Load报错详情后, 可以看到Prepare Time和Finish Time相差60s.
    1. 翻看Doris源码, 确认 “timeout by txn manager”报错位置: 源码位置. 确认是Doris会定时检查哪些导入事物超时了, 超时后主动停止该任务. 通过翻看DatabaseTransactionMgr.java代码, 最后可以知道是TransactionState.javatimeout参数控制超时时间. 默认是Config.stream_load_default_timeout_second, 该配置默认300秒. 但是本次超时是60秒, 说明timeout参数沟通TransactionState.java的构造函数被重置了.
  • 确认isTimeout数来源: 查找TransactionState构造函数的依赖关系, 可以找到如下代码截图: 按照标号顺序看:

说明: FrontendServiceImpl.java是fe提供的RPC服务接口. 提供库、表、事物等的基本操作服务.

到这里貌似就知道地方RPC请求了loadTxnBegin()方法, 什么地方调用的不清楚. 是broker ? be ? 猜测是be

回头再看看stream load在Fe中的处理过程.

stream load我们知道是http请求, 从源码包中我们查到到如下代码:

翻看代码, 通古注册的url可以知道stream load是LoadAction.java这个类处理的. 请求是如何被转到这里处理的, 下回再分解.

 public static void registerAction(ActionController controller) throws IllegalArgException {
        ExecuteEnv execEnv = ExecuteEnv.getInstance();
        LoadAction action = new LoadAction(controller, execEnv);
        controller.registerHandler(HttpMethod.PUT,
                                   "/api/{" + DB_KEY + "}/{" + TABLE_KEY + "}/_load", action);

        controller.registerHandler(HttpMethod.PUT,
                                   "/api/{" + DB_KEY + "}/{" + TABLE_KEY + "}/_stream_load",
                                   new LoadAction(controller, execEnv, true));
    }

executeWithoutPassword()这个方法是当有stream load请求到fe时, 请求会被转发到这个方法处理, 代码核心如下:

TNetworkAddress redirectAddr;
if (!isStreamLoad && !Strings.isNullOrEmpty(request.getSingleParameter(SUB_LABEL_NAME_PARAM))) {
    ...
} else {
    ...
    redirectAddr = new TNetworkAddress(backend.getHost(), backend.getHttpPort());
}

LOG.info("redirect load action to destination={}, stream: {}, db: {}, tbl: {}, label: {}",
        redirectAddr.toString(), isStreamLoad, dbName, tableName, label);
redirectTo(request, response, redirectAddr);

这个核心代码逻辑比较简单, fe会把stream load的请求redirect到一个be节点处理, 这个be节点称为Coordinator节点. 这个be节点会负责和fe通信生成导入执行计划, 处理导入事物等. 下面我们再细说.

那我们看看be是如何处理fe转发过来的stream load请求的.

欢迎添加微信,互相学习↑↑↑ -_-

发表评论

全部评论:0条

白老虎

programming is not only to solve problems, ways to think