Presto 無active worker的一次定位過程

故事是這樣的,突然一個非小白用戶爆出來說presto頁面上active的worker數量爲0。看了一眼機器狀態,都獲得好好的,並沒有啥錯誤日誌。於是開始了一次定位之旅。

獲取集羣狀態

先獲取集羣狀態看看,確認下眼沒有瞎。接口:

http://xxx/v1/cluster

返回:

"runningQueries":0,"blockedQueries":0,"queuedQueries":0,"activeCoordinators":1,"activeWorkers":0,"runningDrivers":0,"totalAvailableProcessors":0,"reservedMemory":0.0,"totalInputRows":268931841,"totalInputBytes":37945815115,"totalCpuTimeSecs":713}

注意到這裏active 的worker數量爲0。

獲取node信息:

是node掛了麼?來,找個接口看看node的狀態。
接口:

http://xxx/v1/node

返回:

[{"uri":"http://xxxx:8080","recentRequests":120.00277776491771,"recentFailures":0.0,"recentSuccesses":120.00277776491774,"lastRequestTime":"2019-09-29T09:53:04.384Z","lastResponseTime":"2019-09-29T09:53:04.386Z","recentFailureRatio":0.0,"recentFailuresByType":{},"age":"5.26d"},{"uri":"http://xxxx:8080","recentRequests":120.00277776491774,"recentFailures":0.0,"recentSuccesses":120.00277776491774,"lastRequestTime":"2019-09-29T09:53:04.342Z","lastResponseTime":"2019-09-29T09:53:04.344Z","recentFailureRatio":0.0,"recentFailuresByType":{},"age":"5.99d"}]

奇怪了。node是有的,並且還挺正常。可以判定worker信息的彙報沒有問題,fail detector也沒有問題。OK,接下來看下怎麼判定爲active的吧。

active狀態判定

//From DiscoveryNodeManager
private NodeState getNodeState(InternalNode node)
{
    if (expectedNodeVersion.equals(node.getNodeVersion())) {
        if (isNodeShuttingDown(node.getNodeIdentifier())) {
            return SHUTTING_DOWN;
        }
        else {
            return ACTIVE;
        }
    }
    else {
        return INACTIVE;
    }
}

這裏isNodeShuttingDown的判斷邏輯和之前講解的ping機制還稍微有點區別。presto還啓動了一個輪詢worker狀態的定時器,定時的從worker處獲取狀態。兩者訪問的接口:

  1. ping,訪問根路徑/,判斷是不是活着;
  2. isNodeShuttingDown,訪問/v1/info/state, 直接從worker處獲取worker的狀態

emmm? 爲什麼還這麼複雜,深思熟慮(google) 後發現,presto提供了個平滑shutdown worker的接口。看這裏。也就是shutdown不採用粗暴的kill方式,下發shutdown後就不再接受新的task,已經在運行的task結束後退出。如果沒人shutdown worker,worker的節點就是active的。

再拉回來,從上面的信息中可以推斷:

  1. worker應該還活着,因爲可以拿到node的信息;
  2. worker大概率不是active的。活着、沒有shutdown它、又不active,基本就是受上述代碼中第一行的版本判斷不滿足了。翻翻接口去拿下更詳細的worker信息吧。

獲取各節點的版本詳情

獲取節點信息的接口:

http://xxx/v1/service

結果:
service返回信息

OK,證明猜測基本成立,版本不對。後來排查到大概率可能的原因是因爲在k8s部署的時候,image版本都選擇用了latest,但是在worker後來經歷了一次重啓,剛好幾天前prestosql升級了。

彩蛋

Presto node上是如何確認版本號的呢?
在ServerMainMoudle中有配置Announce的信息:

// Determine the NodeVersion
 NodeVersion nodeVersion = new NodeVersion(serverConfig.getPrestoVersion());
 binder.bind(NodeVersion.class).toInstance(nodeVersion);

 // presto announcement
 discoveryBinder(binder).bindHttpAnnouncement("presto")
         .addProperty("node_version", nodeVersion.toString())
         .addProperty("coordinator", String.valueOf(serverConfig.isCoordinator()));

那麼確定這個版本信息的代碼就在Server Config中:

private String prestoVersion = getClass().getPackage().getImplementationVersion();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章