Superset 源碼分析

我最初接觸 Superset 是在2018年的時候,那時候 Superset 的版本才0.26,當時在公司內(nèi)部積累了一些best practice,遇到了bug還順便貢獻了代碼,算是對這個項目有比較深入的了解。

這些年看著 Superset 社區(qū)越來越成功,國內(nèi)也有很多公司和開發(fā)者需要圍繞著 Superset 做一些公司生態(tài)內(nèi)的二次開發(fā),而我現(xiàn)在回過頭來看這個項目,對整個項目有了更深刻的理解,接下來,我會輸出一系列的文章,講解如何玩轉(zhuǎn) Superset 的二次開發(fā)。

剛開始接手一個新的項目,大致了解每個目錄下的代碼大概是做什么的非常重要,你會知道代碼去哪里修改,做到心中有數(shù)才能更加游刃有余。

Superset 介紹

Superset 是一個款非常優(yōu)秀的開源項目,作為BI工具,它的開發(fā)語言大眾化,云原生的架構(gòu)能夠滿足企業(yè)各種各樣的定制化需求,從 web server,后端數(shù)據(jù)庫,消息隊列,緩存層都可以根據(jù)業(yè)務(wù)需要進行配置更改。支持各種各樣的大數(shù)據(jù)組件作為查詢引擎,如 Presto,Hive,Spark,Clickhouse,Amazon Athena,Redshift 等等。

而豐富的數(shù)據(jù)可視化解決方案才是 Superset 最大的亮點,它還支持自定義plugin的方式去增加自己想要的圖表。


gallery.jpeg

代碼目錄介紹

Superset branch 1.5為例,根目錄下通常會存放一些代碼樣式規(guī)范,git相關(guān)的配置,docker文件,python setup等腳本。還有做開源貢獻必須仔細閱讀的 code of conductcontributing

這些文件中需要著重閱讀的是 contributing,里面有很詳細的步驟告訴你如何開始貢獻代碼,如何把前端本地開發(fā)環(huán)境搭建起來,前后端如何協(xié)調(diào),怎么修改代碼的縮進等等。

根目錄下還有如圖所示的各個文件夾


Screen Shot 2022-05-17 at 23.05.22.png

挑幾個比較重要的來說說,

  • superset:后端代碼主要放在這個文件夾中
  • superset-frontend: 前端代碼的入口
  • superset-websocket:Nodejs websocket相關(guān)
  • docker:docker文件,docker的啟動腳本等等
  • helm/superset:helm charts 的配置文件,不太了解 helm 的可以看看官方介紹
  • requirements:python環(huán)境下,需要安裝的一些第三方包及其版本
  • .github:存放github CI/CD 相關(guān)的 workflow 配置,可略過
  • RELEASING:存放版本release note

我個人多年來閱讀項目源碼的習慣是先抓住重點,細枝末節(jié)的東西可以以后慢慢一點點補充。一上來不要一下子輸入太多,細節(jié)有時候會把人帶跑。

以上就是比較重要的一些模塊,作為后端開發(fā)(前端我無能為力 ?? ),首先可以看看 superset 文件夾下的代碼。

看源碼的過程建議結(jié)合前端的UI交互、功能來看對應的后端代碼。首先應該自己去上手用一用這款產(chǎn)品,連接一些數(shù)據(jù)庫,建幾張表,最后建幾個dashboard玩一玩,數(shù)據(jù)可視化方面的一些基本知識也需要順便補一補,只有真正成為一個產(chǎn)品的用戶,才會變成一個有心人,發(fā)現(xiàn)很多別人看不到的細節(jié),才有可能做到深入。

后端代碼入口

后端是如何啟動起來的,通過看 Dockerfile 的 entrypoint 或者 CMD

Screen Shot 2022-05-18 at 21.30.27.png

