Spark1.1之後的版本引入了ThriftServer和CLI,使得Hive用戶和RDBMS用戶可以直接通過JDBC方式提交SQL至Spark運行而無需編寫sparksql代碼,下面對spark-thriftserver的源碼進行簡單分析。
執行${SPARK_HOME}/sbin/start-thriftserver.sh即可啓動thriftserver,默認端口爲10000,HiveStatement提交sql時對應的url爲 jdcb:hive2://localhost:10000/default,此時通過Hive提交的sql將在sparksql中執行。
通過start-thriftserver.sh的代碼可以發現,後臺是提交了org.apache.spark.sql.hive.thriftserver.HiveThriftServer2類至spark-submit執行。對HiveThriftServer2源碼的閱讀可以發現,HiveThriftServer2註冊了ThriftBinaryCLIService服務,而thriftserver服務端綁定的Processor爲TCLIService.Processor類。
通過getProcessMap方法可以發現,Processor類中已經預先註冊了相關的thrift調用接口。
ThriftBinaryCLIService類中通過啓動TThreadPoolServer來監聽thrift客戶端請求,下面以HiveStatement的executeQuery爲例,分析整個執行流程。
executeQuery方法在內部調用sendBase向thrift服務器發送請求,sendBase方法的簽名爲void sendBase(String methodNmae, TBase args); methodName爲接口名,args爲參數,在這裏methodName爲"ExecuteStatement"。
服務端收到請求之後,解析出method參數名爲ExecuteStatement,從processMap中獲取TCLIService.Processor.ExecuteStatement,調用該類的getReasult方法,該方法中調用iface.ExecuteStatement,iface.ExecuteStatement的實現有兩種,TCLIService.ExecuteStatement和ThriftCLIService.ExecuteStatement,前者爲客戶端的實現,後者是服務端的實現:
由cliService.executeStatementAsync一直看下去,最終到了HiveSessionIml.executeStatementInternal,具體實現爲
getOperationManager方法返回org.apache.spark.sql.hive.thriftserver.server.SparkSQLOperationManager類,其newExecuteStatementOperation的具體實現爲:
可以看到其返回了SparkExecuteStatementOperation類,最終operation.run方法是調用了SparkExecuteStatementOperation的execute方法:
可以看到execute方法中通過sqlContext執行對應的sql語句並返回結果,TCLIService.Processor.ExecuteStatement.getResult執行完成後,通過thrift協議返回結果給客戶端:
整體的服務流程通過TThreadPoolServer類的run方法可以看得很清楚:
最後給出ThriftServer的Processor端處理的時序圖:
寫得比較亂,歡迎各位交流指正!