劉從軍,劉 毅
1(江蘇科技大學 計算機學院,鎮江 212003)
2(江蘇科大匯峰科技有限公司,鎮江 212003)
“微服務”的概念,雖然誕生時間不長,卻迅速的成為了軟件架構領域爭相討論的熱點.在微服務架構理論不斷完善的同時,具體實施微服務架構的相關技術框架也正在不斷的涌現出來.
國內最出名的微服務框架是阿里巴巴旗下服務化治理框架Dubbo,該框架目前除了應用于阿里巴巴集團的各成員站點,也被國內很多互聯網公司使用.
國外的微服務框架Spring Cloud 最為突出,Spring Cloud 是Spring 家族的產品,它包含了開發分布式系統所必需的多個組件,覆蓋了微服務架構開發的方方面面,在微服務開發中相對比較成熟.微服務框架在各個系統中的應用也越來越廣泛.
相對于微服務架構,傳統的單體式架構系統往往存在以下的問題:
(1)開發效率低:代碼的編寫在同一個項目中進行,開發人員提交代碼時沖突嚴重.
(2)代碼維護難:項目中包含太多模塊,模塊之間耦合性高,當某一功能需要修改時,可能會關聯或影響到其他功能的使用[1].
(3)部署效率低:單體式架構需要整體部署,修改系統中一個小功能都需要重新部署應用.當項目功能復雜、代碼量大的時候,構建和部署項目需要花費大量時間,并且當修改其中一個功能時,雖然其他功能沒有問題,但依然不能正常使用[2].
(4)可靠性不高:所有模塊運行在同一進程.任何一個模塊出現故障,可能會導致整個系統崩潰.
(5)擴展能力低:因為個模塊之間耦合度高,需要添加新的功能時,往往需要大規模的改動項目.
隨著房地產市場的飛速發展,房屋的維修資金的交存使用以及監管問題成為了廣大業主以及政府相關部門所關心的重要問題[3].目前存在的住宅維修資金管理系統,大多屬于基于單體式架構的應用系統,這些系統也存在著這些問題:1)系統每一個功能的新增或者修改都需要重新部署整個系統,屆時其他功能也無法使用.如新增維修資金查詢的圖表分析的功能時,雖然只涉及到查詢部分的功能,但是資金交存以及資金的使用辦理等功能依然無法使用.2)系統資金交存辦理時,如果同一時刻交存人數過多,系統處理特別慢,系統性能不足以支撐高并發訪問.3)系統中如果某一功能出現故障,會導致整個系統不可用.比如系統中的查詢模塊出現問題時,整個系統都會崩潰不能運行,此時資金交存、使用等功能雖然沒有問題仍會不可使用.
為解決現階段維修資金管理系統建設中存在的問題,本文提出了基于Spring Cloud 的微服務架構,將系統中高度耦合的功能分解到各個離散的微服務中以實現對應用系統的解耦[4].將系統拆分為幾個微服務同時進行開發,加快系統開發周期,降低了系統部署的難度.每個服務之間通過RESTful API 接口進行通信,以業務為中心,構建起自動化運行機制,實現了集中式管理[5].
微服務架構(Microservice Architect)是近年來軟件開發領域興起的一種新型軟件架構,它提倡將單塊架構的應用劃分成一組小的服務,服務之間互相協調、互相配合,為用戶提供最終價值[6].每個服務運行在其獨立的進程中,服務與服務間采用輕量級的通信機制互相溝通[7].每個服務都圍繞著具體業務進行構建,并且能夠被獨立的部署到生產環境、類生產環境等.微服務架構旨在通過將功能分解到各個離散的服務中以實現對解決方案的解耦[8].
微服務架構如圖1所示.

