Java專案有可能做到所有的程式碼邏輯均可熱部署嗎?

鉑賽東發表於2022-11-22

前言

首先我們明確下什麼叫做熱部署,熱部署是在不重啟java虛擬機器的前提下,自動更新class的行為,從而更新整個執行時的邏輯。

在java開發領域,熱部署一直是一個難以解決的問題,java虛擬機器理論上只能實現方法體的修改熱部署,對於整個類結構的更改,仍然需要重啟虛擬機器,對類重新載入才能完成更新操作。

OSGI

其實java業界有一些解決方案,比如osgi架構,這玩意時間比較長了,但一直沒火起來。osgi架構的出現,可以讓java系統變成模組化的形式,讓模組重啟成為可能。從一定程度上也算是個熱部署的方案。可惜這玩意以前開發起來就覺得很反人類,配置檔案一大堆不說,學習成本也很大。和spring結合起來,居然是一個模組一個spring上下文體系。並且如果模組之間有呼叫關係的話,重啟相關的模組會讓應用出現短暫的功能性休克,也就說,整個熱啟動過程不平滑。

這項技術現在估計很多小夥伴都沒聽說過,目前也漸漸的退出歷史舞臺,用的企業估計很少。

ASM

ASM是一款修改位元組碼的框架,同型別的框架還有Cglib。這些框架能載入一個class資訊,使用者可以按照自己的需求增強修改這些資訊,最後輸出成一個新的class。

具體實現過程,這裡就不展開了。大家可以百度下,相關技術實現文章不少。

但單純修改位元組碼一般要和其他技術結合起來,單靠這個也無法完成熱更新,雖然ASM類的框架能夠修改類,但是這些ASM的修改邏輯也是用java寫的,這段程式碼也需要執行的。如果你把ASM的程式碼寫在java裡,也無法實現從外部來熱更新。

Javaagent&Attach API結合ASM

這就是上面一段說的ASM要結合其他技術才能實現熱更新的方案,也是目前很多開源框架採用的方案。

比如大名鼎鼎的Arthas,就是利用javaagent透過Attach API執行時載入目標Java程式,最終利用Instrumention API或者ASM增強class,來實現程式碼跟蹤,以及程式碼熱修改的特性。

但筆者認為用Arthas來完成線上程式碼的熱更新,只能用於一些很緊急的場景。不能替代日常業務邏輯修改。而且操作起來也挺複雜。

你需要先修改java程式碼,然後把java程式碼放到伺服器上,在arthas裡查詢這個類的類載入器的hashcode,然後利用arthas提供的命令編譯java程式碼輸出成新的class檔案,最用利用redefine命令進行熱更新。

試想下,如果大量邏輯的更改。這得有多麻煩。

所以更多的是利用arthas對線上應用進行診斷,追蹤,熱更改程式碼其實就是arthas眾多功能中其中一個,並不是主要功能。

換一種思路

以上方案都是基於修改class本身,然後讓JVM的類載入器重新載入來實現的。

那麼有沒有更好的方案呢?

其實java程式碼可以執行一些指令碼的,jdk本身就支援呼叫指令碼,從JDK 1.6開始,java就支援JSR223,可以用一致的形式在JVM上執行一些指令碼語言,而且可實時編譯,執行的效率和java不相上下的。

有的同學看到這裡可能會拍磚了:利用指令碼只能更改部分邏輯,不可能把所有的邏輯都用指令碼寫吧,你這篇文章探討的不是“有沒有可能所有的邏輯都可熱更新”麼?

別急,首先我們來確定一個事情。你的java應用系統需不需要所有的邏輯都是可以熱更新的?很多程式碼都是大致固定不變的,比如util類,一些vo的定義也不大變更的,一些固定的業務也不需要熱更新需求的。只有一些經常變更的決策部分,可能需要熱更新。

那麼我們只要把需要經常變的部分用指令碼來定義不就可以了麼。

