鑫財通iOS版前置socket連線架構升級優化設計

楊闖發表於2018-03-13

來到火幣,領導教育我要進行多方面的總結和分享,自己一直都是比較喜歡總結的人,但是我有一個問題,就是我語句表達不是很清晰,我所掌握的技術可能不是比較高深的,後來想了想,語言表達不清晰是可以鍛鍊的,掌握技術不是高深的,是給自己的一個記憶,也是給那些初入門者的一個思路。

我在聯通華建(曾經單獨成立鑫財通一年左右,現在公司名叫梧桐花開)的時候,親自參與討論設計實現了前置socket連線中使用者互動的升級體驗。

業務背景

前置交易服務系統指的是鑫財通部署在券商的交易服務程式和業務處理機程式,實現客戶端使用者券商賬戶相關的請求。客戶端每次登入都連線交易服務程式,當使用者發出請求的時候,客戶端向交易服務程式傳送資料請求或委託指令,交易服務程式將指令轉發到業務處理機程式,業務處理機程式將前置機轉發過來的資料解包,按照交易介面規範重新組包,把請求發給交易櫃檯,然後把櫃檯返回的結果發給交易服務程式,交易服務程式再將業務處理機返回的結果傳送給客戶端,網路連線結構如圖中紅框所示。

鑫財通網路連線服務結構圖

因此,以上的條件保證了交易業務的正常請求。在各種加密驗證的有效處理下,也保證了整個連線的安全性。

服務網路規則背景

 1、客戶端與交易服務程式之間的連線是長連線,業務處理機與券商交易櫃檯之間的連線雖然為socket連線,但是一次只進行一個業務的請求,可以當成短連線來看待。

2、在同一個客戶端和交易服務程式之間的連線中,如果同時發出兩個請求,業務處理機會建立兩個執行緒請求券商交易櫃檯,並且客戶端傳送請求和接收到的反饋資料都會有一個固定的時間戳,也就是客戶端能夠區分出來該資料返回對應的是哪次請求。

曾經iOS前置連線設計方案

由於iOS程式碼是由brew程式碼修改而來,做了一些簡單修改,形成設計如下:

層級名稱 | 類名 | 說明 - | :-: | -: 介面互動層 | LTDataInterface | 與介面進行互動,接收介面協議請求或反饋給介面請求資料結果 協議組裝層 | HJSTKNetWorkDataInterface | 組包、解包、驗證資料有效性以及獨有的祕鑰交換環節處理 資料連結層 | HJSTKStreamSocket | 呼叫系統介面進行資料的請求,包括返回連結錯誤等結果

資料連結層

此層處理的是純粹的socket資料的發包和收包。

協議組裝層發過來的資料在可以傳送資料的時候直接傳送給服務端,不管任何的協議規則。

對於接收到的資料按照協議組裝層的要求需要獲取到多少資料以及超時時間,只要沒有在固定時間內獲取到規定的資料長度,則認為超時,反饋給協議組裝層。因為socket的傳輸資料一般都是兩部分,第一部分的長度是固定的,其中就包含後邊資料的長度,但是由於此時的資料連結層只管接收不管資料的具體內容,一個資料的接收對於資料鏈路層來說就是兩組資料的返回,所對應的超時時間就要協議組裝層呼叫兩次,使得同一個請求有兩個互不關聯的超時處理。

存在問題: * 一次資料的返回要用兩個超時時間,設計上不符合一個資料整體的設計結構。 * 同一時刻只能處理一個任務,使得請求只能序列連線,介面層在請求一個業務時只能鎖屏處理。

協議組裝層

此層接收到介面互動層的請求處理後,按照協議進行組包。與此同時,該層控制著當重新建立一個連結,需要在業務請求前進行交換祕鑰,當獲取到交換祕鑰資料解析成功之後繼續進行後續的業務組包請求。

介面互動層

介面組裝層組要就是接收到介面發過來的請求把傳遞過來的資料和需要傳遞的資料傳送給協議組裝層。

##升級優化

考慮程式碼優化和使用者體驗,需要對程式碼進行優化升級,主要考慮以下幾個方面。

不鎖屏