圖1 微服務架構圖
微服務架構的優點[9]可以總結如下:
(1)微服務將巨大單體式應用分解為多個小服務,每個服務業務清晰、功能明確簡單、代碼量小,開發和維護單個微服務相對簡單.解決了系統開發和維護的復雜性問題.
(2)每個微服務可以有不同的人員進行開發,并且開發技術棧不受限制,開發人員可以采取不同的技術進行開發.
(3)每個微服務可以獨立的部署,相對于單體應用來說,微服務架構下若某一功能需求發生變更,只需對這一單獨的服務重新編碼部署,不影響其他服務的使用.
(4)每個服務獨立擴展,可以根據新的需求,實現細粒度的擴展.
Spring Cloud 是一個微服務框架,主要為了簡化分布式系統的開發.利用Spring Boot 一鍵啟動、部署的特點對云應用開發中的服務注冊發現、API Gateway、斷路器、服務配置治理、負載均衡等操作都提供了簡單的開發方式.
由于Spring Cloud 微服務框架相對于其他微服務框架更為成熟,Spring 社區也更為活躍,故選用Spring Cloud 作為系統微服務的開發框架.
國務院頒布的《住宅共用部分設施設備維修基金管理辦法》中對“維修基金”的定義是:專項用于住宅共用部位、共用設施設備保修期滿后的大修、更新、改造的資金[10].
隨著各地房地產業的發展,維修資金的使用的管理越來越復雜,這就需要建立科學的、信息化的管理體系,來實現維修資金的自動化管理[11].住宅維修資金管理系統應該滿足以下的需求:
(1)對小區、樓盤以及資金交存的銀行和業主等信息進行整合,建立房屋的信息數據庫,實現對小區、樓盤等信息的規范化管理.
(2)建立一套規范而且完善的住房維修資金管理業務流程,實現維修資金交存、使用等管理工作的規范化與自動化.
(3)實現維修工程、意見征詢以及資金撥付等審批的科學化、信息化.使業務的審核流程變得更為簡便快捷.
(4)實現對維修工程數據以及資金交存、使用等數據的統計分析.方便業主查詢自己的維修資金,方便領導對維修工程的審查與決策.
根據系統的功能需求,分析得出系統的業務流程主要分為資金的交存和使用兩部分,系統總體的業務流程圖如圖2所示.

圖2 系統業務流程圖
2.2.1 微服務拆分
根據系統的需求分析,將整個系統分為4 個微服務模塊來完成功能開發,分別是基礎數據管理服務、資金交存服務、資金使用服務、查詢統計服務.四個微服務的功能如下:
基礎數據管理服務主要包括對樓盤信息、物業區域信息、物業公司信息、維修公司信息、開發企業信息、銀行信息和銀行賬戶信息等數據的管理.
資金交存服務主要是指資金交存管理、資金續交、交存調整三個功能.
資金使用服務包括從維修工程開始到資金結付等所有內容,是住宅專項維修資金管理的重要組成部分.主要是維修工程申報和審核、維修意見的征詢和審核、維修工程的驗收和審核以及維修資金的撥付和審批.
查詢與統計分析模塊包括了維修資金交存記錄查詢、維修資金使用記錄查詢、銀行賬戶流水查詢、維修工程信息查詢以及這些數據的圖表統計和報表打印等.
2.2.2 微服務總體架構設計
為了住宅專項維修資金管理系統每個微服務的開發與分工更容易界定,同時降低開發難度并且提升工作效率;以及系統后期部署時,可以實現業務邏輯和應用界面分別部署在不同的服務器中,提高系統服務的并行性能,并且系統各服務依賴的數據庫也單獨部署,提升系統數據的安全性和可靠性;為系統復雜的業務流程之間的關系解耦,使系統達到“高內聚,低耦合”的設計目標而采用了分層架構的設計模式.依照以上設計原則,將系統分為基礎支撐層、數據層、服務層、接口層以及應用層進行開發,系統架構圖如圖3所示.各層包含內容如下:
(1)基礎支撐層:主要包括機房、服務器及網絡設備、安全組件和光纖寬帶接入等組成,支撐和保障了整個服務平臺穩定安全的運行.
(2)數據層:數據層主要包資金信息的數據、項目信息的數據、和電子材料數據等.項目采用統一的數據中心管理模式,對平臺數據進行統一有效的管理,解決各服務間數據對接和數據共享問題.
(3)平臺服務層:主要包括基礎的業務服務如基礎數據管理服務、資金交存服務、資金使用服務和查詢統計分析服務.還包括以Spring Cloud 為基礎的微服務架構服務,如微服務的基石服務注冊和發現組件Eureka、基于Ribbon 的負載均衡組件、基于Hystrix斷路器及容錯處理機制以及基于Spring Cloud Config的自動化服務等.以上搭建了微服務架構,并完成基礎業務服務的功能.
(4)接口層:使用API Zuul 網關統一所有的服務接口,連接平臺服務與系統應用,包括與銀行的數據對接等,使用JWT 實現身份認證等權限的管理.
(5)應用層:包括對于業主用戶的意見征詢和賬戶查詢以及工程查詢的功能、對于小區物管的意見征詢和工程申報等功能、對于政府相關部門的業務辦理以及審核等功能和對于銀行系統的資金數據報接功能以及移動端應用的功能.
系統微服務架構由Spring Cloud 組件構建組成.通過Eureka 組件實現服務注冊與發現;Feign 組件實現服務的Ribbon 負載均衡與Eureka 的整合,加強網絡數據處理能力、提高網絡的靈活性和可用性;將基礎數據處理、資金交存等四個業務微服務注冊到Eureka 服務端,并通過Fegin 實現的負載均衡完成對外的調用.通過Zuul 實現服務網關,統一向外系統提供RESTful API;Hystrix 實現微服務的容錯處理,避免在微服務架構中個別服務出現異常時引起的故障蔓延;數據庫使用SQL Server 數據庫,各個業務服務都有獨立數據庫,并且使用Redis 作為緩存處理.

