前言
首先我們明確下什么叫做熱部署,熱部署是在不重啟 java 虛擬機(jī)的前提下,自動更新 class 的行為,從而更新整個運行時的邏輯。 在 java 開發(fā)領(lǐng)域,熱部署一直是一個難以解決的問題,java 虛擬機(jī)理論上只能實現(xiàn)方法體的修改熱部署,對于整個類結(jié)構(gòu)的更改,仍然需要重啟虛擬機(jī),對類重新加載才能完成更新操作。
OSGI
其實 java 業(yè)界有一些解決方案,比如 osgi 架構(gòu),這玩意時間比較長了,但一直沒火起來。osgi 架構(gòu)的出現(xiàn),可以讓 java 系統(tǒng)變成模塊化的形式,讓模塊重啟成為可能。從一定程度上也算是個熱部署的方案。可惜這玩意以前開發(fā)起來就覺得很反人類,配置文件一大堆不說,學(xué)習(xí)成本也很大。和 spring 結(jié)合起來,居然是一個模塊一個 spring 上下文體系。并且如果模塊之間有調(diào)用關(guān)系的話,重啟相關(guān)的模塊會讓應(yīng)用出現(xiàn)短暫的功能性休克,也就說,整個熱啟動過程不平滑。 這項技術(shù)現(xiàn)在估計很多小伙伴都沒聽說過,目前也漸漸的退出歷史舞臺,用的企業(yè)估計很少。
ASM
ASM 是一款修改字節(jié)碼的框架,同類型的框架還有 Cglib。這些框架能加載一個 class 信息,用戶可以按照自己的需求增強修改這些信息,最后輸出成一個新的 class。 具體實現(xiàn)過程,這里就不展開了。大家可以百度下,相關(guān)技術(shù)實現(xiàn)文章不少。 但單純修改字節(jié)碼一般要和其他技術(shù)結(jié)合起來,單靠這個也無法完成熱更新,雖然 ASM 類的框架能夠修改類,但是這些 ASM 的修改邏輯也是用 java 寫的,這段代碼也需要執(zhí)行的。如果你把 ASM 的代碼寫在 java 里,也無法實現(xiàn)從外部來熱更新。
Javaagent&Attach API 結(jié)合 ASM
這就是上面一段說的 ASM 要結(jié)合其他技術(shù)才能實現(xiàn)熱更新的方案,也是目前很多開源框架采用的方案。 比如大名鼎鼎的 Arthas,就是利用 javaagent 通過 Attach API 運行時加載目標(biāo) Java 程序,最終利用 Instrumention API 或者 ASM 增強 class,來實現(xiàn)代碼跟蹤,以及代碼熱修改的特性。 但筆者認(rèn)為用 Arthas 來完成線上代碼的熱更新,只能用于一些很緊急的場景。不能替代日常業(yè)務(wù)邏輯修改。而且操作起來也挺復(fù)雜。 你需要先修改 java 代碼,然后把 java 代碼放到服務(wù)器上,在 arthas 里查找這個類的類加載器的 hashcode,然后利用 arthas 提供的命令編譯 java 代碼輸出成新的 class 文件,最用利用redefine命令進(jìn)行熱更新。 試想下,如果大量邏輯的更改。這得有多麻煩。 所以更多的是利用 arthas 對線上應(yīng)用進(jìn)行診斷,追蹤,熱更改代碼其實就是 arthas 眾多功能中其中一個,并不是主要功能。
換一種思路
以上方案都是基于修改 class 本身,然后讓 JVM 的類加載器重新加載來實現(xiàn)的。 那么有沒有更好的方案呢? 其實 java 代碼可以運行一些腳本的,jdk 本身就支持調(diào)用腳本,從 JDK 1.6 開始,java 就支持 JSR223,可以用一致的形式在 JVM 上執(zhí)行一些腳本語言,而且可實時編譯,運行的效率和 java 不相上下的。 有的同學(xué)看到這里可能會拍磚了:利用腳本只能更改部分邏輯,不可能把所有的邏輯都用腳本寫吧,你這篇文章探討的不是 “有沒有可能所有的邏輯都可熱更新” 么? 別急,首先我們來確定一個事情。你的 java 應(yīng)用系統(tǒng)需不需要所有的邏輯都是可以熱更新的?很多代碼都是大致固定不變的,比如 util 類,一些 vo 的定義也不大變更的,一些固定的業(yè)務(wù)也不需要熱更新需求的。只有一些經(jīng)常變更的決策部分,可能需要熱更新。 那么我們只要把需要經(jīng)常變的部分用腳本來定義不就可以了么。 業(yè)界有沒有類似的開源框架呢? 還真有,而且是高 star 的熱門開源項目,能夠幫你做到用腳本進(jìn)行熱更新業(yè)務(wù)。
開源編排規(guī)則引擎
可能有小伙伴又要說了:你不是介紹 java 代碼熱部署么,怎么話題轉(zhuǎn)到規(guī)則引擎上去了? 這里要說下,規(guī)則引擎的一大特性就是把決策部分邏輯剝離到外面,能夠?qū)崿F(xiàn)邏輯的變動快速熱變更。 而這次介紹的規(guī)則引擎框架則更為強大,除了能剝離邏輯,還能解耦系統(tǒng),讓你的所有的邏輯塊均可隨意變更。理論上能實現(xiàn)所有的邏輯都可變更,不是部分哦。 這就是業(yè)界現(xiàn)在 很火的編排式規(guī)則引擎框架:LiteFlow。 LiteFlow 的理念很簡單,就是把系統(tǒng)中的各個邏輯切分成一小塊一小塊的,稱之為組件,這些組件可以由 java 代碼來寫,也可以用腳本來寫。然后一個完整業(yè)務(wù)就是把各個組件組搭一起,形成一個完整業(yè)務(wù)鏈。
這種模式的好處就是,不需要熱更新的部分可以用 java 組件來寫,需要經(jīng)常變的部分可以用腳本來寫。所有的組件均可混搭成為一個業(yè)務(wù)。如何編排這些組件,LiteFlow 獨創(chuàng)了 ELF 語法,擁有非常好上手的編排語法。程序員的話,十分鐘就可以上手。上圖粉色部分就是最簡單的一種串聯(lián)形式。 業(yè)務(wù)鏈路中組件可實時更換,也可實時增加,形成一個新的業(yè)務(wù)鏈。同時定義好的組件也可復(fù)用在其他的鏈路中。
LiteFlow 的腳本方案也是利用 JSR223 來實現(xiàn)的,目前已經(jīng)實現(xiàn)的腳本有三種:
為什么說利用 LiteFlow 編排引擎框架,你的所有邏輯都是可以變更的呢。因為你完全可以把所有的邏輯都用腳本組件來實現(xiàn),LiteFlow 提供了非常強大的腳本支持,完全和 Java 底層打通,你可以在腳本中 import java 的類,也可以調(diào)用 java 的類方法,甚至于可以在腳本中去定義方法,定義類,一切寫法和 java 中完全一樣。 更夸張的是,LiteFlow 允許你在腳本中調(diào)用 spring 上下文的 bean,你可以在腳本中調(diào)用 DAO 取數(shù)據(jù),可以在腳本中發(fā)送 rpc 給其他微服務(wù)。只要你愿意,你可以一行 java 業(yè)務(wù)代碼不寫,完全把業(yè)務(wù)搬到腳本組件中去。 而且連邏輯塊的順序你也可以隨意變動,因為 LiteFlow 的編排規(guī)則和腳本均可實現(xiàn)熱變更。 LiteFlow 為經(jīng)常用的存儲中間件也提供了原生支持:
LiteFlow 支持所有的關(guān)系型數(shù)據(jù)庫,另外 zk,etcd,nacos 均可支持,還提供了額外的擴(kuò)展接口,供你自己擴(kuò)展成其他的存儲方式。 有想過么,你所有的邏輯和規(guī)則編排語法,都是存在于系統(tǒng)之外的。只要更改其腳本和邏輯,你所有節(jié)點的系統(tǒng)不需要做任何事,實時的進(jìn)行熱變更。 而這一切,LiteFlow 做到了非常平滑,所謂平滑的意思是,不用擔(dān)心在熱變更的時候你的業(yè)務(wù)會受到任何的中斷,也不會因為熱變更造成正在執(zhí)行的鏈路產(chǎn)生任何的異常。 LiteFlow 編排能力有多強大呢,簡單的幾個關(guān)鍵字就可以編排出超乎想象的效果:
結(jié)語
在 java 的業(yè)務(wù)熱部署領(lǐng)域,LiteFlow 作為一款規(guī)則引擎,給出了一種新的解決思路。 除以上文中介紹的之外,LiteFlow 框架還擁有眾多的高級特性,從各個方位提升你系統(tǒng)的靈活性。 并且作為開源軟件,LiteFlow 擁有國內(nèi)非常好的社區(qū)氛圍和文化。 最后放出 LiteFlow 的官網(wǎng)和倉庫地址,如果你覺得這款開源框架對你的業(yè)務(wù)有幫助,趕緊來了解一下吧 。
項目官網(wǎng): https://liteflow.yomahub.com gitee
托管倉庫: https://gitee.com/dromara/liteFlow github
托管倉庫: https://github.com/dromara/liteflow
審核編輯:湯梓紅
-
JAVA
+關(guān)注
關(guān)注
19文章
2967瀏覽量
104752 -
代碼
+關(guān)注
關(guān)注
30文章
4788瀏覽量
68612 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
917瀏覽量
28197
原文標(biāo)題:Java項目有可能做到所有的代碼邏輯均可熱部署嗎?
文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論