韓立峰, 亓雪冬
(中國石油大學(華東) 信息化建設處, 山東 青島 266580)
目前,高校普遍建設了校園一卡通系統(tǒng),它集成了身份認證和電子支付的功能,師生在餐廳等消費場所通過刷卡,就可使用個人賬戶資金進行支付。隨著互聯(lián)網(wǎng)應用的普及,為了支撐校園一卡通的互聯(lián)網(wǎng)應用,我校建設了校園一卡通開放平臺[1]。平臺提供了一系列有關一卡通查詢、轉(zhuǎn)賬、支付功能的Rest API,第三方應用系統(tǒng)通過調(diào)用這些接口,就可將一卡通認證和支付功能嵌入到自己的系統(tǒng)或業(yè)務流程里。
當前,網(wǎng)上預訂和網(wǎng)上支付逐漸成為師生的行為喜好。建設網(wǎng)上訂餐系統(tǒng),師生可提前獲知當日餐品供應并根據(jù)個人口味預訂;餐廳銷售方可根據(jù)預訂情況合理安排餐品供應。同時在后疫情時代,線上自主預訂、線下分散取餐,可有效減少人員現(xiàn)場聚集,避免交叉?zhèn)魅尽?/p>
因此我們設計了基于微服務架構(gòu)的網(wǎng)上訂餐系統(tǒng),系統(tǒng)將用戶認證、預訂、支付等功能抽取為相互獨立的微服務,供前端PC、手機、自助點餐機等客戶端調(diào)用,同時系統(tǒng)以校園一卡通開放平臺為基礎,通過調(diào)用平臺接口,實現(xiàn)基于一卡通的身份認證和網(wǎng)上支付功能。
隨著互聯(lián)網(wǎng)應用規(guī)模的不斷擴大,傳統(tǒng)的垂直應用架構(gòu)已經(jīng)無法應對。微服務架構(gòu)[2-3]是一種新興的互聯(lián)網(wǎng)應用架構(gòu),它將單一應用程序劃分成一組小的服務,每個服務運行在其獨立的進程中,服務之間通訊采用輕量級的通訊協(xié)議。微服務架構(gòu)可以根據(jù)應用的需求,動態(tài)擴充服務資源,具有很強的伸縮性。
微服務架構(gòu)帶來了服務治理的問題,面對數(shù)量龐大的服務,如何實現(xiàn)服務的動態(tài)注冊和發(fā)現(xiàn),明確服務間的依賴關系,合理調(diào)整服務的容量,Dubbo解決了以上問題。Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調(diào)用、智能容錯和負載均衡、以及服務自動注冊和發(fā)現(xiàn)[4]。Dubbo框架對系統(tǒng)各種服務的運行過程進行管理,管理架構(gòu)如圖1所示。
圖1 Dubbo服務管理架構(gòu)
圖中共有5個角色,各角色之間調(diào)用關系為:服務提供者在注冊中心注冊其提供的服務;服務消費者從注冊中心訂閱自己的服務;服務容器負責啟動運行服務進程;監(jiān)控中心負責統(tǒng)計服務調(diào)用的次數(shù)和時間。
網(wǎng)上訂餐系統(tǒng)的整體設計分為三層架構(gòu),其設計思想為:最底層是數(shù)據(jù)訪問層,數(shù)據(jù)訪問層作為服務支撐的基礎保障,由一卡通開放平臺提供功能支持;中間層是業(yè)務層,里面對業(yè)務模塊進行細化和拆分,將系統(tǒng)用戶所需的功能抽取成多個微服務,微服務向下調(diào)用基礎服務層一卡通開放平臺的API,向上對用戶訪問層提供微服務接口;用戶訪問層包括PC、手機、自助機等各種類型終端調(diào)用微服務接口,實現(xiàn)相應用戶功能,系統(tǒng)架構(gòu)如圖2所示。
圖2 網(wǎng)上訂餐系統(tǒng)架構(gòu)
本文重點說明業(yè)務微服務層設計,訂餐系統(tǒng)業(yè)務非常明確,將其拆分成5個子服務,分別是餐品發(fā)布服務、餐品查詢服務、餐品預訂服務、用戶支付服務和商戶結(jié)算服務。每個子服務都是獨立的功能設計單元,其代碼實現(xiàn)不同但技術架構(gòu)相似。以支付微服務為例,支付微服務首先構(gòu)建好實現(xiàn)代碼,然后將其部署到服務器上運行,這里可根據(jù)實際訪問量來進行服務器數(shù)量的選擇。初期可以先搭建一臺服務器,然后通過ZooKeeper對服務模塊的提供方進行注冊,此時一個靈活的、可監(jiān)控、可管理的子業(yè)務就初步完成了。后期隨著業(yè)務量上升,可以復制原有的代碼,完成新服務器的部署搭建,只需將新的服務提供者注冊到ZooKeeper中,就形成了一個最輕量的負載集群。由于系統(tǒng)采用Dubbo的服務治理框架,隨著數(shù)據(jù)量和訪問量的上升,Dubbo可以使用權(quán)重算法分析負載,動態(tài)調(diào)配系統(tǒng)資源。另外非常重要一點是對服務進行管理和監(jiān)控,它可以保證系統(tǒng)長時間的在各種復雜的情況下正常運行。
用戶通過網(wǎng)頁、微信、App等方式,首先對菜品進行瀏覽,在選擇好需要的菜品后,進行支付,最后系統(tǒng)自動根據(jù)對每日支付的訂單為商戶進行結(jié)算,如圖3所示。
圖3 訂餐業(yè)務流程
如本文前面所述,訂餐業(yè)務劃分成很多子服務,任何一個子服務都是可供其他程序獨立調(diào)用的,在前置條件充足的情況下子服務之間完全解耦,這是本系統(tǒng)設計的核心思想,也旨在建立起一個健壯而又可擴展的現(xiàn)代化網(wǎng)絡應用系統(tǒng)。本文以支付微服務為例,闡述采用Dubbo框架對子服務進行管理,同時采用微服務的設計思想,由服務提供者創(chuàng)建微服務、由ZooKeeper注冊微服務,并通過服務消費者調(diào)用微服務的設計理念。
網(wǎng)上訂餐系統(tǒng)作為服務提供者創(chuàng)建支付微服務,首先需要定義服務接口,繼而實現(xiàn)服務接口。這里筆者創(chuàng)建了支付微服務PayService,提供線上支付扣款功能。
(1) 服務端定義支付微服務接口
public interface PayService {
int Pay(String account, double tranamt, string meraccc, string order_no);
}
Pay方法中,參數(shù)account表示學工號;tranamt表示扣款金額;meraccc表示商戶號;order_no表示訂單號;返回值為0表示支付成功,非0表示支付失敗。
(2) 服務端實現(xiàn)支付微服務接口
public class PayServiceImpl implements PayService {
int Pay(String account, double tranamt, string meraccc, string order_no) {
String jsonStr = JSONObject.toJSONString(inJsonObject);
HttpClient httpClient = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofString(jsonStr))
.uri(URI.create("https://一卡通開放平臺IP/…/card_pay"))
.build();
int retcode=Integer.parseInt(outJsonObject.getString("retcode"));
return retcode;
}
}
接口PayService的Pay方法在實現(xiàn)時需調(diào)用基礎服務層一卡通開放平臺的支付接口card_pay,實現(xiàn)基于一卡通賬戶的支付,接口地址https://一卡通開放平臺IP/…/card_pay,數(shù)據(jù)交換格式為JSON,請求方法HTTPS POST,一卡通開放平臺執(zhí)行完扣費操作后,返回JSON格式的處理結(jié)果,retcode和errmsg分別表示返回碼和錯誤信息,返回值0表示扣費成功,否則表示扣費失敗,調(diào)用過程如圖4所示。
圖4 一卡通開放平臺支付接口調(diào)用
(3) 聲明暴露支付微服務
配置provider.xml文件,在網(wǎng)絡中暴露支付微服務:
interface="com.hanlifeng.Dubbo.provider.service.PayService" ref="payService"/> (4) 服務消費者調(diào)用支付微服務 用戶使用PC、手機等客戶端與訂餐系統(tǒng)發(fā)生交互,調(diào)用支付微服務,客戶端程序首先根據(jù)消費者配置文件consumer.xml建立應用上下文context,然后通過context.getBean()語句獲取遠程支付微服務的代理對象payService。接下來代理對象的GetOrderInfo方法獲取掃描訂單二維碼得到的訂餐信息,包括學工號、訂餐金額、商戶號、訂單編號等。最后調(diào)用支付微服務payService的Pay方法完成支付。 根據(jù)訂餐系統(tǒng)架構(gòu),實際部署方案為:1.前端部署2臺Nginx用于應用反向代理,服務器配置成主從模式,單臺Nginx并發(fā)數(shù)可達3萬,足以滿足學校高峰時使用。2.部署1臺ZooKeeper服務器用于服務的注冊,保存服務列表地址。3.部署1臺RabbitMQ[5]服務器,消息隊列主要負責處理高峰時段訂單的下發(fā),將其排隊并按序推送給支付微服務網(wǎng)關,從而實現(xiàn)高峰時段對集中請求分發(fā)的處理要求。4.部署1臺 Redis服務器和1臺MySQL服務器,高峰訂餐時段菜品的查詢會非常頻繁,如果采用通過關系型數(shù)據(jù)庫直接查詢,可能會導致數(shù)據(jù)查詢緩慢。系統(tǒng)采用在餐品發(fā)布完成后,記錄到MySQL數(shù)據(jù)庫的同時,在Redis內(nèi)存中也生成一個餐品的數(shù)據(jù)高速緩存,高峰期所有的查詢都是直接通過內(nèi)存中的高速緩存來進行查詢,這樣可以保證查詢速度在毫秒級別,滿足師生在訂餐時段的用戶體驗。5.部署2臺微服務業(yè)務的服務器,將微服務Java源文件進行編譯,并打包成mealOrdering.jar分別拷貝到兩臺服務器的tomcat / webapps目錄下,啟動tomcat即可,程序會把微服務的節(jié)點(各個子服務提供者)注冊到ZooKeeper服務器的樹狀節(jié)點中,此時服務消費端可以通過ZooKeeper服務器的樹狀列表找到自己需要的服務,從而實現(xiàn)分布式微服務的功能。 網(wǎng)上訂餐系統(tǒng)采用微服務架構(gòu)設置,在業(yè)務層將餐品預訂、支付、商戶結(jié)算等功能抽取拆分形成一個個微小的子服務,借助校園一卡通開放平臺和數(shù)據(jù)平臺提供的基礎用戶認證和支付能力,同時利用Dubbo框架對系統(tǒng)子服務進行治理,有效解決了微服務的注冊、調(diào)用、監(jiān)控、追溯以及高低峰負載均衡等設計問題,使系統(tǒng)具有很高的并發(fā)處理能力和伸縮擴展性,可以有效應對校園師生在訂餐中大規(guī)模使用的場景。5 系統(tǒng)部署方案
6 總結(jié)