圖3 系統架構圖
服務的注冊和發現是微服務架構的基礎[12].Spring Cloud 搭建服務注冊中心的核心就是服務發現組件:Eureka.Eureka 一般搭配負載均衡組件Ribbon 使用,服務發現的架構圖如圖4所示.

圖4 服務發現架構圖
Eureka Server 端實現如下:
(1)pom 文件中添加spring-cloud-starter-eurekaserver 依賴.
(2)在SpringBoot 主類上添加@EnableEureka Server 注解.

(3)在application.properties 中配置端口號和注冊中心的地址,如下所示:



圖5 Eureka 服務頁面
Eureka Client 端實現如下:
(1)在基礎數據管理、資金交存、資金使用、查詢分析微服務以及Zuul 路由網關、Hy 斷路器等服務中的pom 文件中添加spring-cloud-starter-eureka-server依賴.
(2)在各自的啟動類上添加@EnableEurekaClient的注解.
(3)在各服務的application.properties 配置文件中添加如下配置:
eureka.client.serviceUrl.defaultZone=_blankhttp://lo calhost:9003/eureka/
之后依次啟動各微服務,在Eureka Server 頁面中可以查看各服務狀態,如圖6所示.

圖6 服務注冊到Eureka 狀態圖
各服務狀態為up 表明各服務已經成功注冊到Eureka Server 中了.
生產環境下,各個微服務有多個實例,將消費者的請求分攤到每一個實例中需要使用負載均衡機制.Ribbon 是一款可以控制HTTP 和TCP 行為的負載均衡器.Ribbon 可以基于負載均衡算法如輪詢算法、隨機算法等幫助服務消費者去請求服務提供者的地址[13].
Spring Cloud 中Feign 組件整合了Ribbon 和Eureka 來提供均衡負載的HTTP 客戶端實現.Feign 實現如下:
(1)在Pom 文件中添加添加spring-cloud-starterfeign 依賴.
(2)創建一個Feign 接口,并添加@FeignClient 注解.以下以查詢統計分析微服務為例:

其余微服務實現Fegin 接口與上面類似.
路由網關是為了讓所有的微服務對外只有一個接口API,我們只需要訪問一個網關地址,即可由路由網關將我們的請求代理到不同的服務中[14].如果沒有路由網關,多個服務提供給前端調用地址管理錯綜復雜,增加了客戶端的復雜性,認證也相對麻煩,每個服務都需要編寫相同的認證.
圖7和圖8分別展示了用戶請求多個微服務時使用和不使用路由網關的區別.
Spring Cloud 是通過Zuul 來實現路由網關的,Zuul 支持自動路由映射到Eureka Server 上注冊的服務.Spring Cloud 提供了注解@EnableZuulProxy 來啟動路由代理.
Zuul 組件具體實現代碼如下:
(1)pom 中添加spring-cloud-starter-zuul 依賴.
(2)在啟動類上添加注解@EnableZuulProxy,聲明一個Zuul 代理.該代理使用Ribbon 來定位注冊在Eureka Server 中的微服務[15].

(3)編寫配置文件application.yml


圖7 用戶請求多個微服務

圖8 使用路由網關
當服務消費者請求服務時,如果此時服務提供者響應時間過長,那么請求會被等待.高負載下,這種問題可能會導致系統崩潰[16].采用Hystrix 組件的容錯處理機制可以解決這一問題.具體實現代碼如下:
(1)在pom.xml 中添加spring-cloud-starter-hystrix依賴.
(2)在各服務啟動類添加注解@EnableHystrix,為項目啟用斷路器.

項目開發采用了前后端分離的形式,項目首先實現了后端接口功能,后端各服務接口開發完成后,需要先對接口進行測試,本項目中引入Swagger2 作為接口測試工具.
Swagger 2 是一個開源項目,用于描述和記錄RESTful API.Swagger 2 是語言無關的,可擴展到除HTTP 之外的新技術和協議.Swagger UI 允許其他API 開發人員或用戶與API 的資源交互,而沒有任何實現邏輯到位.應該結構化,使其具有信息性,簡潔性和易于閱讀.
Swagger 的實現如下:
(1)在pom 文件中添加springfox-swagger2 和springfox-swagger-ui 的依賴.
(2)創建Swagger2 配置類.
在Application.java 同級創建Swagger2 的配置類Swagger2

