Apache Drill 受 Google Dremel 啟發,定位於**大數據集的交互式實時分析**。它不替代 Hadoop MapReduce 或 Storm/S4 等批處理/流處理框架,而是填補「秒級 SQL 查詢海量數據」的空白。Drill 的靈活性體現在:
實現一個可查詢 **HTTP GET + JSON API** 的存儲插件,支持如下查詢語法:
-- 動態參數構建查詢(where 條件轉為 URL 參數)
SELECT name, length FROM http.`/e/api:search` WHERE $p=2 AND $q='avi';
-- 靜態完整 URL 查詢
SELECT name, length FROM http.`/e/api:search?q=avi&p=2` WHERE length > 0;
開發一個 Storage Plugin 需實現以下核心接口(掃描機制基於 Calcite 的 Plan 轉換):
| 類/接口 | 核心職責 |
|---|---|
StoragePluginConfig | 配置類,JSON 可序列化,如 {type:"http", connection:"https://host:8000", resultKey:"results", enabled:true} |
AbstractStoragePlugin | 插件主類,構造函數固定簽名 (Config, DrillbitContext, String),實現 getPhysicalScan、registerSchemas、getOptimizerRules |
SchemaFactory / AbstractSchema | 動態註冊 Schema/Table,HTTP 場景下 Table 對應 API Endpoint |
AbstractGroupScan / SubScan | 查詢規劃階段傳遞掃描規格(如 HTTP 路徑、參數) |
BatchCreator / AbstractRecordReader | 執行階段:創建 RecordReader,實際發起 HTTP 請求、解析 JSON、轉換為 Drill 內部 Vector 列式格式 |
Drill 啟動時掃描 classpath 下 AbstractStoragePlugin 實現類,讀取 /tmp/drill/sys.storage_plugins(Windows 為 D:\tmp\drill\sys.storage_plugins)加載配置。
public Table getTable(String tableName) {
// tableName 即 HTTP API 路徑,如 "/e/api:search?q=avi&p=2"
HttpScanSpec spec = new HttpScanSpec(tableName);
return new DynamicDrillTable(plugin, schemaName, null, spec);
}
HttpScanSpec → AbstractStoragePlugin.getPhysicalScan() → HttpGroupScan → HttpSubScan → HttpScanBatchCreator → HttpRecordReader
setup():發起 HTTP GET 請求,獲取 JSON 響應next():使用 JsonReader 解析 JSON,寫入 VectorContainerWriter(Drill 列式內存格式)實現 StoragePluginOptimizerRule 可將 Drill 的 WHERE 過濾條件下推為 HTTP 參數(如 MongoDB Plugin 將 WHERE a > 1 轉為 {$gt: 1}),減少數據傳輸。本 Demo 暫未完善,Drill 會在內存中過濾。
Drill 依賴 Apache Calcite 進行 SQL 解析 → Logical Plan → Physical Plan(Execution Plan)優化。Plan 結構類似語法樹,StoragePluginOptimizerRule 本質是重寫語法樹節點。文檔匱乏、代碼複雜是擴展難點。
drill-mongo-storage 等官方插件源碼逆向工程jars/ 目錄,重啟 Drillbit,Web UI 配置啟用