通常我們在編寫一個flink的作業的時候,肯定會有依賴的jar包。flink官方希望你將所有的依賴和業務邏輯打成一個fat jar,這樣方便提交,因為flink認為你應該對自己的業務邏輯做好單元測試,而不應該把這部分測試工作頻繁提交到集群去做。但事實是我們往往不願意打一個fat jar,我們希望將業務邏輯獨立出來,依賴動態提交。可惜的是,flink並不支持這種提交模式。
flink官方的文檔中提供了-C這個選項,來支持提交classpath,我們當時以為這個會有作用,后來再研讀源碼和實際測試的情況看來,不行,-C不是這么用的。
-C,--classpath , Adds a URL to each user code classloader on all nodes in the cluster. The paths must specify a protocol (e.g. file://) and be accessible on all nodes (e.g. by means of a NFS share). You can use this option multiple times for specifying more than one URL. The protocol must be supported by the {@link
如上,是flink官方文檔中對-C的解釋,再加上對1.4.2版本源碼以及1.5.0版本源碼和1.6.0版本源碼的研讀,以及對cli的實際調用,總結如下:
1.此處的classpath的url必須是一個能夠在client,JM和TM都被訪問到的位置。
2.此位置從client端的提交到JM的分發到TM的訪問的過程中,不會發生文件移動的動作,在1.4.2和1.5.0和1.6.0的版本中都是這樣。
3.url支持的協議包括file,ftp,gopher,http,https,jar,mailto,netdoc,亦即java中URL類支持的協議類型。注意:不能放在hdfs上。
所以,如果要想使用-C這個選項,一般有兩個做法:
1.手動將classpath中的位置在每個節點上進行部署。
2.使用共享存儲,此共享存儲可以被所有節點的角色訪問。
那如何實現我們的要求了?
三個方案:
1.與-yt結合使用
原理:-yt是在yarnCluster模式下用來將本地jar提交到遠端的參數,當指定了-yt的值后,客戶端會將目錄中的jar上傳到hdfs中本應用的lib目錄中,在tm下載之后,會存在於tm的classpath中。
優點:無需修改代碼,結合-yt在創建cluster的時候先行上傳依賴文件,在提交作業的時候,再指定-C選項即可。
缺點:
多個作業共享一個cluster,則此cluster需要包含所有的作業可能的依賴。
如果要替換一個依賴,則比較困難,需要重新建立集群
-yt命令雖然將依賴上傳到了hdfs,但是-C命令還是需要將文件上傳到client端即我們的agent端,操作比較繁雜。
2.改動PackageProgram將lib包放入其library屬性中
原理:后續在構建jobGraph的過程中,以library為基准去設置userJar屬性。
優點:改動的位置比較靠前,而且packageProgram感覺在將來改動的可能性還是有。
缺點:library是一個用到的地方比較多的屬性,是否對其他地方的調用產生影響,需要進一步的研究。
3.改動ClusterClient中的getJobGraph方法,將lib包放入jobGraph的userJar屬性中
原理:jobGraph的userJar是用來上傳的屬性,放入這里,lib包將會被上傳到JM的BlobServer中。
優點:比較清晰,改動的影響可控可見,比較沒有副作用。
缺點:改動的比較深,對於日后的升級等或許有一定影響。
根據我們自己的情況,我們選擇了方案2,但在某種情況下,方案1雖然有點煩,但至少不用改源碼,也是可以考慮的。