唐煜舟



摘要:該文分析了現有微信公眾號平臺存在的問題,對如何優化現有微信公眾號平臺以便支持千萬級用戶訪問量的總體需求進行了分析,介紹了系統架構調整的原因以及如何調整,具體的調整內容以及如何實現。
關鍵詞:微信公眾平臺;異步;隊列;緩存
中圖分類號:TP311 ? ? ? ?文獻標識碼:A
文章編號:1009-3044(2019)15-0096-04
1 概述
J銀行信用卡中心微信服務號自2014年1月正式上線以來,累計關注用戶數已突破2000萬,綁卡用戶數已突破1700萬。微信服務號已經成為卡中心電子渠道中最為活躍、最為重要的一個部分,同時也成為卡中心市場推廣、營銷的最重要的手段之一。
預計2019年底J銀行信用卡中心微信服務號關注用戶數將突破3000萬,對微信公眾號平臺自身的容量及可用性提出了更高的要求。卡中心微信服務號定時全量客戶群發也會對卡中心各個系統造成沖擊。
本文分析了為達到業務目標現有微信公眾號平臺存在的問題,對如何支撐業務目標改造現有微信公眾平臺的總體需求進行了分析,探討了如何優化J銀行卡中心現有微信公眾號平臺的系統架構并重構部分功能以支持千萬級用戶量的微信公眾號平臺。
2 總體需求分析
為滿足2019年底微信服務號關注用戶數達到3000萬的業務目標,微信公眾平臺亟須解決問題如下:
1) 騰訊與微信公眾號平臺對接的網絡不穩定
騰訊通過J銀行總行payment域名與卡中心微信公眾號平臺對接,網絡鏈路長、故障點多,已多次發生由于線路故障導致交易中斷的情況。
2) 業務高峰期系統響應慢
在用戶賬單日或者J銀行信用卡開展大型活動期間,瞬間用戶訪問量超過微信公眾號平臺、后端業務系統容量上限時,會造成響應緩慢甚至無響應情況。同時,騰訊在大量請求無回復后會重復發起請求,用戶也會在系統無響應后重復點擊微信公眾號菜單,導致情況進一步惡化。
3) 下發模板消息無流量控制
后端業務系統對接微信公眾號平臺發送模板消息,如訪問騰訊服務器的線路故障,將導致請求積壓,影響微信公眾號平臺、后端業務系統的并行處理能力,甚至導致系統宕機。大量的下發模板消息也容易引導用戶訪問J銀行卡中心諸如官網、App、商城等其他對外系統,造成對其他系統沖擊,引發其他系統宕機。
為解決上述問題,微信公眾號平臺亟須優化現有架構,以便系統容量能夠滿足日益增長的業務目標。
3 系統架構設計
用戶關注J銀行信用卡中心微信公眾號,在3*5菜單或者對話框中輸入問題,點擊發送后至騰訊,騰訊將用戶的請求發送至J銀行總行payment域名。J銀行總行payment域名將消息轉發至微信公眾號平臺,Proxy軟負載服務器收到請求后,將請求隨機分發至多臺Robot服務器中的某一臺,Robot服務器調用平臺的AI引擎獲取后續操作指令后調用后端業務系統返回處理結果。
后端業務系統也可以通過調用微信公眾號平臺的下發/群發服務器,將營銷內容、交易提醒等實時模板消息發送至騰訊,騰訊將實時模板消息推送至用戶的微信號上。
現有系統架構如圖1。
上述架構存在消息接入鏈路長、每筆消息同步回復容易對后端系統造成沖擊、系統響應慢導致用戶重復請求以及實時模板下發無法實現流控等等弊端。現有微信公眾號平臺架構已無法滿足2019年底微信服務號用戶數達到3000萬的業務目標,更無法適應互聯網用戶無規律、大并發、脈沖式的訪問。故本文引入專線接入、異步回復、隊列機制、緩存機制、重復請求甄別機制、實時模板下發流控等機制,對系統架構進行調整。
調整后系統架構如圖2。
4 具體調整內容
4.1 專線接入
目前騰訊平臺發送微信公眾號平臺的報文需通過J銀行總行payment域名及總行DMZ、卡中心辦公網轉發。卡中心主動訪問騰訊服務器有2條線路,一條是通過卡中心DMZ的外網出口(備用線路),一條是通過電信的專線出口(主用線路)。
現有接入方式如圖3。
現有平臺與騰訊服務器的接入方式存在線路環節較多、延時較大、出故障概率高、問題排查較復雜等問題。為解決上述問題,改進機制如下:
1) 通過電信、鐵通專線直連騰訊機房,跳過中間環節,減少故障概率。
2) 平臺入口由電信、鐵通專線在物理層面形成主備,同時保留卡中心DMZ出口,將騰訊服務器的地址作為基礎參數,快速實現出口網絡(專線、互聯網)環境切換。
調整后采用專線接入方式如圖4。
4.2 異步回復
目前微信公眾號平臺所接收到的服務請求會通過平臺自有的Proxy軟負載服務器平均分配至3臺Robot服務器,如果后端業務系統響應超過4s則回復空串。
未采用異步回復方式如圖5。
4S等待時間并無太大意義,一旦超時,對于用戶請求來說相當于浪費了4S。同時,由于延遲響應,將堆積后續服務請求,對系統造成更大的壓力。為解決上述問題,改進機制如下:
1) Proxy軟負載服務器將請求放入隊列服務器后即返回空串,具體實現如下:
//返回騰訊空字符串內容
String con = "success";
//直接在IO中返回將空字符串內容返回騰訊
out.write(con);
// 將請求放入隊列服務器
executor.execute(new Runnable() {
public void run() {
KafkaUntils.push(topic_req, openid, reqxml);
}
});
2) 由后端Robot服務器從隊列服務器中獲取請求并處理用戶的請求后異步返回結果,具體實現如下:
channel.send(return.get(resp));
調整后采用異步回復方式如圖6。
4.3 隊列機制
微信公眾號平臺在接收到用戶同時大量并發請求后直接發送至后端,在超出后端處理能力的情況下,將導致對后端資源的爭搶,后端處理響應將變慢,交易耗時增加。
未采用隊列的方式如圖7。
采用隊列后,微信公眾號平臺將以后端能夠承受的速度發送請求。假設1筆交易平均耗時0.25s(平均5個接口*50ms=0.25s),在后端系統不擴容、響應不變的前提下,如果交易量增加1倍,則原有用戶交易不受影響,新增一半用戶交易時長增加0.25s,但預計可抵消由于交易量激增導致的后端響應緩慢問題。
采用隊列后的效果如圖8。
采用消息隊列技術,所有的用戶請求都先進入到隊列服務器中,程序保持先進先出的原則順序讀取隊列并對所有用戶的請求進行處理。Proxy服務器根據算法將不同用戶的消息放置入不同隊列中,不同Robot服務器從不同隊列中獲取消息。Proxy服務器監控隊列深度,一旦發現某隊列深度超過最大值,則判為Robot服務器故障,改變分發策略。同時,隊列深度超過一定閾值還會觸發告警,以便運維人員及時了解Robot服務器、后端業務系統是否存在故障。
Robot服務器以指定的速度(考慮后端業務系統處理能力)從隊列服務器中獲取消息后送后端業務系統處理。Robot服務器將返回消息放入隊列服務器,由Proxy服務器以最快速度發送騰訊。
隊列機制具體實現如下:
Map
List
//從隊列中獲取數據以指定頻率發送后端業務系統處理
if(topic.equals(PropertiesUtil.getValueByKey("topic"))){
ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(a_numThreads));
for (final KafkaStream stream : streams) {
executor.submit(new KafkaMasssendThread(stream));
}
}
隊列方式的技術實現如圖9。
4.4 緩存機制
在業務處理的過程中,引入Redis緩存讀取機制,即在處理請求前查看是否存在可用的緩存內容并加以使用,以及在完成業務處理后將結果保存到緩存中以供重復使用。
緩存設計在以下幾個場景中使用:
1) 對騰訊端內容的緩存:緩存請求響應報文中的Token供系統生成報文時使用,具體實現如下:
URLConnection conn = new URL(tokenUrl).openConnection();
ByteArrayOutputStream ?bytesOut =
new ByteArrayOutputStream();
accessToken = new String(bytesOut.toByteArray(), "UTF-8");
2) 對綁定關系的緩存:緩存用戶微信openid與用戶賬戶usrid的綁定關系、用戶下掛卡關系,具體實現如下:
Object[] bindinfo = bindService.isBind(openid, nickname);
3) 對每個用戶操作行為緩存:供對重復請求判斷時使用,具體實現如下:
boolean isRepeat = RedisService.isRepeat(openid, action);
緩存機制技術實現如圖10。
4.5 重復請求甄別機制
Proxy服務器每次接收請求后從Redis緩存服務器中獲取用戶操作行為,對用戶在短時間內重復請求的甄別,按照一定規則(例如10s內同類型重復請求)排除重復請求防止對系統資源的浪費:
1) 如果為重復請求,將重復請求放入重復請求的隊列中,由存儲服務器記錄供相關維護人員查看。
2) 如果不為重復請求,則緩存用戶請求后將用戶請求放入隊列中供Robot服務器處理。
3) 對于短時間內來源于同一用戶的大量重復請求做出預警,有相關人員來判斷是否屬于惡意攻擊。
重復請求甄別機制具體實現如下:
boolean isRepeat = RedisService.isRepeat(openid, action);
if(isRepeat){
//重復請求放入相應隊列供業務人員、運維人員分析
KafkaUntils.push(topic_req, openid, reqxml);
}else{
//正常請求由Robot服務器處理
int result = this.proxyClient.executeMethod(post);
}
重復請求甄別機制技術實現如圖11。
4.6 實時模板下發流控
現有微信公眾號平臺的下發/群發模塊在收到后端系統的下發請求后直接將下發請求發送至騰訊服務器。如騰訊服務器響應超時,將影響使用下發接口的后端業務系統。同時,平臺直接接收后端系統的下發請求并實時發送,無法對下發的模板實現并發數等流量控制。
調整前實時模板下發方式如圖12。
改造后,微信公眾號平臺下發/群發服務器在收到下發請求后將消息寫入隊列服務器并立刻返回后端系統,Proxy服務器從隊列服務器中獲取下發請求后發送騰訊。
實時模板下發流控具體實現如下:
//流控隊列線程池處理
ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(b_numThreads));
for (final KafkaStream stream : streams) {
executor.submit(new KafkaMasssendThread(stream));
}
}
調整后實時模板下發方式如圖13。
4.7 實時模板消息回執處理
微信公眾號平臺在實時模板消息發送后對消息的發送回執進行判斷:對于未發送成功的消息回執進行存儲,并生成相應報表,后期可通過人工干預的方式進行處理。
消息回執中包含以下有用內容:用戶openID、所發消息messageID、發送是否成功標示、發送失敗原因標示(用戶屏蔽、其他原因)。
具體實現如下:
//模板消息回執放置入隊列稍后處理
if event.equals("TEMPLATESENDJOBFINISH") {
executor.execute(new Runnable() {
public void run() {
KafkaUntils.push(topic_templatesend, openid, reqxml);
}
});
}
實時模板消息回執處理實現方式如圖14。
5 結束語
通過引入專線接入、異步回復機制、隊列機制、緩存機制、重復請求甄別機制、實時模板下發流控等機制后,J銀行卡中心微信公眾號平臺系統容量、可靠性、穩定性獲得了極大的提升。
平臺架構調整后,微信公眾號平臺性能、容量可滿足2019年底J銀行卡中心微信服務號關注用戶數達到3000萬的業務目標,J銀行卡中心微信公眾號更是獲得了信用卡行業關注用戶數、品牌影響力、美譽度等綜合排名僅次于行業標桿招行信用卡的微信公眾號。
【通聯編輯:代影】