因為以往執行前置請求時就要進行鎖屏處理,以防使用者操作出現同一時刻要兩個業務請求的處理情景,同時可以進行多個業務請求。

委託請求特殊處理

在不鎖屏的情況下,要特別注意的是委託業務的重要之處,因為一個股票在一秒鐘的時間內就可能會變化很大,因此要考慮如果有多個資料請求的情況下,要保證委託請求優先送達服務端。

擇優輪詢

一般每個券商都會有兩個前置服務,以防一個前置程式出現問題後不影響使用者的相關操作,該內容會另發文章進行描述。

現在設計

在新的前置請求框架結構中,自下而上仍然還是資料鏈路層、協議處理層和介面互動層三個層次,但是相對功能發生了很大的改變。

資料鏈路層:

資料鏈路層負責資料的傳遞、接收完整性驗證、超時管理等操作,完成前置請求資料的傳送和資料的接收,並將請求結果返回給協議處理層。

資料鏈路層將前置協議欄位結構和socket連結建立、資料傳送、資料接收結合到一起,每次請求資料和接受資料的完成都是一個前置請求協議的完整資料:在接受到傳送資料func sendData(data:Data)命令時,將請求資料全部轉換載入到待請求資料中,等待後續連結可以傳送數時傳送給服務端,將請求超時時間分別加入到超時陣列中。每當資料可以傳送的時候,只要本地存在待傳送資料就傳送,並將沒有傳送出去的資料繼續保留待下次傳送;在接收到資料時,根據協議格式,通過返回資料的前n個位元組判斷該資料請求該返回的資料長度,在獲取資料超過n位元組資料時立即根據n位元組資料內容判斷後續的內容長度m,當資料獲取長度達到一個完整返回包長度(長度等於n+m)時,直接通過閉包回撥的方式呼叫協議組裝層將整個協議請求資料全部傳遞過去,否則按照資料請求超時處理。

通過資料鏈路層與具體業務協議處理產生關聯,更加有效的進行超時管理,不是前n個位元組為一個超時標準,而是一整個請求資料的傳送到返回是一個超時時間來控制,與此同時也保證了每次的請求都是一個完整的,也為本設計中的同一時刻可能等待多條協議響應提供了基本前提。使得程式碼結構層次更加鮮明,並使得協議組裝層對請求資料與反饋資料的管理配對等程式碼編寫更加簡潔,增加程式碼的可讀性。

協議組裝層:

協議處理層主要呼叫資料鏈路層,決定著socket的連線和協議請求的傳送,同時也負責請求資料的組包、解包、請求佇列的管理,對交易請求擇優輪詢起著至關重要的作用。協議組裝層直接將請求結果返回到協議對應的具體介面,避免過多的邏輯傳遞。

協議組裝層主要控制著請求資料的佇列機制,控制一個待請求交易陣列,保證了佇列的有序控制。接收到協議請求時,如果網路斷開或者還沒有完成金鑰交換請求,則將請求放置待請求佇列中,並先完成建立連線和金鑰交換流程,等金鑰交換完成後,將所有待請求委託資料全部傳送給資料鏈路層,並保證委託資料之外的其它請求資料在上一個非委託資料請求結果回來之後再發下一個請求。而進行委託資料請求時,如果完成了交換祕鑰,則直接傳送給陣列鏈路層,不進行任何的陣列儲存。

當接收到鏈路層資料時,通過時間戳判斷該資料返回所對應的請求配置,進而反饋給介面。

介面互動層:

當介面控制器要進行資料請求時,將請求資料以及block回撥內容傳遞給介面互動層相關方法,介面互動層再按照規則將傳遞過來的資料和當前券商賬戶相關基本資料組裝成QzModel物件,並根據請求協議號的判斷對委託等請求給予委託特別標識賦值cmd.isFirstExch 使得協議請求在協議組裝層有特殊通道,然後呼叫協議組裝層的send方法使得協議組裝層繼續後面的處理。

介面互動層直接為介面提供介面,接收頁面請求命令,根據業務請求整理出需要傳遞給服務端的相關資料model,並傳遞給協議處理層,不進行任何結果的反饋。同時也控制賬戶的切換,對外提供當前賬戶相關登入資料的查詢功能。

相關文章