摘要:基本原理函數監視的文件描述符分類,分別是和。具體模型如下與模式相比,在完成數據讀取之后,將業務處理過程交由一個線程池來完成,主線程直接返回進行下一次循環操作,效率大大提升。是提供的最高效的網絡模型。
I/O多路復用
IO多路復用就是通過一種機制,一個進程可以監聽多個文件描述符,一個某個描述符就緒(一般是讀就緒或寫就緒),就能夠通知程序進行相應的讀寫操作。select、poll、epoll本質上都是同步IO,因為他們需要在讀寫事件就緒后自己負責讀寫,即這個讀寫過程是阻塞的,而異步IO則無需自己負責讀寫,異步IO的實現會把數據從內核拷貝到用戶空間。
select 基本原理select 函數監視的文件描述符分3類,分別是writefds、readfds、和exceptfds。調用后select函數會阻塞,直到有描述符就緒(有數據 可讀、可寫、或者有except),或者超時(timeout指定等待時間,如果立即返回設為null即可),函數返回。當select函數返回后,可以通過遍歷fdset,來找到就緒的描述符。
select的缺點單進程所能打開的文件描述符有一定限制,32位機默認1028,64位機默認2048。
對socket進程掃描時是線性掃描,效率很低。
用來存放文件描述符的數據結構,在用戶空間和內核空間的復制開銷極大。
pollpoll與select類似,略過。
epollepoll是在linux 2.6內核中提出的,是select和poll的增強版本。
基本原理epoll支持水平觸發和邊緣觸發,最大的特點在于邊緣觸發,它只告訴進程哪些fd剛剛變為就緒態,并且只會通知一次。還有一個特點是,epoll使用“事件”的就緒通知方式,一旦該fd就緒,內核就會采用類似callback的回調機制來激活該fd。
epoll的優點沒有最大連接數的限制,1G內存約能監聽10W個端口。
不采用輪詢的方式,不會隨著FD數目的增加效率下降。只有活躍可用的FD才會回調。
內存拷貝,epoll使用mmap減少復制開銷。(注:mmap本質就是繞過從網卡、磁盤拷貝數據到內核再拷貝到用戶空間的方式,直接從網卡拷貝數據到用戶空間,性能爆炸。)
Thrift網絡服務模型thrift提供的網絡服務模型有阻塞服務模型、非阻塞服務模型:
阻塞服務模型:TSimpleServer、TThreadPoolServer
非阻塞服務模型:TNonblockingServer、THsHaServer和TThreadedSelectorServer
TSimpleServer該模式采用最簡單的阻塞IO,一次只能接收并處理一個socket,處理流程如下:
此種模式效率低下,生產不會使用,略過。
TThreadPoolServer模式采用阻塞socket方式工作,主線程負責阻塞式(劃重點,不是select的方式)監聽是否有新socket到來,具體的業務處理交由一個線程池來處理。
accept部分的代碼如下:
protected TSocket acceptImpl() throws TTransportException { if (serverSocket_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); } try { // 阻塞式監聽新的連接 Socket result = serverSocket_.accept(); TSocket result2 = new TSocket(result); result2.setTimeout(clientTimeout_); return result2; } catch (IOException iox) { throw new TTransportException(iox); } }
具體模型如下:
TThreadPoolServer本質是One Thread Per Connection模型。模型受限于線程池的最大線程數,在連接數很大話,請求只能排隊,對于高并發的場景,此模型并不合適。
TNonblockingServerTNonblockingServer模式也是單線程工作,但是采用NIO的模式,借助Channel/Selector機制, 采用IO事件模型來處理。本質是一種event-loop模型。
具體模型如下:
event-loop的核心代碼如下:
private void select() { try { // 等待事件,jdk7之前的版本存在問題,會存在會將CPU打滿的情況,沒有事件,select卻返回,從而將CPU打滿;Netty中通過threshold,解決了該問題 selector.select(); // 獲取IO事件 IteratorselectedKeys = selector.selectedKeys().iterator(); while (!stopped_ && selectedKeys.hasNext()) { SelectionKey key = selectedKeys.next(); selectedKeys.remove(); // skip if not valid if (!key.isValid()) { cleanupSelectionKey(key); continue; } // if the key is marked Accept, then it has to be the server // transport. // 處理連接事件 if (key.isAcceptable()) { handleAccept(); } else if (key.isReadable()) { // deal with reads // 處理讀事件 handleRead(key); } else if (key.isWritable()) { // deal with writes // 處理寫事件 handleWrite(key); } else { LOGGER.warn("Unexpected state in select! " + key.interestOps()); } } } catch (IOException e) { LOGGER.warn("Got an IOException while selecting!", e); } }
這個模型一般由一個event dispatcher等待各類事件,待事件發生后原地調用對應的event handler,全部調用完后等待更多事件,故為"loop"。這個模型的實質是把多段邏輯按事件觸發順序交織在一個系統線程中。一個event-loop只能使用一個核,故此類程序要么是IO-bound,要么是每個handler有確定的較短的運行時間(比如http server),否則一個耗時漫長的回調就會卡住整個程序,產生高延時。在實踐中這類程序不適合多開發者參與,一個人寫了阻塞代碼可能就會拖慢其他代碼的響應。由于event handler不會同時運行,不太會產生復雜的race condition,一些代碼不需要鎖。此類程序主要靠部署更多進程增加擴展性。
THsHaServerTHsHaServer繼承于TNonblockingServer,引入了線程池提高了任務處理的并發能力。THsHaServer是半同步半異步(Half-Sync/Half-Async)的處理模式,Half-Aysnc用于IO事件處理(Accept/Read/Write),Half-Sync用于業務handler對rpc的同步處理上。
具體模型如下:
THsHaServer與TNonblockingServer模式相比,THsHaServer在完成數據讀取之后,將業務處理過程交由一個線程池來完成,主線程直接返回進行下一次循環操作,效率大大提升。
但是,主線程仍然需要處理accpet、read、write時間,當并發量非常大,讀取或者發送的數據量比較大時,會將主線程阻塞住,新的連接無法被及時處理。
TThreadedSelectorServerTThreadedSelectorServer是對THsHaServer的一種改進,它將selector中的read/write事件從主線程中剝離出來。
TThreadedSelectorServer是thrift提供的最高效的網絡模型。具體模型如下:
構成如下:
一個Accpet線程,專門用來處理新的socket
n個SelectorThread,用來處理read/write事件,讀取、返回數據都是有這些線程完成的,每個SelectorThread會與若干個socket綁定,每個SelectorThread會處理與它綁定socket的read/write事件。
一個負載均衡器SelectorThreadLoadBalancer對象,在accpet線程接收到新的socket以后,由SelectorThreadLoadBalancer決定將socket與哪個SelectorThread綁定(其實就是一個next函數,每分配一個socket,就調用next)。
一個ExecutorService類型的worker線程池,在SelectorThread讀取數據之后,將其包裝成一個task,分配給worker線程池,處理業務邏輯。
總結:TThreadedSelectorServer模式,其實就是標準的Reactor模式,Tomcat7以后的版本、Cobar、MyCat(分庫分表proxy)基本都是這個套路,具體實現略有差異。
原文鏈接https://segmentfault.com/a/11...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76986.html
摘要:簡介是一個軟件框架用來進行可擴展且跨語言的服務的開發它結合了功能強大的軟件堆棧和代碼生成引擎以構建在這些編程語言間無縫結合的高效的服務官網地址安裝的安裝比較簡單在下可以直接使用快速安裝或可以通過官網下載這里就不再多說了當下載安裝完畢后我們就 簡介 thrift是一個軟件框架, 用來進行可擴展且跨語言的服務的開發. 它結合了功能強大的軟件堆棧和代碼生成引擎, 以構建在 C++, Java...
摘要:服務器端使用它來做頂層接口,編寫實現類。會自動生成同步調用和異步調用的兩個接口。方法參數的封裝類,以方法名命名方法返回值的封裝類,以方法名命名參考個人博客 基本概念 輕量級、跨語言的RPC框架 功能特點: 基于IDL(接口描述語言)生成跨語言的RPC clients and servers,支持超過20種語言 支持二進制的高性能的編解碼框架 支持NIO的底層通信 相對簡單的服務調用模...
摘要:由于工作需要使用,并且需要根據需求修改源碼,因此必須熟悉執行的流程。目前支持的模型包括使用阻塞的單線程服務器,主要用于調試。 由于工作需要使用thrift,并且需要根據需求修改thrift源碼,因此必須熟悉thrift執行的流程。以下是根據thrift源碼閱讀而得出流程分析。 thrift協議棧概述 thrift是一個rpc框架,開發者可以通過thrift自帶的接口定義語言(IDL)來...
摘要:是一種接口描述語言和二進制通訊協議,它被用來定義和創建跨語言的服務。它被當作一個遠程過程調用框架來使用,是由為大規模跨語言服務開發而開發的。筆者使用的異步服務端提供的接口實現一個了異步協程化的應用。 Swoole擴展簡介 Swoole:面向生產環境的 PHP 異步網絡通信引擎使 PHP 開發人員可以編寫高性能的異步并發 TCP、UDP、Unix Socket、HTTP,WebSock...
閱讀 684·2021-11-25 09:43
閱讀 2953·2021-11-24 10:20
閱讀 1002·2021-10-27 14:18
閱讀 1076·2021-09-08 09:36
閱讀 3382·2021-07-29 14:49
閱讀 1783·2019-08-30 14:07
閱讀 2937·2019-08-29 16:52
閱讀 3049·2019-08-29 13:12