服務器端沾包處理的copy效率問題

本文說的基於數據包(有頭尾標示並且獨立被處理的數據區)的高效通信要求下,閱讀需要有一定的沾包處理經驗。沾包是tcp流傳輸的一個特點,形成沾包的主要原因是,數據包小於接收緩衝時,對方不斷髮生數據包,接受方連續接收數據放入接收緩衝導致的。

要想不產生沾包現像,可以採用一發一答方式,就是我發送一個數據包過去之後,對方應答了再發送下一個數據包;還有就是規定數據包頭2個字節(假定)代表數據包長度,每次先接收2個字節,然後根據這兩個字節的十六進制值去分配符合數據包大小的緩衝再去接收剩餘的數據。這兩種方式簡化了很多通信數據的處理過程,前者降低服務器負荷,後者增加了OS底層的CPU佔用率,兩者的效率一樣是相當地下的。和採用沾包處理算法的來說,效率根本不是底一個檔次這麼簡單。當然,如果你的系統對單個鏈接的效率沒有過多的要求話另當別論了。另外還有采用固定包(不夠長度的填充無效數據)的方式,每次接收緩衝就和固定包大小一致,但這個情況前提是你有足夠內存並且浪費帶寬。

綜上所述,也就是說在效率要求下“沾包處理”是不可避免的了。沾包處理根據服務器角色分有兩種情形,一種是網關服務器情形,另一種是邏輯服務器情形。網關服務器的特點是連接量大、單個連接流量小;邏輯服務器特點是連接量少、單個連接流量大。沾包處理需要從流緩衝中找到若干個數據包區域並copy到若干個獨立的緩衝中,交予主線程去處理,這個環節重要的工作是copy。假定單線程內存copy是1秒1GByte的效率,這個消耗還是不容忽視的。

單個連接的沾包處理必須有序處理才能保證數據不亂,因爲處理一個接收緩衝的時候會有殘包的問題,必須留下來和下一個接收緩衝進行合併才能處理提取數據包,也就是說要等前面的人處理完了才能告訴後面的人有沒有殘包,所以一般都是採用一個線程對一個連接進行沾包處理的工作。

對於網關服務器來說,N個連接就有多個線程來處理,這個似乎還是多線程範疇。對於邏輯服務器,一個網關一般只有一個連接,這個時候就變成了單線程模式了。在單個連接小流量通信情況下,網關服務器總體的copy消耗可能沒有太明顯的問題,但邏輯服務器因爲是單線程的模式,一個連接的流量等於一個網關服務器N個連接的流量總和,這麼大流量情況下因爲copy導致的效率問題就很明顯了(同樣在單個連接大流量的情況下,網關服務器也會有同樣的問題,只是相對對於當前的用戶帶寬來說這種可能性小一些罷了)。

那麼針對這個問題,假定採用多線程來進行單個連接的沾包處理工作可以進一步提高copy的效率的話,怎麼才能保證有序高效的處理呢?目前本人想到的方法如下:

                R1(SR1)                                          R2(SR2)

D1(L1)    D2(L2)     D3.2(L3)          D3.8    D4(L4)     D5(L5)

T1           T2             T3                                   T4             T5

Q1           Q2                                       Q3       Q4             Q5

R:接收緩衝,

SR:接收緩衝的大小

D:接收緩衝包含的數據包內容(假定每個數據包的頭兩個字節代表長度信息,其中R1包含D1,、D2和D3的20%內容,R2包含D3的80%內容、D4和D5)

L :數據包的長度

T:線程

Q:數據包入列的位置


一、線程T1先喚醒;

二、線程T1根據數據包D1的長度信息L1和SR1比較知道有下一個數據包;

三、線程T1喚醒線程T2並告訴它D2地址是D2=R1+L1,餘下緩衝大小是S2=SR1-L1;

四、線程T1進行效驗工作並把D1 Copy到隊列Q1位置(如果是解密的話,解密處理已經包含了效驗和Copy操作了);


五、線程T2根據數據包D2的長度信息L2和S2比較知道有下一個數據包;

六、線程T2喚醒線程T3並告訴它D3地址是D3=D2+L2,餘下緩衝大小是S3=S2-L2;

七、線程T2進行效驗工作並把D2 Copy到隊列Q2位置;


八、線程T3根據數據包D3的長度信息L3和S3比較知道是殘包,所以和R2合併得到D3=D3+R2,合併後緩衝大小是S3=S3+SR2;

九、線程T3根據數據包D3的長度信息L3和S3比較知道有下一個數據包;

十、線程T3喚醒線程T4並告訴它D4地址是D4=D3+L3,餘下緩衝大小是S4=S3-L3;

十一、線程T3進行效驗工作並把D3 Copy到隊列Q3位置;


十二、線程T4根據數據包D4的長度信息L4和S4比較知道有下一個數據包;

十三、線程T4喚醒線程T5並告訴它D5地址是D5=D4+L4,餘下緩衝大小是S5=S4-L4;

十四、線程T4進行效驗工作並把D4 Copy到隊列Q4位置;


十五、線程T5根據數據包D5的長度信息L5和S5比較知道是最後一個數據包了;

十六、線程T5進行效驗工作並把D5 Copy到隊列Q5位置;


十七、主線程依次對Q1~Q5進行有序處理


從上述步驟(四、七、十一、十四、十六)來說,線程T1~T5是可以並行處理效驗和Copy工作的。

(抽象了點,慢慢看就會體會理解)






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章