后台开发技术--接入层设计
通常把跟客戶端直連的服務(wù)器稱為接入服務(wù)器,一個或多個接入服務(wù)器構(gòu)成的接入層。接入層有以下功能:
這里可以發(fā)現(xiàn),如果把接入層跟業(yè)務(wù)層合并也可以實現(xiàn)以上的功能,而且節(jié)省了實現(xiàn)功能2需要的工作量,根據(jù)簡單性原則,接入層不應(yīng)該被獨立出來。對于一個功能單一,用戶少,并發(fā)小的系統(tǒng),接入層的確沒有必要獨立出來。但對于一個復(fù)雜的系統(tǒng)來說,如果把也接入層和業(yè)務(wù)層合并勢必導(dǎo)致某一業(yè)務(wù)模塊的代碼代碼復(fù)雜,如下圖所示:
?
這是一個電商系統(tǒng)架構(gòu)的一部分,用戶模塊中合并了接入層。一般來說,后臺系統(tǒng)都有一個從簡單到復(fù)雜的演進(jìn)過程,在個過程中會經(jīng)歷多次版本迭代,每次都會有開發(fā)-測試-發(fā)布上線,每次發(fā)布上線都會重啟服務(wù)器。拿著里的用戶模塊來說,第一個版本一般很簡單,只有用戶注冊,登錄,查詢用戶信息這幾個功能,為了提升轉(zhuǎn)轉(zhuǎn)化率,很快就會加速未注冊用戶購物購物流程,就需要用模塊增加管理臨時用戶的功能。隨著用戶量增加,用戶模塊還需要設(shè)計成分布。這樣用戶模塊就需要經(jīng)常因為發(fā)布上線而重啟,重啟時就會因想用戶體驗,更嚴(yán)重的是如果用戶正在進(jìn)行像支付這樣的跟錢有關(guān)的操作時,很有可能造成直接的經(jīng)濟(jì)損失。同樣地,接入層的功能迭代是也會影響到新用戶注冊和老用戶登錄。如果把接入層獨立出來,則可以有效的減少這樣的故障。
?
功能越簡單,改動越少的服務(wù)器,越容易做得穩(wěn)定。相對于業(yè)務(wù)層模塊,接入服務(wù)器功能相對簡單很多,也很少有變化。也就是說,接入服務(wù)器比業(yè)務(wù)層模塊更容易做得穩(wěn)定。接入服務(wù)器是直接更用戶連接的,它直接影響用戶體驗。接入服務(wù)器故障或者是重啟肯定會影響到用戶,而其他業(yè)務(wù)模塊故障或者重啟則不一定會影響用戶體驗。從這一點上說,應(yīng)該盡量避免其他模塊對接入服務(wù)器的不良影響。
接入層獨立出來有下好處:
架構(gòu)設(shè)計的終極目標(biāo)是滿足業(yè)務(wù)需求,接入層設(shè)計也不能例外。設(shè)計接入層時需要搞清楚這樣幾個問題:網(wǎng)絡(luò)延遲有什么要求?并發(fā)有多大?但消息平均長度多少?用戶規(guī)模多少?用戶地域分布是什么情況?用戶的網(wǎng)絡(luò)環(huán)境怎樣?對這幾個問題有了清醒的認(rèn)識就能就能設(shè)計出恰到好處的接入層架構(gòu)。
接入層的架構(gòu)是隨著用戶量增加,流量增大,訪問并發(fā)增大由簡單到復(fù)雜演進(jìn)的,如下圖所示
1. 單個IP地址接入
?
2. 多個IP地址隨機(jī)接入
?
3. DNS根據(jù)用戶位置和用戶的網(wǎng)絡(luò)運(yùn)營商返回接入地址
?
?
4. DNS根據(jù)用戶位置和網(wǎng)絡(luò)運(yùn)營商返回二級引導(dǎo)服務(wù)器地址,二級引導(dǎo)服務(wù)器根據(jù)根據(jù)負(fù)載情況和業(yè)務(wù)需求返回接入地址
?以上四種架構(gòu)中,第1中可以用開源的DNS服務(wù)器bind架設(shè)。第2,3,4中架構(gòu)需要自己開發(fā)一個DNS服務(wù)器,這里面的關(guān)鍵是需要一個IP庫,這個IP中記錄了不同的IP地址段所屬的地理區(qū)域及運(yùn)營商。
?
客戶端狀態(tài)管理
管理客戶端的狀態(tài)是接入層的另一個主要自責(zé),當(dāng)客戶端連接到接入服務(wù)器后,這個連接會有不同的狀態(tài),如游客狀態(tài),登錄狀態(tài)等。對于不同類型的連接,管理狀態(tài)發(fā)方法也不一樣。一般來說,客戶端與服務(wù)器之間可以有兩種不同的連接類型:
1. 長連接。使用TCP協(xié)議,TCP連接建立成功后需要盡可能地保持,通過心跳保持連接,實現(xiàn)重連。一般用在客戶端需要被動接受數(shù)據(jù)的場景。
2. 端連接。TCP,UDP皆可,一個請求--返回為一次數(shù)據(jù)交換,完成之后如果是TCP會斷開連接。
消息識別
管理客戶端狀態(tài),第一步必須要識別客戶端的消息。假如有A,B兩個客戶端連接上了服務(wù)器,服務(wù)器收到了m1, m2兩個消息,處理這兩個消息需要建立如A->m1, B->m2這樣的對應(yīng)關(guān)系。現(xiàn)在的做法是使用session來識別消息,每個session都有一個的session ID, session ID由服務(wù)器生成,服務(wù)器要保證它的唯一性,客戶端與服務(wù)器器之間通訊過程中,每一條消息都要帶上這它。 session有過期時間,過期后需要重新建立session。
?
session存儲
session數(shù)據(jù)有一下幾個特點:
1. 單條數(shù)據(jù)量小, 每條session數(shù)據(jù)一般在256Byte以內(nèi)。
2. 數(shù)據(jù)總規(guī)模增加速度慢,每100w個session也就300MB左右。
3. 讀寫頻率高。相對于其他數(shù)據(jù)的來說,session的讀寫平率很有可能是最高的,因為每一條消息都會觸發(fā)至少一次的session讀-寫。
基于以上3個特點發(fā)現(xiàn),把session放在內(nèi)存中是最劃算的,占用內(nèi)存空間不大,讀寫速度快。假如session的過期時間是1天,系統(tǒng)的日活躍有100W用戶,存儲session所需要的空間是300MB,這個量級服務(wù)器表示很輕松。筆者這里推薦使用redis存儲session,既能滿足要求,又簡單。
?
用戶狀態(tài)管理
在一個系統(tǒng)中,用戶一般有兩種:匿名用戶和注冊用戶。
用戶進(jìn)入系統(tǒng)后沒登錄的就是匿名用戶,這個時候需要使用session來標(biāo)示用戶的臨時數(shù)據(jù)。例如一個電商網(wǎng)站,在用沒有登錄的情況下也可以往購物車?yán)锾砑由唐?#xff0c;此時購物車?yán)锏臄?shù)據(jù)就是臨時數(shù)據(jù),當(dāng)session過期后,這些數(shù)據(jù)會被刪除。
用戶進(jìn)入系統(tǒng)登錄后,此時這個用戶就是注冊用戶,每個注冊用戶都有一個唯一的用戶ID,通過這個用戶ID,把用戶和session綁定。這樣就可以通過session找到用戶ID,通過用戶ID找到用戶的私有數(shù)據(jù),進(jìn)而向用戶提供各種服務(wù)。有時候,還有通過用戶ID找到session, 這就要求在把用戶ID和session綁定的時候同時建立用戶ID到session的key-value關(guān)系。
?
消息轉(zhuǎn)發(fā)
如果有需要接入層還要負(fù)責(zé)消息轉(zhuǎn)發(fā),消息轉(zhuǎn)發(fā)有兩個過程:生成消息,推送消息。消息可以由用戶生成,如用戶的聊天消息;也可以有系統(tǒng)生成,如你在你在使用一個APP時收到的廣告。消息生成之后接下來就是要把消息推送給用戶,用戶能夠收到消息的前提條件是客戶端與服務(wù)器之間保持一個長連接。一條消息可以定向推送到特定的一個用戶,也可以推送到多個用戶,這兩種場景都很常見。成功地把一條消息推送給用戶,首先要確定消息需要推送給哪些用戶,然后再找出這些用戶與哪些接入服務(wù)器建立了長連接,然后把消息消息推送到相應(yīng)的接入服務(wù)器,剩下的就是接入服務(wù)器的事了。
接入服務(wù)器收到需要推送的消息后,會根據(jù)消息頭中目標(biāo)用戶ID找到session, 從session中取出長連接的socket文件描述符,發(fā)送消息。這樣做理論上沒問題,但實際上很容易出錯。在linux上,socket文件描述符是循環(huán)使用的。如果用戶A 的連接短開了,如果用A重連之前,用戶B建立了連接,這時用戶B的連接文件描述符與用戶先前用戶A的是同一個。這個時候試圖推送給A的消息會推送給B。這個文件的解決方案是每個連接建立的時候,給文件描述符生成一個在一個較長時間內(nèi)不會重復(fù)的流水號,使用這個流水號來查找文件描述符。
總結(jié)
以上是生活随笔為你收集整理的后台开发技术--接入层设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络:为什么会出现大量的time_wai
- 下一篇: 常见拒绝服务型攻击原理及行为特征