這段代碼可以發(fā)現(xiàn),啟動后端服務(wù)應該是在 ./docker/docker-ci.sh 這個文件里執(zhí)行的,順著這個文件找下去,會發(fā)現(xiàn)最終執(zhí)行的是一個叫 ./docker/run-server.sh 的腳本。

Screen Shot 2022-05-18 at 21.36.37.png

啟動 Superset 后端server的一個命令就是 gunicorn 這一句。gunicorn 要啟動的這個 ${FLASK_APP} 變量通過代碼搜索可以發(fā)現(xiàn)就是 FLASK_APP="superset.app:create_app()"

它所對應的方法就是 superset/app.py 文件中的 create_app() 方法。


def create_app() -> Flask:  
    app = SupersetApp(__name__)  
  
    try:  
        # Allow user to override our config completely  
        config_module = os.environ.get("SUPERSET_CONFIG", "superset.config")  
        app.config.from_object(config_module)  
  
        app_initializer = app.config.get("APP_INITIALIZER", SupersetAppInitializer)(app)  
        app_initializer.init_app()  
  
        return app  
  
    # Make sure that bootstrap errors ALWAYS get logged  
    except Exception as ex:  
        logger.exception("Failed to create app")  
        raise ex  
  
  
class SupersetApp(Flask):  
    pass

這段創(chuàng)建應用的代碼做了幾件事:

  • 加載 superset/config.py,也就是說將配置文件加載進來,看過官網(wǎng)的介紹應該也知道默認的配置文件就是這個。
  • 調(diào)用 app_initializer 進行一系列的初始化,配置文件里沒有的話,默認就調(diào)用 SupersetAppInitializer.init_app() 方法
    • 這個 init_app() 里面又處理了很多初始化的工作,比如 setup database, configure celery, config cache 等等
    • 最重要的還有一個 init_views() 方法。

代碼:https://github.com/apache/superset/blob/1.5/superset/initialization/init.py

def init_app(self) -> None:  
    """  
    Main entry point which will delegate to other methods in    order to fully init the app    """    self.pre_init()  
    self.check_secret_key()  
    # Configuration of logging must be done first to apply the formatter properly  
    self.configure_logging()  
    # Configuration of feature_flags must be done first to allow init features  
    # conditionally    self.configure_feature_flags()  
    self.configure_db_encrypt()  
    self.setup_db()  
    self.configure_celery()  
    self.enable_profiling()  
    self.setup_event_logger()  
    self.setup_bundle_manifest()  
    self.register_blueprints()  
    self.configure_wtf()  
    self.configure_middlewares()  
    self.configure_cache()  
  
    with self.superset_app.app_context():  
        self.init_app_in_ctx()  
  
    self.post_init()

init_views()

這個方法很重要,因為 Superset 后端是用 Flask + FlaskAppBuilder 這兩個框架去寫的,因此需要初始化一些 FlaskAppBuilder 的 views,API,links 等等。

到此為止,整個后端代碼的入口介紹就差不多了,后端核心的代碼放在 superset 文件夾中,通過文件夾的命名,也能夠看到大致的端倪。

這個看代碼入口的方法套到其他的開源項目也是適用的哦,這是一個屢試不爽的好方法。

如何上手代碼

想要更好地理解 Superset 的代碼,你還需要做一些額外的準備:

  • 熟悉 Python 語言,了解一些常見的語法糖,語言的特性。這樣看到報錯信息可以幫助更好地定位問題,而不是一頭霧水。
  • 熟悉 Flask 和 FlaskAppBuilder 框架,因為 Superset 的后端 API,views,models 的理解都需要在了解這兩個框架的基礎(chǔ)上。
  • 熟悉一些常見的 python package,如 SQLAlchemy,marshmallow,pandas,celery等。

最后

如果你對Superset的代碼或者二次開發(fā)有問題,可以找我咨詢,我組建了免費的社區(qū),大家都很樂于分享。如有需要,看我個人簡介來聯(lián)系我,注明來意~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容