關(guān)鍵詞:Presto Plugin
1. 前言
本文源碼環(huán)境:
presto: prestoDb 0.275版本
-
在Presto框架中插件機制設(shè)計是一種非常常見和強大的擴展方式。它可以使軟件系統(tǒng)更加靈活和可擴展,允許用戶根據(jù)自己的需求和偏好自定義和擴展系統(tǒng)功能。在 Presto 這樣的分布式 SQL 查詢引擎中,插件機制發(fā)揮著重要的作用,為用戶提供了豐富的擴展能力。
-
Presto 是一個基于內(nèi)存的分布式查詢引擎,旨在快速而高效地處理大規(guī)模數(shù)據(jù)。它被廣泛應(yīng)用于數(shù)據(jù)分析和處理場景,具有優(yōu)秀的性能和靈活的查詢能力。Presto 其插件架構(gòu)是構(gòu)建在 Presto 的核心架構(gòu)之上,為用戶提供了一種可擴展的方式來增強和定制 Presto 的功能。通過插件機制,用戶可以加載自定義的插件,以增加新的查詢功能、支持新的數(shù)據(jù)源、實現(xiàn)自定義的函數(shù)等。
2. Presto插件架構(gòu)
在 Presto 插件架構(gòu)中,插件是一個獨立的模塊,可以包含一個或多個相關(guān)功能的集合。每個插件可以有自己的配置、依賴和生命周期管理。插件可以與 Presto 的核心代碼進行交互,使用 Presto 提供的API來擴展和定制系統(tǒng)功能。
Presto 插件可以提供以下功能:
- 數(shù)據(jù)源擴展:插件可以加載不同類型的數(shù)據(jù)源驅(qū)動程序,允許 Presto 查詢和訪問各種數(shù)據(jù)源,如關(guān)系型數(shù)據(jù)庫、NoSQL 數(shù)據(jù)庫、對象存儲等。
- 函數(shù)庫擴展:插件可以提供自定義的函數(shù)和聚合函數(shù),以滿足特定的業(yè)務(wù)需求。用戶可以根據(jù)自己的需求加載相應(yīng)的插件,并使用插件中定義的函數(shù)來進行數(shù)據(jù)處理和計算。
- 認證和授權(quán)擴展:插件可以提供自定義的認證和授權(quán)機制,允許用戶根據(jù)自己的安全需求對查詢進行訪問控制和身份驗證。
- 優(yōu)化器和執(zhí)行器擴展:插件可以實現(xiàn)自定義的查詢優(yōu)化規(guī)則和執(zhí)行計劃算法,以提高查詢的性能和效率。
Presto 插件架構(gòu)的核心組件是 PluginManager 類。PluginManager 類負責(zé)插件的加載、注冊、維護和生命周期管理。它提供了一組方法來加載插件 JAR 文件,解析插件配置,注冊插件,并確保插件的正確初始化和銷毀。
通過 PluginManager 類,Presto 可以動態(tài)加載和管理插件,使用戶能夠根據(jù)自己的需要輕松地擴展和定制 Presto 的功能。插件的加載和管理過程是一個關(guān)鍵的環(huán)節(jié),通過對此過程進行深入的源碼分析,我們可以更好地理解 Presto 插件架構(gòu)的工作原理,為開發(fā)和利用插件提供指導(dǎo)和技巧。
3. Plugin接口
Presto Plugin接口主要在Presto-spi模塊中,presto-spi 是 Presto 的一個核心模塊,它提供了一組公共的接口和服務(wù)提供者接口(Service Provider Interface,SPI),被其他模塊用來定義和擴展 Presto 的行為和功能,Presto通過SPI模塊實現(xiàn)了一種松耦合的插件化架構(gòu),使得各種組件和功能可以通過實現(xiàn)接口和服務(wù)提供者接口來定制和擴展。這樣的架構(gòu)能夠方便地支持不同的數(shù)據(jù)源和擴展需求,同時保持 Presto 的核心邏輯的完整性和可維護性。
3.1 插件協(xié)議
com.facebook.presto.spi#Plugin接口定義的功能方法如下:
public interface Plugin
{
// 返回插件ConnectorFactory實現(xiàn) -- 連接外部數(shù)據(jù)源
default Iterable<ConnectorFactory> getConnectorFactories()
{
return emptyList();
}
// 返回插件提供的 BlockEncoding 實現(xiàn),用于壓縮和解壓 Presto 內(nèi)部數(shù)據(jù)結(jié)構(gòu),提高內(nèi)存和網(wǎng)絡(luò)傳輸效率
default Iterable<BlockEncoding> getBlockEncodings()
{
return emptyList();
}
// 返回插件提供的類型(Type)實現(xiàn),用于擴展 Presto 內(nèi)置類型,支持更多不同種類、不同格式的數(shù)據(jù)
default Iterable<Type> getTypes()
{
return emptyList();
}
// 返回插件提供的 ParametricType 實現(xiàn),用于支持更復(fù)雜的泛型類型,比如 MAP<ARRAY<STRING>> 等
default Iterable<ParametricType> getParametricTypes()
{
return emptyList();
}
// 返回插件提供的自定義函數(shù)實現(xiàn),可以是 SQL 函數(shù),也可以是自定義聚合函數(shù)或標(biāo)量函數(shù),這可以大幅提高 Presto 的靈活性和擴展性
default Set<Class<?>> getFunctions()
{
return emptySet();
}
// 返回插件提供的 SystemAccessControlFactory 實現(xiàn),用于自定義 Presto 的系統(tǒng)訪問控制策略,比如授權(quán)、資源限制等
default Iterable<SystemAccessControlFactory> getSystemAccessControlFactories()
{
return emptyList();
}
// 返回插件提供的 PasswordAuthenticatorFactory 實現(xiàn),用于支持自定義 Presto 的密碼認證方式
default Iterable<PasswordAuthenticatorFactory> getPasswordAuthenticatorFactories()
{
return emptyList();
}
// 返回插件提供的 EventListenerFactory 實現(xiàn),用于自定義一些事件的監(jiān)聽和處理機制,比如在 SQL 執(zhí)行前/后添加日志功能等
default Iterable<EventListenerFactory> getEventListenerFactories()
{
return emptyList();
}
// 返回插件提供的 ResourceGroupConfigurationManagerFactory 實現(xiàn),用于自定義 Presto 的資源管理策略,比如作業(yè)分組、優(yōu)先級等
default Iterable<ResourceGroupConfigurationManagerFactory> getResourceGroupConfigurationManagerFactories()
{
return emptyList();
}
// 返回插件提供的 SessionPropertyConfigurationManagerFactory 實現(xiàn),用于自定義 Presto 的會話屬性配置,并在 SQL 執(zhí)行時按照這些屬性進行處理
default Iterable<SessionPropertyConfigurationManagerFactory> getSessionPropertyConfigurationManagerFactories()
{
return emptyList();
}
// 返回插件提供的 FunctionNamespaceManagerFactory 實現(xiàn),用于實現(xiàn) Presto 的函數(shù)命名空間管理,這樣可以支持不同用戶、不同組織、不同數(shù)據(jù)源之間的函數(shù)隔離和共享
default Iterable<FunctionNamespaceManagerFactory> getFunctionNamespaceManagerFactories()
{
return emptyList();
}
// 返回插件提供的 TempStorageFactory 實現(xiàn),用于將一些中間結(jié)果存儲到外部臨時存儲中,從而避免內(nèi)存消耗過大,甚至導(dǎo)致 OutOfMemoryError;
default Iterable<TempStorageFactory> getTempStorageFactories()
{
return emptyList();
}
// 返回插件提供的 QueryPrerequisitesFactory 實現(xiàn),用于自定義 Presto 執(zhí)行 SQL Query 前的準(zhǔn)備工作,比如生成優(yōu)化計劃前的數(shù)據(jù)準(zhǔn)備、元數(shù)據(jù)加載等;
default Iterable<QueryPrerequisitesFactory> getQueryPrerequisitesFactories()
{
return emptyList();
}
// 返回插件提供的 NodeTtlFetcherFactory 實現(xiàn),用于獲取 Presto 集群中各個節(jié)點的服務(wù)生命周期狀態(tài),從而支持動態(tài)的節(jié)點上下線功能;
default Iterable<NodeTtlFetcherFactory> getNodeTtlFetcherFactories()
{
return emptyList();
}
// 返回插件提供的 ClusterTtlProviderFactory 實現(xiàn),用于支持 Presto Query 過期的功能,也就是定時清理歷史查詢的記錄;
default Iterable<ClusterTtlProviderFactory> getClusterTtlProviderFactories()
{
return emptyList();
}
// 返回插件提供的 ExternalPlanStatisticsProvider 實現(xiàn),用于收集 Presto 執(zhí)行計劃的運行時統(tǒng)計信息,以便分析和優(yōu)化執(zhí)行性能。
default Iterable<ExternalPlanStatisticsProvider> getExternalPlanStatisticsProviders()
{
return emptyList();
}
}
常見的 Presto 插件功能和作用:
- Connector 插件:用于連接不同的數(shù)據(jù)源,比如 Hadoop HDFS、Amazon S3、Apache Kafka、MySQL 等,使 Presto 可以查詢和分析這些不同數(shù)據(jù)源中的數(shù)據(jù)。
- Function 插件:提供新的內(nèi)置函數(shù)或用戶自定義函數(shù),豐富 Presto 的查詢功能。這些函數(shù)可以用于數(shù)據(jù)轉(zhuǎn)換、數(shù)學(xué)計算、字符串處理、日期處理等。
- Authentication/Authorization 插件:用于提供認證和授權(quán)機制,確保只有授權(quán)用戶可以訪問 Presto 引擎并執(zhí)行查詢操作。這可以通過集成現(xiàn)有的身份驗證系統(tǒng)(如 Kerberos)或提供自定義的用戶認證和授權(quán)邏輯來實現(xiàn)。
- SerDe 插件:提供用于序列化和反序列化數(shù)據(jù)的解析器,使得 Presto 可以讀取和分析不同的數(shù)據(jù)格式,比如 JSON、Avro、Parquet 等。
- Metadata 插件:用于在 Presto 的元數(shù)據(jù)系統(tǒng)中添加新的數(shù)據(jù)源、表和列類型,使 Presto 可以理解和管理這些新的數(shù)據(jù)結(jié)構(gòu)。
- Connector Manager 插件:負責(zé)管理和維護連接到 Presto 引擎的各個數(shù)據(jù)源連接。它可以提供連接池、連接的生命周期管理等功能。
3.2 插件實現(xiàn)類
Presto 插件常見接口及其對應(yīng)的實現(xiàn)類:
- Connector:該接口定義了與外部數(shù)據(jù)源連接的功能。一些常見的 Connector 接口的實現(xiàn)類包括:
○ JdbcConnector:用于連接支持 JDBC 協(xié)議的關(guān)系型數(shù)據(jù)庫,如 MySQL、PostgreSQL、Oracle 等。
○ HiveConnector:用于連接 Hive 數(shù)據(jù)倉庫,支持查詢 Hive 表格和視圖。
○ KafkaConnector:用于連接 Apache Kafka 流處理平臺,支持讀取和寫入 Kafka 主題。 - Function:該接口定義了自定義 SQL 函數(shù)的功能。一些常見的 Function 接口的實現(xiàn)類包括:
○ ScalarFunction:實現(xiàn)標(biāo)量函數(shù),接收一個或多個輸入?yún)?shù),并返回一個結(jié)果。
○ AggregateFunction:實現(xiàn)聚合函數(shù),對一個數(shù)據(jù)集進行計算,返回一個聚合結(jié)果。
○ WindowFunction:實現(xiàn)窗口函數(shù),對數(shù)據(jù)窗口進行聚合計算,并返回一個結(jié)果集。 - Type:該接口定義了自定義數(shù)據(jù)類型的功能。一些常見的 Type 接口的實現(xiàn)類包括:
○ ArrayType:實現(xiàn)數(shù)組類型,表示包含多個元素的數(shù)組。
○ MapType:實現(xiàn)映射類型,表示鍵值對映射的數(shù)據(jù)結(jié)構(gòu)。
○ RowType:實現(xiàn)行類型,表示一組具有命名字段的數(shù)據(jù)。 - Split:該接口定義了查詢?nèi)蝿?wù)(split)的功能。一些常見的 Split 接口的實現(xiàn)類包括:
○ FileSplit:用于處理文件分割任務(wù)。
○ TableSplit:用于處理表格分割任務(wù)。
○ PartitionSplit:用于處理分區(qū)分割任務(wù)。
在 presto-main 、presto-hive、presto-jdbc 等模塊中,都提供了相應(yīng)的實現(xiàn)類來實現(xiàn)上述接口,以便連接不同的數(shù)據(jù)源、定義自定義函數(shù)和類型,并處理查詢?nèi)蝿?wù)。此外,還可以根據(jù)需要自定義實現(xiàn)這些接口,以滿足特定需求。
常見的JDBCPlugin(關(guān)系庫插件); HivePlugin 示例:
4. 插件加載過程
Presto插件加載是在Presto啟動時進行如下:
com.facebook.presto.server#run
....
// 創(chuàng)建 Bootstrap 對象:通過創(chuàng)建 Bootstrap 對象來啟動 Presto,并傳入一個模塊列表。
// Bootstrap 是 Presto 提供的一個啟動類,用于初始化 Presto 的運行環(huán)境并加載必要的模塊。
Bootstrap app = new Bootstrap(modules.build());
try {
// 初始化并獲取 Injector:使用 app.initialize() 方法初始化 Bootstrap 對象,
// 返回一個 Injector 實例。Injector 是 Guice 框架提供的依賴注入容器,
// 用于管理 Presto 中的對象依賴關(guān)系。
Injector injector = app.initialize();
// 加載插件:通過獲取 PluginManager 實例,調(diào)用 loadPlugins() 方法加載插件。
//PluginManager 是 Presto 的插件管理器,負責(zé)加載、管理和擴展 Presto 的插件。
injector.getInstance(PluginManager.class).loadPlugins();
ServerConfig serverConfig = injector.getInstance(ServerConfig.class);
if (!serverConfig.isResourceManager()) {
injector.getInstance(StaticCatalogStore.class).loadCatalogs();
}
.......
4.1 PluginManager
Presto的插件管理器(PluginManager)負責(zé)加載所有的插件。以下是其基本的工作流程:
- Presto在啟動時,會通過配置文件(通常是config.properties)來確定插件的目錄(plugin.dir)。
- 插件管理器會掃描這個目錄以及其子目錄,尋找任何有效的插件。
- 對于每個找到的插件,插件管理器會創(chuàng)建一個新的類加載器,然后使用這個類加載器來加載插件的類。
- 插件管理器會調(diào)用插件的ConnectorFactory,創(chuàng)建一個新的Connector實例。
- 這個新的Connector實例會被添加到Presto的全局Connector列表中。
這個過程是在Presto啟動時自動進行的,所以所有的插件都會在Presto啟動后立即可用。
如果你想要添加一個新的插件,你只需要將插件的jar文件和一個名為presto-plugin.properties的配置文件放到插件目錄的一個新的子目錄中。然后,你可以重新啟動Presto,新的插件就會被自動加載。
注意:在加載插件時,Presto不會檢查插件的版本或者兼容性。因此,你需要確保你的插件是與你的Presto版本兼容的。
loadPlugins加載方法如下:
其中加載配置路徑由 config.properties文件中plugin.bundles或者plugin.dir 進行指定,plugin.bundles 是一個包含插件 JAR 文件路徑的逗號分隔列表。每個 JAR 文件通常包含一個或多個 Presto 插件。這些 JAR 文件可以位于本地文件系統(tǒng)中,也可以是遠程位置(如 HDFS 或 S3)。
當(dāng) Presto 啟動時,它會掃描 plugin.bundles 中指定的 JAR 文件,加載其中的插件。
plugin.dir 則是指定一個目錄,Presto 會在啟動時掃描該目錄下的所有 JAR 文件,并嘗試加載其中的插件。與 plugin.bundles 不同的是,plugin.dir 只能指定一個目錄路徑,而不能包含多個逗號分隔的路徑。
plugin.bundles 適用于在啟動時加載預(yù)定義的插件 JAR 文件,而 plugin.dir 則適用于動態(tài)加載特定目錄下的所有插件 JAR 文件。選擇使用哪種方式取決于你的需求和插件管理的方式。
最終installPlugin()方法就是將插件中定義的各種功能注冊到Presto中,使得Presto具備這些功能,擴展了Presto的能力和靈活性。通過安裝插件,用戶可以根據(jù)自己的需求來定制和配置Presto,滿足不同場景下的數(shù)據(jù)處理需求。
5. 插件應(yīng)用
由于篇幅有限這里僅分析函數(shù)的擴展案例:
比如我們要在SQL中實現(xiàn)一個集成支持向量機SVM進行分類模型的訓(xùn)練的機器學(xué)習(xí)函數(shù),只需要直接集成Plugin
按照 如類似UDF等函數(shù)的寫法實現(xiàn)自己的Presto機器學(xué)習(xí)函數(shù)
LearnClassifierAggregation 該類定義了三個方法:input()、combine() 和 output(),它們分別對應(yīng)于聚合函數(shù)的三個階段:輸入(即接受輸入行數(shù)據(jù))、合并(將多個聚合器合并為一個)和輸出(生成最終結(jié)果)
6. 總結(jié)
Presto以其插件機制設(shè)計,實現(xiàn)了高度的靈活性和可擴展性。通過插件接口,用戶可以輕松地擴展和定制數(shù)據(jù)源、函數(shù)庫、認證和授權(quán)、優(yōu)化器和執(zhí)行器等方面的功能。這種靈活性為用戶提供了廣泛的擴展和定制選項,使得Presto能夠更好地適應(yīng)多樣化的應(yīng)用場景。
作為一個大數(shù)據(jù)分布式計算框架,Presto擁有強大的功能和優(yōu)勢。它能夠無縫地處理不同數(shù)據(jù)源、執(zhí)行分布式內(nèi)存計算,并具備靈活的執(zhí)行器和監(jiān)控功能。這些特性使得Presto在大數(shù)據(jù)領(lǐng)域的分布式計算環(huán)境中具有重要的地位和作用。文章來源:http://www.zghlxwxcb.cn/news/detail-743585.html
綜上所述,Presto的插件機制為用戶提供了靈活性和可擴展性,使其成為一個功能強大且適用廣泛的分布式計算框架。在未來的大數(shù)據(jù)分析和處理中,Presto有望繼續(xù)發(fā)揮重要的作用,并在不斷演進的大數(shù)據(jù)環(huán)境中保持領(lǐng)先地位。文章來源地址http://www.zghlxwxcb.cn/news/detail-743585.html
到了這里,關(guān)于presto插件機制揭秘:探索無限可能的數(shù)據(jù)處理舞臺的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!