(3)在各服務API 中添加聲明.
以下以資金使用服務中的維修工程查詢接口為例,配置swagger 聲明:

運行各服務,訪問http://localhost:8080/swaggerui.html 頁面,如圖9所示,可以查看每個微服務的接口.

圖9 各服務接口
如圖10所示,點擊Expand Operations 按鈕可以展開每個接口的詳細信息,包括接口參數,提示代碼等.

圖10 維修工程查詢接口詳細
輸入好接口所需參數,點擊try it out 按鈕可以執行該接口方法,返回值如圖11所示.

圖11 維修工程查詢接口測試
本節以資金使用微服務為例,對資金使用環節部分功能進行測試.
維修申報列表頁面如圖12所示.由小區物業管理單位(或社區)進行維修工程申報,寫申請維修原因、申請維修費用、維修方案等信息.
工程申報之后可以選擇分攤戶進行分攤,分攤之后可以提交住建部門領導審核.維修工程提交之后由物管中心進行審核,主要對維修工程的維修內容、施工公司信息以及資金預算信息等進行審核.審核通過之后才可進行維修意見征詢流程.審核頁面如圖13.

圖12 維修工程申報

圖13 維修工程審核
維修工程經市物業管理中心審核通過后,由小區物管中心打印維修意見征詢表找與此維修工程申報相關的受益業主進行簽字確認.由小區物管單位根據受益業主簽字確認情況,在系統中確認已同意維修的受益業主.意見征詢頁面如圖14所示.

圖14 維修工程意見征詢
維修工程意見征詢通過后,項目便開始實施.當項目竣工后,施工單位組織工程驗收并填寫維修工程驗收表,經業主委員會、物業公司簽字確認.根據業主委員會、物業公司在維修工程驗收表中的簽字意見,在系統中進行維修驗收登記,界面如圖15所示.
維修工程驗收通過之后,維修公司選擇需要付款的結算單向市物業管業中心提交付款申請(分為首期款和尾款).資金撥付申請頁面如圖16所示.
本文使用Apache Bench 模擬100 個用戶對系統中不同業務同時發出訪問請求,在高并發請求訪問環境下,對微服務架構改進下的系統以及傳統的Java Web 架構下的兩種維修資金管理系統處理不同業務平均響應時間進行比較.記錄數據圖如表1所示.

圖15 維修工程驗收登記

圖16 資金撥付申請

表1 本系統與傳統住宅專項維修資金管理系統部分業務處理高并發訪問平均響應時間對比數據分析(單位:ms)
從表1中的對比可以看出,在模擬100 位用戶并發訪問的情況下,使用微服務架構的系統比傳統系統響應時間明顯下降,時間少了大約1/2,這說明在處理高并發業務時,采用微服務架開發的住宅專項維修資金管理系統性能明顯優于原系統,用戶體驗更加友好.
圖17展示了維修系統部分業務實例在高并發場景隨時間內存的消耗情況.上圖中橫軸表示時間,單位為秒,縱軸表示內存使用大小,單位為MB,上方紅色線條表示傳統系統測試實例的內存消耗總和,下方藍色線條表示基于微服務架構系統的測試實例的內存消耗總和.從圖中可以看出,在高并發場景下,基于微服務架構的系統內存消耗小于傳統單體式架構的內存消耗,并且內存使用相對平穩.
基于微服務架構的住宅專項維修資金管理系統采用了分布式架構,將系統整體功能拆分為各個服務,分別部署在不同的服務節點,可以有效避免因為單節點服務壓力過大引起系統宕機的風險.系統微服務框架搭建采用了基于Ribbon 的負載均衡組件,使得對于系統的高并發訪問請求進行分攤,實現系統的高可用、對網絡壓力有了緩解,解決了傳統系統內存壓力過大而導致系統資源加載過慢的情況,更好的提升了用戶的體驗.
本文設計并實現了基于微服務架構的住宅維修資金管理系統.相對于傳統的資金管理系統,本系統將功能劃分為基礎數據管理、維修資金交存、維修資金使用和查詢統計分析四項微服務.每個微服務可以單獨開發和部署,其中一個服務出現問題時,可以單獨修改不會影響到其他服務的使用,采微服務架構,系統處理高并發請求時,效率更高.本文采用了Spring Cloud 框架及其相關組件來搭建微服務架構,同時實現了服務注冊和發現、負載均衡、路由網關以及容錯處理機制.通過該服務框架可以對住宅維修資金管理系統進行快速開發,實現系統的組件化、獨立部署、維護風險降低等優勢.