業界有沒有類似的開源框架呢?

還真有,而且是高star的熱門開源專案,能夠幫你做到用指令碼進行熱更新業務。

開源編排規則引擎

可能有小夥伴又要說了:你不是介紹java程式碼熱部署麼,怎麼話題轉到規則引擎上去了?

這裡要說下,規則引擎的一大特性就是把決策部分邏輯剝離到外面,能夠實現邏輯的變動快速熱變更。

而這次介紹的規則引擎框架則更為強大,除了能剝離邏輯,還能解耦系統,讓你的所有的邏輯塊均可隨意變更。理論上能實現所有的邏輯都可變更,不是部分哦。

這就是業界現在 很火的編排式規則引擎框架:LiteFlow

LiteFlow的理念很簡單,就是把系統中的各個邏輯切分成一小塊一小塊的,稱之為元件,這些元件可以由java程式碼來寫,也可以用指令碼來寫。然後一個完整業務就是把各個元件組搭一起,形成一個完整業務鏈。

1.png

這種模式的好處就是,不需要熱更新的部分可以用java元件來寫,需要經常變的部分可以用指令碼來寫。所有的元件均可混搭成為一個業務。如何編排這些元件,LiteFlow獨創了ELF語法,擁有非常好上手的編排語法。程式設計師的話,十分鐘就可以上手。上圖粉色部分就是最簡單的一種串聯形式。

業務鏈路中元件可實時更換,也可實時增加,形成一個新的業務鏈。同時定義好的元件也可複用在其他的鏈路中。

2.png

LiteFlow的指令碼方案也是利用JSR223來實現的,目前已經實現的指令碼有三種:

3.png

為什麼說利用LiteFlow編排引擎框架,你的所有邏輯都是可以變更的呢。因為你完全可以把所有的邏輯都用指令碼元件來實現,LiteFlow提供了非常強大的指令碼支援,完全和Java底層打通,你可以在指令碼中import java的類,也可以呼叫java的類方法,甚至於可以在指令碼中去定義方法,定義類,一切寫法和java中完全一樣。

更誇張的是,LiteFlow允許你在指令碼中呼叫spring上下文的bean,你可以在指令碼中呼叫DAO取資料,可以在指令碼中傳送rpc給其他微服務。只要你願意,你可以一行java業務程式碼不寫,完全把業務搬到指令碼元件中去。

而且連邏輯塊的順序你也可以隨意變動,因為LiteFlow的編排規則和指令碼均可實現熱變更。

LiteFlow為經常用的儲存中介軟體也提供了原生支援:

4.png

LiteFlow支援所有的關係型資料庫,另外zk,etcd,nacos均可支援,還提供了額外的擴充套件介面,供你自己擴充套件成其他的儲存方式。

有想過麼,你所有的邏輯和規則編排語法,都是存在於系統之外的。只要更改其指令碼和邏輯,你所有節點的系統不需要做任何事,實時的進行熱變更。

而這一切,LiteFlow做到了非常平滑,所謂平滑的意思是,不用擔心在熱變更的時候你的業務會受到任何的中斷,也不會因為熱變更造成正在執行的鏈路產生任何的異常。

LiteFlow編排能力有多強大呢,簡單的幾個關鍵字就可以編排出超乎想象的效果:

5.png

6.png

結語

在java的業務熱部署領域,LiteFlow作為一款規則引擎,給出了一種新的解決思路。

除以上文中介紹的之外,LiteFlow框架還擁有眾多的高階特性,從各個方位提升你係統的靈活性。

並且作為開源軟體,LiteFlow擁有國內非常好的社群氛圍和文化。

最後放出LiteFlow的官網和倉庫地址,如果你覺得這款開源框架對你的業務有幫助,趕緊來了解一下吧

專案官網:

https://liteflow.yomahub.com

gitee託管倉庫:

https://gitee.com/dromara/lit...

github託管倉庫:

https://github.com/dromara/li...

相關文章