行鏈路)
Gretty 源碼深度剖析從 Gradle 插件到 Runner 的完整執(zhí)行鏈路【免費(fèi)下載鏈接】grettyAdvanced gradle plugin for running web-apps on jetty and tomcat.項(xiàng)目地址: https://gitcode.com/gh_mirrors/gr/gretty當(dāng)你在build.gradle里敲下apply plugin: org.akhikhl.gretty再執(zhí)行一行g(shù)radle appRun一個(gè) Jetty 或 Tomcat 容器便神奇地啟動(dòng)起來瀏覽器自動(dòng)彈出你的 Web 應(yīng)用。Gretty正是這樣一個(gè)高級(jí) Gradle 插件它把構(gòu)建 Web 應(yīng)用并在 Jetty/Tomcat 上運(yùn)行這件事簡化到了極致。但這一行命令背后到底發(fā)生了什么從Gradle 插件注冊(cè)任務(wù)、到DefaultLauncher拉起獨(dú)立 JVM、再到Runner進(jìn)程里啟動(dòng) Servlet 容器是一條設(shè)計(jì)精巧的完整執(zhí)行鏈路。本文將從源碼角度把這條鏈路從頭到尾拆給你看幫助你真正理解 Gretty 的運(yùn)行機(jī)制。一、Gretty 源碼整體架構(gòu)三個(gè)關(guān)鍵層次 ?在深入執(zhí)行鏈路之前先認(rèn)識(shí) Gretty 的源碼布局。克隆倉庫后核心代碼集中在libs/目錄下可以分成三個(gè)層次層次模塊職責(zé)Gradle 插件層libs/gretty/與 Gradle 深度耦合注冊(cè)任務(wù)、擴(kuò)展、配置、依賴橋接層libs/gretty-core/、libs/gretty-runner/進(jìn)程啟動(dòng)、端口協(xié)商、服務(wù)協(xié)議、Runner 主類容器適配層gretty-runner-jetty7/8/9/93/94、gretty-runner-tomcat/7/8針對(duì)不同 Servlet 容器實(shí)現(xiàn)ServerManager這種分層設(shè)計(jì)非常巧妙Gradle 插件層libs/gretty只負(fù)責(zé)與構(gòu)建系統(tǒng)交互容器適配層完全獨(dú)立于 Gradle甚至可以直接復(fù)用。理解了這三個(gè)層次整條執(zhí)行鏈路就清晰了一半。二、執(zhí)行鏈路總覽一次 appRun 的完整旅程 一次gradle appRun的完整執(zhí)行大致經(jīng)歷以下五個(gè)階段插件入口GrettyPlugin.apply()注冊(cè)擴(kuò)展與任務(wù)任務(wù)執(zhí)行AppStartTask組裝配置構(gòu)造DefaultLauncher進(jìn)程拉起LauncherBase協(xié)商端口通過javaexec啟動(dòng) Runner 子進(jìn)程服務(wù)循環(huán)Runner主進(jìn)程監(jiān)聽命令調(diào)用ServerManager啟動(dòng)容器交互控制Gradle 側(cè)監(jiān)聽按鍵向 Runner 發(fā)送 restart/stop 指令下面我們逐個(gè)階段深入剖析。三、第一階段插件入口 —— GrettyPlugin 干了什么 一切從GrettyPlugin開始它是整個(gè)插件的總開關(guān)源碼位于 GrettyPlugin.groovy。它的apply()方法主要做了四件事1. 注冊(cè)擴(kuò)展DSLproject.extensions.create(gretty, GrettyExtension) project.extensions.create(farm, FarmExtension, project) project.extensions.create(product, ProductExtension)這就是你能在build.gradle里寫gretty { ... }、farm { ... }配置塊的來源。2. 批量注冊(cè)任務(wù)在addTasks()方法中插件一口氣注冊(cè)了幾十個(gè)任務(wù)appRun、appStart、appStop、appRestart、jettyRun、tomcatRun以及各自的 Debug 變體如appRunDebug還有集成測試配套的appBeforeIntegrationTest/appAfterIntegrationTest。3. 建立任務(wù)依賴在addTaskDependencies()中appRun會(huì)依賴prepareInplaceWebApp或prepareArchiveWebApp確保啟動(dòng)前 Web 應(yīng)用資源已準(zhǔn)備就緒。4. 注入依賴配置插件還會(huì)為 Spring Boot 項(xiàng)目自動(dòng)排除內(nèi)嵌 Tomcat/Jetty避免與 Gretty 管理的容器沖突這正是 Gretty 能優(yōu)雅支持 Spring Boot 的關(guān)鍵細(xì)節(jié)。小知識(shí)GrettyStartTask類已標(biāo)記Deprecated建議直接使用AppStartTask源碼見 GrettyStartTask.groovy。四、第二階段任務(wù)執(zhí)行 —— StartBaseTask 的模板方法 運(yùn)行appRun時(shí)實(shí)際執(zhí)行的是AppStartTask繼承自StartBaseTask。StartBaseTask是一個(gè)經(jīng)典的模板方法模式實(shí)現(xiàn)源碼見 StartBaseTask.groovy。它的核心是TaskAction action()方法LauncherConfig config getLauncherConfig() Launcher launcher new DefaultLauncher(project, config) launcher.scannerManager createScannerManager(config, ...) launcher.launch()而AppStartTask.getStartConfig()見 AppStartTask.groovy負(fù)責(zé)把 DSL 配置、項(xiàng)目默認(rèn)值、命令行參數(shù)合并成最終的ServerConfig和WebAppConfig并調(diào)用doPrepareServerConfig()處理證書生成、Jacoco 參數(shù)注入、SpringLoaded 熱加載 agent 等細(xì)節(jié)。五、第三階段進(jìn)程拉起 —— LauncherBase 與端口協(xié)商 DefaultLauncher繼承了LauncherBase源碼在 LauncherBase.groovy這里藏著兩個(gè)重要機(jī)制1. 端口協(xié)商beforeLaunch()會(huì)先檢查build/gretty_ports屬性文件判斷服務(wù)器是否已在運(yùn)行如果未運(yùn)行則通過findFreePorts()分配兩個(gè)空閑端口servicePort服務(wù)端口用于接收命令和statusPort狀態(tài)端口用于回報(bào)啟動(dòng)狀態(tài)并寫入屬性文件。2. 啟動(dòng)子進(jìn)程launchThread()中會(huì)構(gòu)造JavaExecParams以org.akhikhl.gretty.Runner為主類通過javaexec在獨(dú)立的 JVM 進(jìn)程中啟動(dòng)服務(wù)器params.main org.akhikhl.gretty.Runner params.args [ --servicePort${servicePort}, --statusPort${statusPort}, --serverManagerFactory${getServerManagerFactory()} ]設(shè)計(jì)亮點(diǎn)服務(wù)器運(yùn)行在獨(dú)立進(jìn)程中與 Gradle 守護(hù)進(jìn)程隔離。即使 Gradle 任務(wù)結(jié)束服務(wù)器也能存活這也是appStart非交互模式能后臺(tái)常駐的原因。六、第四階段Runner 主進(jìn)程 —— 命令驅(qū)動(dòng)的服務(wù)循環(huán) Runner是獨(dú)立 JVM 的入口源碼見 Runner.groovy它的main()解析三個(gè)命令行參數(shù)后進(jìn)入一個(gè)死循環(huán)創(chuàng)建ServerSocket監(jiān)聽servicePort并向 Gradle 側(cè)發(fā)送init信號(hào)循環(huán)讀取 Gradle 側(cè)發(fā)來的 JSON 命令首次收到配置后加載 logback 日志配置調(diào)用ServerManager.startServer()之后根據(jù)命令響應(yīng)status返回啟動(dòng)狀態(tài)、stop停止服務(wù)器并退出、restart重啟容器、redeploy xxx熱部署指定 Web 應(yīng)用這個(gè)機(jī)制讓Gradle 任務(wù)已退出、服務(wù)器仍在運(yùn)行成為可能服務(wù)器啟動(dòng)后appRun的交互循環(huán)只是不停讀取鍵盤輸入并把按鍵翻譯成restartWithEvent等命令發(fā)給 Runner。七、第五階段ServerManager —— 容器適配層的抽象 ServerManager是容器適配層的核心接口ServerManager.groovy只定義四個(gè)方法setParams()—— 注入運(yùn)行參數(shù)startServer()—— 啟動(dòng)容器stopServer()—— 停止容器redeploy()—— 熱部署指定應(yīng)用每個(gè)容器版本提供自己的實(shí)現(xiàn)gretty-runner-jetty9、gretty-runner-jetty94負(fù)責(zé) Jetty 各版本gretty-runner-tomcat8等負(fù)責(zé) Tomcat。Runner 通過Class.forName(params.serverManagerFactory)反射加載對(duì)應(yīng)的工廠類從而與具體容器解耦。這種一個(gè) Runner 多個(gè) ServerManager 實(shí)現(xiàn)的架構(gòu)讓 Gretty 只需一份命令協(xié)議就能無縫支持 Jetty 7/8/9/9.3/9.4 與 Tomcat 7/8 全家桶。八、熱部署與自動(dòng)重啟的秘密Scanner 機(jī)制 執(zhí)行鏈路之外Gretty 最受好評(píng)的熱部署功能也值得一看。StartBaseTask的createScannerManager()支持兩種掃描器源碼見 scanner/JDKScannerManager.groovy 和 JettyScannerManager.groovyJDK 掃描器基于WatchService性能更高優(yōu)先使用Jetty 掃描器作為 JDK 掃描器不可用時(shí)的降級(jí)方案當(dāng)掃描器檢測到 class 或資源變化時(shí)會(huì)通過asyncResponse向 Runner 發(fā)送restartWithEvent命令并等待完成事件實(shí)現(xiàn)優(yōu)雅的熱重啟。若開啟了 Spring Loaded 的managedClassReload還能實(shí)現(xiàn)類級(jí)別的熱替換。九、進(jìn)階場景Farm 多應(yīng)用集群與集成測試 如果你有多個(gè) Web 應(yīng)用需要同時(shí)運(yùn)行Gretty 的Farm機(jī)制會(huì)派出用場。GrettyPlugin.addTasks()會(huì)為每個(gè) farm 生成farmRun、farmStart、farmStop等一系列任務(wù)在同一個(gè)容器中部署多個(gè)應(yīng)用。此外appBeforeIntegrationTest/appAfterIntegrationTest任務(wù)與integrationTest任務(wù)配合可以在測試前自動(dòng)啟動(dòng)服務(wù)器、測試后自動(dòng)關(guān)閉——配合integrationTests/目錄下的大量示例如 farm/、helloGretty/你可以快速學(xué)會(huì)各種場景的用法。十、總結(jié)一次點(diǎn)擊背后的精妙設(shè)計(jì) 回看整條鏈路Gradle 插件注冊(cè)任務(wù) → 任務(wù)組裝配置 → Launcher 協(xié)商端口 → 獨(dú)立 JVM 中的 Runner 循環(huán) → ServerManager 啟動(dòng)容器 → Scanner 驅(qū)動(dòng)熱部署。Gretty 的成功源于兩個(gè)關(guān)鍵決策進(jìn)程隔離服務(wù)器跑在獨(dú)立 JVM 中與 Gradle 生命周期解耦協(xié)議抽象統(tǒng)一的服務(wù)協(xié)議 可插拔的容器適配層一份命令通吃所有容器希望這篇 Gretty 源碼剖析能幫你建立起從 Gradle 插件到 Runner 的完整認(rèn)知。下次運(yùn)行g(shù)radle appRun時(shí)你就能清楚地知道屏幕背后那條精心設(shè)計(jì)的執(zhí)行鏈路正在如何為你工作。如果想親手驗(yàn)證可以用git clone https://gitcode.com/gh_mirrors/gr/gretty拉取源碼邊讀邊調(diào)試收獲會(huì)更大?!久赓M(fèi)下載鏈接】grettyAdvanced gradle plugin for running web-apps on jetty and tomcat.項(xiàng)目地址: https://gitcode.com/gh_mirrors/gr/gretty創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考