◆何金獅
(福建富士通信息軟件有限公司 福建 350003)
一種基于epoll模型的高效代理服務(wù)架構(gòu)
◆何金獅
(福建富士通信息軟件有限公司 福建 350003)
本文通過對epoll模型的靈活運用,結(jié)合多線程多隊列模式,對socket描述符進行合理分配,介紹了一種高效的代理服務(wù)框架。
數(shù)據(jù)轉(zhuǎn)發(fā);代理服務(wù);epoll
代理服務(wù)被用于數(shù)據(jù)轉(zhuǎn)發(fā),需要同時管理客戶端和服務(wù)器連接,并且能夠準確的將一端的數(shù)據(jù)轉(zhuǎn)發(fā)到對應(yīng)的另一端,在連接數(shù)大的情況下對性能和穩(wěn)定性都是一個非常大的考驗。因此一個高效的代理服務(wù)框架顯得非常重要。
epoll是Linux內(nèi)核為處理大批量文件描述符而作了改進的poll,是Linux下多路復(fù)用IO接口select/poll的增強版本,它能顯著提高程序在大量并發(fā)連接中只有少量活躍的情況下的系統(tǒng)CPU利用率。另一原因就是獲取事件的時候,它無須遍歷整個被偵聽的描述符集,只要遍歷那些被內(nèi)核IO事件異步喚醒而加入準備隊列的描述符集合就行了。epoll除了提供select/poll那種IO事件的水平觸發(fā)(Level Triggered)外,還提供了邊緣觸發(fā)(Edge Triggered),這就使得用戶空間程序有可能緩存IO狀態(tài),減少系統(tǒng)調(diào)用,提高應(yīng)用程序效率。
代理服務(wù)的主要功能是將一個網(wǎng)絡(luò)終端的數(shù)據(jù)轉(zhuǎn)發(fā)到另一個網(wǎng)絡(luò)終端,兩端設(shè)備不需要在同一個局域網(wǎng)內(nèi),只要網(wǎng)絡(luò)可達即可。一個完整的代理服務(wù)過程分為,客戶端與代理服務(wù)器建立連接,代理服務(wù)器根據(jù)自定義的代理協(xié)議與目標服務(wù)器創(chuàng)建連接,客戶端與服務(wù)端通訊的所有數(shù)據(jù)都由代理服務(wù)器來轉(zhuǎn)發(fā)。常見的代理服務(wù)有HTTP代理和Socks代理。
圖1 網(wǎng)絡(luò)拓撲
架構(gòu)設(shè)計的思想是主進程根據(jù)系統(tǒng)的cpu核心數(shù)創(chuàng)建對應(yīng)數(shù)量的線程,并且為每個線程創(chuàng)建一個隊列。主進程負責(zé)監(jiān)聽新的連接請求,一旦有新的請求進來,主進程會遍歷所有的隊列將新的請求的socket描述符以及相關(guān)信息放入數(shù)量最小的隊列中。子線程實時掃描隊列發(fā)現(xiàn)有新的請求就將請求從隊列中移除并且放入線程內(nèi)部的epoll隊列中,子線程負責(zé)管理這些連接的數(shù)據(jù)收發(fā)。
子線程從對應(yīng)的隊列中獲取新連接,創(chuàng)建客戶端結(jié)構(gòu)體一同放入本線程創(chuàng)建的epoll隊列中。子線程進行epoll_wait等待事件觸發(fā),如果事件類型是EPOLLIN讀事件同時是客戶端并且首次觸發(fā),根據(jù)連接信息獲取客戶端要連接的服務(wù)器信息。子線程創(chuàng)建與服務(wù)端的連接,同時創(chuàng)建服務(wù)器結(jié)構(gòu)體,并且客戶端和服務(wù)端的結(jié)構(gòu)體中分別存放對方的信息,這樣當接收到任何一端的數(shù)據(jù)時都可以快速找到對端的連接。
圖2 主進程流程
圖3 線程流程
將客戶端的連接通過獨立的隊列均衡負載到不同的線程中,由每個獨立的線程分別建立epoll監(jiān)聽極大的提高了數(shù)據(jù)處理能力。通過在同一種結(jié)構(gòu)體中用字段表示連接是屬于客戶端還是服務(wù)端的方式,在epoll中可以同時對客戶端和服務(wù)端連接進行管理使得架構(gòu)更加靈活高效。
[1]宋敬彬,孫海濱.Linux網(wǎng)絡(luò)編程.清華大學(xué)出版社,2010.
[2]https://banu.com/blog/2/how-to-use-epoll-a-complet --example-in-c/.