? ? ? ?當客戶端以控制臺Console、腳本--execute等方式提交SQL作業(yè)時,Presto的Client會將作業(yè)相關的參數(shù)和腳本封裝成一個Restful請求,提交給PrestoServer端。然后再進行后續(xù)的諸如解析執(zhí)行計劃、拆分Stage、調度task到Worker端執(zhí)行等操作。下面就介紹一下Client提交作業(yè)到服務端部分的源碼。
Main函數(shù)
? ? ? ?客戶端提交作業(yè)的代碼是從Presto的main函數(shù)開始的:

? ? ? ?在Console的run方法中,如果入參中含有--execute,會直接將值取出作為待執(zhí)行的SQL語句。否則認為是通過--file指定了SQL文件,此時會通過文件IO讀取該文件中的SQL腳本。這種情況對應著通過腳本提交作業(yè)的情況,而如果--execute和--file都沒有指定,則認為是通過控制臺Console的方式提交SQL。
通過腳本提交作業(yè)
? ? ? ?通過腳本的方式會直接執(zhí)行Console類的executeCommand方法。按照“;”切分出SQL語句,并依次調用Console類的process方法來提交作業(yè)。
通過控制臺提交作業(yè)
? ? ? ?這種情況相對麻煩一些,他會執(zhí)行Console.runConsole方法處理客戶提交的請求。Presto為這種方式設置了一個AtomicBoolean existing變量來判斷Client是否存在,如果不存在則不再提交后續(xù)的SQL(對應在控制臺中輸入了多條sql語句,并用;間隔,當前邊的語句正在執(zhí)行時退出Console,此時后續(xù)的sql就不會被提交了)。


? ? ? ?在runConsole方法中可以看到,他會有一個while循環(huán)不斷的循環(huán)處理LineReader對象讀取到的命令,LineReader繼承自jline.console.ConsoleReader,是一個專門處理控制臺輸入的Java類庫(官方網址是https://jline.github.io/)。這個類每讀取一行輸入就會將值傳遞給一個名為buffer的StringBuilder對象,然后根據(jù)“;”和“\\G”來識別一個完整的SQL,并將SQL交給process方法進行調度。最后會將剩下不完整的語句賦值給重新初始化的buffer對象作為下一條SQL的開頭。

構建請求并發(fā)送
? ? ? ?下面我們看一下process方法,這個方法中最重要的部分是他會在try with resources中調用QueryRunner的startQuery方法,如下:

? ? ? ?這個語法表示小括號中創(chuàng)建的對象如果實現(xiàn)了closable接口,則無論是否出現(xiàn)異常,都會在try catch結束后調用其close方法。
? ? ? ?如下是startQuery方法:

? ? ? ?然后我們一路點進去,經過QueryRunner的startInernalQuery、StatementClientFactory的newStatementClient方法之后,我們來到了StatementClientV1的構造函數(shù):

? ? ? ?在buildQueryRequest方法中,會構建一個目標Rest地址為/v1/statement的請求,

? ? ? ?隨后在JsonResponse.execute中會發(fā)起這個請求。
? ? ? ?然后我們搜索一下Rest地址/v1/statement,發(fā)現(xiàn)他的目標服務類為StatementResouce。

? ? ? ?以上就是Client提交查詢請求,到PrestoServer端響應的過程。