Java EE应用程序的单片到微服务重构
您是否曾經(jīng)想過將現(xiàn)有的Java EE整體應(yīng)用程序重構(gòu)為基于微服務(wù)的應(yīng)用程序需要做什么?
該博客解釋了一個簡單的購物車示例如何轉(zhuǎn)換為基于微服務(wù)的應(yīng)用程序,以及圍繞它的一些擔(dān)憂。 整體和基于微服務(wù)的應(yīng)用程序的完整代碼庫位于: github.com/arun-gupta/microservices 。
繼續(xù)閱讀以獲取更多榮耀!
Java EE Monolith
Java EE整體應(yīng)用程序通常定義為WAR或EAR檔案。 該應(yīng)用程序的全部功能都打包在一個單元中。 例如,在線購物車可能包含用戶,目錄和訂單功能。 所有網(wǎng)頁都在應(yīng)用程序的根目錄中,所有相應(yīng)的Java類都在WEB-INF/classes目錄中,資源在WEB-INF/classes/META-INF目錄中。
讓我們假設(shè)您的整體設(shè)計不是設(shè)計為一個分散的大泥巴,并且該應(yīng)用程序是按照良好的軟件體系結(jié)構(gòu)構(gòu)建的。 一些常見的規(guī)則是:
- 分離關(guān)注點,可能使用Model-View-Controller
- 使用定義明確的API的高內(nèi)聚和低耦合
- 不要重復(fù)自己(干)
- 接口/ API和實現(xiàn)是分開的,并且遵循Demeter定律 。 類不會直接調(diào)用其他類,因為它們恰好位于同一存檔中
- 使用域驅(qū)動設(shè)計將與域/組件相關(guān)的對象保持在一起
- YAGNI或您不需要它:不要構(gòu)建您現(xiàn)在不需要的東西
這是一個瑣碎的購物車整體WAR存檔的外觀:
此整體應(yīng)用程序具有:
- 網(wǎng)頁,例如.xhtml文件,用于用戶,目錄和訂單組件,打包在歸檔的根目錄中。 這些網(wǎng)頁還打包了在不同網(wǎng)頁之間共享的所有CSS和JavaScript資源。
- 這三個組件的類在WEB-INF/classes目錄中的單獨軟件包中。 多個類使用的所有實用程序/公共類也都打包在這里。
- 每個組件的配置文件打包在WEB-INF/classes/META-INF目錄中。 該應(yīng)用程序的任何配置文件(例如分別連接和填充數(shù)據(jù)存儲的persistence.xml和load.sql也都打包在此處。
它具有眾所周知的體系結(jié)構(gòu),IDE友好,易于共享,簡化測試,易于部署等常見優(yōu)點 。 但同時也具有諸如敏捷性受限,持續(xù)交付的障礙,技術(shù)堆?!翱ㄗ ?#xff0c;技術(shù)債務(wù)增加等缺點 。
即使微服務(wù)如今已成為熱門,但整體還是不錯的。 即使那些對您不起作用的服務(wù),也可能不會立即遷移到微服務(wù)中,從而受益匪淺。 其他方法,例如更好的軟件工程和體系結(jié)構(gòu),可能會有所幫助。 微服務(wù)既不是免費的午餐也不是靈丹妙藥,它需要大量的投資才能成功,例如服務(wù)發(fā)現(xiàn),服務(wù)復(fù)制,服務(wù)監(jiān)視,容器,PaaS,彈性等等。
除非您的系統(tǒng)過于復(fù)雜而無法作為一個整體進(jìn)行管理,否則甚至不要考慮使用微服務(wù)。
微服務(wù)高級版
Java EE的微服務(wù)架構(gòu)
好了,我已經(jīng)聽說了所有這些內(nèi)容,但是想知道之前/之后的內(nèi)容,即整體代碼庫的外觀以及重構(gòu)后的微服務(wù)代碼庫的外觀。
首先,讓我們看一下整體架構(gòu):
該體系結(jié)構(gòu)的關(guān)鍵部分是:
- 在將用戶,訂單和目錄組件打包為單獨的WAR文件的情況下,應(yīng)在功能上分解應(yīng)用程序。 每個WAR文件應(yīng)具有該組件所需的相關(guān)網(wǎng)頁( #15 ),類和配置文件。
- Java EE用于實現(xiàn)每個組件,但是對堆棧沒有長期承諾,因為不同的組件使用定義良好的API( #14 )相互通信。
- 每個檔案都有自己的數(shù)據(jù)庫,即不共享數(shù)據(jù)存儲。 這允許每個微服務(wù)發(fā)展和選擇最合適的數(shù)據(jù)存儲類型-關(guān)系,NoSQL,平面文件,內(nèi)存中或其他。
- 每個組件都將向服務(wù)注冊中心注冊。 這是必需的,因為每個服務(wù)的多個無狀態(tài)實例可能在給定的時間運行,并且它們的確切端點位置僅在運行時才知道( #17 )。 Netflix Eureka , Etcd , Zookeeper是該領(lǐng)域的一些選項( 更多詳細(xì)信息 )。
- 如果組件之間需要相互通信(這很常見),則可以使用預(yù)定義的API進(jìn)行通信。 實現(xiàn)同步的REST或?qū)崿F(xiàn)異步通信的Pub / Sub是實現(xiàn)此目的的常用方法。在我們的案例中,Order組件發(fā)現(xiàn)用戶和目錄服務(wù),并使用REST API與它們進(jìn)行對話。
- 該應(yīng)用程序的客戶端交互是在另一個應(yīng)用程序(在本例中為Shopping Cart UI)中定義的。 該應(yīng)用程序主要從服務(wù)注冊表中發(fā)現(xiàn)服務(wù)并將其組合在一起。 它應(yīng)該主要是一個啞代理,在其中調(diào)用不同組件的UI頁面以顯示界面( #18 )??梢酝ㄟ^提供標(biāo)準(zhǔn)CSS / JavaScript資源來實現(xiàn)常見的外觀。
該應(yīng)用程序相當(dāng)瑣碎,但至少強(qiáng)調(diào)了一些基本的體系結(jié)構(gòu)差異。
整體與微服務(wù)
下面比較了基于單體和基于微服務(wù)的應(yīng)用程序的一些統(tǒng)計信息:
| 檔案數(shù)量 | 1個 | 5
|
| 網(wǎng)頁 | 8 | 8(見下文) |
| 配置文件 | 4
| 每個檔案3個
|
| 類文件 | 12 | 26
|
| 檔案總大小 | 24 KB | ?52 KB(總計) |
- 整體應(yīng)用程序的代碼庫位于: github.com/arun-gupta/microservices/tree/master/monolith/everest
- 支持微服務(wù)的應(yīng)用程序的代碼庫位于: github.com/arun-gupta/microservices/tree/master/microservice
問題和待辦事項
以下是將整體重構(gòu)為基于微服務(wù)的應(yīng)用程序時遇到的問題和TODO:
- Java EE已經(jīng)允許使用EAR打包對應(yīng)用程序進(jìn)行功能分解。 應(yīng)用程序的每個組件都可以打包為WAR文件,并捆綁在EAR文件中。 他們甚至可以通過這種方式共享資源。 現(xiàn)在這不是真正的微服務(wù)方式,但這可能是使您入門的過渡步驟。 但是,請注意, @FlowScoped bean沒有在EAR中正確激活( WFLY-4565 )。
- 使用JSF資源庫模板提取所有模板文件。
- 目前,所有網(wǎng)頁都在everest模塊中,但它們應(yīng)該位于每個組件中( #15 )。
- 將整體數(shù)據(jù)庫拆分為多個數(shù)據(jù)庫需要為每個應(yīng)用程序使用單獨的persistence.xml和DDL / DML腳本。 同樣,需要相應(yīng)地創(chuàng)建遷移腳本,例如使用Flyway。
- 必須為所有組件創(chuàng)建一個REST接口,該接口需要被另一個組件訪問。
- UI仍在單個Web應(yīng)用程序中。 而是應(yīng)將其包含在已分解的WAR( #15 )中,然后再在啞代理中進(jìn)行組合。 聞起來像portlet嗎?
- 在PaaS中部署多個WAR文件( #12 )
- 每個微服務(wù)都應(yīng)易于部署在容器中( #6 )
這是單片應(yīng)用程序的類的完整列表:
./target/classes/org/javaee7/wildfly/samples/everest/cart/Cart.class ./target/classes/org/javaee7/wildfly/samples/everest/cart/CartItem.class ./target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItem.class ./target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemBean.class ./target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemType.class ./target/classes/org/javaee7/wildfly/samples/everest/checkout/Order.class ./target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderBean.class ./target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderItem.class ./target/classes/org/javaee7/wildfly/samples/everest/checkout/Shipping.class ./target/classes/org/javaee7/wildfly/samples/everest/uzer/Uzer.class ./target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerBean.class ./target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerItem.class這是基于微服務(wù)的應(yīng)用程序的類的完整列表:
./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/ApplicationConfig.class ./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItem.class ./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemREST.class ./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItemType.class ./catalog/target/classes/org/javaee7/wildfly/samples/everest/catalog/ServiceRegistration.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/cart/Cart.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/cart/CartItem.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogBean.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/catalog/CatalogItem.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/Order.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderBean.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/OrderItem.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/checkout/Shipping.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscovery.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscoveryStatic.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscoveryURI.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/ServiceDiscoveryZooKeeper.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerBean.class ./everest/target/classes/org/javaee7/wildfly/samples/everest/uzer/UzerItem.class ./order/target/classes/org/javaee7/wildfly/samples/everest/order/ApplicationConfig.class ./order/target/classes/org/javaee7/wildfly/samples/everest/order/Order.class ./order/target/classes/org/javaee7/wildfly/samples/everest/order/OrderItem.class ./order/target/classes/org/javaee7/wildfly/samples/everest/order/OrderREST.class ./user/target/classes/org/javaee7/wildfly/samples/everest/uzer/ApplicationConfig.class ./user/target/classes/org/javaee7/wildfly/samples/everest/uzer/UserREST.class ./user/target/classes/org/javaee7/wildfly/samples/everest/uzer/Uzer.class- 同樣,完整的代碼庫位于github.com/arun-gupta/microservices 。
未來話題
本系列中的一些未來主題將是:
- 微服務(wù)是否需要容器?
- 如何使用容器部署多個微服務(wù)?
- 如何輕松監(jiān)控所有這些服務(wù)?
- A / B測試
- 使用微服務(wù)和容器進(jìn)行連續(xù)部署
您還想看些什么?
請享用!
翻譯自: https://www.javacodegeeks.com/2015/06/monolithic-to-microservices-refactoring-for-java-ee-applications.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Java EE应用程序的单片到微服务重构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: #102030:在30天内运行20 10
- 下一篇: 义乌海关备案去哪里(义乌海关备案)