Apple 新開源了一個 Swift 相關(guān)的項目,叫 swift-nio彬呻,是一個事件驅(qū)動的非阻塞的網(wǎng)絡(luò)框架衣陶,用來寫高性能網(wǎng)絡(luò)應(yīng)用≌⒌看來官方真的繼續(xù)在往 Server-Side 方面努力.GitHub.
SwfitNIO 的目標是支持所有可以運行 Swift 的平臺剪况。目前,SwfitNIO 可以在 macOS 和 Linux 上運行蒲跨,包括:
Ubuntu 14.04+
macOS 10.12+
基本架構(gòu)
SwfitNIO 包含了幾種基本構(gòu)建塊译断,所有的 SwfitNIO 應(yīng)用程序都是由這幾種組件組成的。
EventLoopGroup
EventLoop
Channel
ChannelHandler
Bootstrap
ByteBuffer
EventLoopPromise 和 EventLoopFuture
EventLoop 是 SwfitNIO 最基本的 IO 原語财骨,它等待事件的發(fā)生镐作,在發(fā)生事件時觸發(fā)某種回調(diào)操作。在大部分 SwfitNIO 應(yīng)用程序中隆箩,EventLoop 對象的數(shù)量并不多该贾,通常每個 CPU 核數(shù)對應(yīng)一到兩個 EventLoop 對象。一般來說捌臊,EventLoop 會在應(yīng)用程序的整個生命周期中存在杨蛋,進行無限的事件分發(fā)。
EventLoop 可以組合成 EventLoopGroup,EventLoopGroup 提供了一種機制用于在各個 EventLoop 間分發(fā)工作負載逞力。例如曙寡,服務(wù)器在監(jiān)聽外部連接時,用于監(jiān)聽連接的 socket 會被注冊到一個 EventLoop 上寇荧。但我們不希望這個 EventLoop 承擔所有的連接負載举庶,那么就可以通過 EventLoopGroup 在多個 EventLoop 間分攤連接負載。
目前揩抡,SwiftNIO 提供了一個 EventLoopGroup 實現(xiàn)(MultiThreadedEventLoopGroup)和兩個 EventLoop 實現(xiàn)(SelectableEventLoop 和 EmbeddedEventLoop)户侥。
MultiThreadedEventLoopGroup 會創(chuàng)建多個線程(使用 POSIX 的 pthreads 庫),并為每個線程分配一個 SelectableEventLoop 對象峦嗤。
SelectableEventLoop 使用選擇器(基于 kqueue 或 epoll)來管理來自文件和網(wǎng)絡(luò) IO 事件蕊唐。EmbeddedEventLoop 是一個空的 EventLoop,什么事也不做烁设,主要用于測試替梨。
?Channels、ChannelHandler装黑、ChannelPipeline 和 ChannelHandlerContext
盡管 EventLoop 非常重要副瀑,但大部分開發(fā)者并不會與它有太多的交互,最多就是用它創(chuàng)建 EventLoopPromise 和調(diào)度作業(yè)恋谭。開發(fā)者經(jīng)常用到的是 Channel 和 ChannelHandler俗扇。
每個文件描述符對應(yīng)一個 Channel,Channel 負責管理文件描述符的生命周期箕别,并處理發(fā)生在文件描述符上的事件:每當 EventLoop 檢測到一個與相應(yīng)的文件描述符相關(guān)的事件,就會通知 Channel滞谢。
ChannelPipeline 由一系列 ChannelHandler 組成串稀,ChannelHandler 負責按順序處理 Channel 中的事件。ChannelPipeline 就像數(shù)據(jù)處理管道一樣狮杨,所以才有了這個名字母截。
ChannelHandler 要么是 Inbound,要么是 Outbound橄教,要么兩者兼有清寇。Inbound 的 ChannelHandler 負責處理“inbound”事件,例如從 socket 讀取數(shù)據(jù)护蝶、關(guān)閉 socket 或者其他由遠程發(fā)起的事件华烟。Outbound 的 ChannelHandler 負責處理“outbound”事件,例如寫數(shù)據(jù)持灰、發(fā)起連接以及關(guān)閉本地 socket盔夜。
ChannelHandler 按照一定順序處理事件,例如,讀取事件從管道的前面?zhèn)鞯胶竺嫖沽矗鴮懭胧录t從管道的后面?zhèn)鞯角懊娣凳C總€ ChannelHandler 都會在處理完一個事件后生成一個新的事件給下一個 ChannelHandler。
ChannelHandler 是高度可重用的組件椭微,所以盡可能設(shè)計得輕量級洞坑,每個 ChannelHandler 只處理一種數(shù)據(jù)轉(zhuǎn)換,這樣就可以靈活組合各種 ChannelHandler蝇率,提升代碼的可重用性和封裝性迟杂。
我們可以通過 ChannelHandlerContext 來跟蹤 ChannelHandler 在 ChannelPipeline 中的位置。ChannelHandlerContext 包含了當前 ChannelHandler 到上一個和下一個 ChannelHandler 的引用瓢剿,因此逢慌,在任何時候,只要 ChannelHandler 還在管道當中间狂,就能觸發(fā)新事件攻泼。
SwiftNIO 內(nèi)置了多種 ChannelHandler,包括 HTTP 解析器鉴象。另外忙菠,SwiftNIO 還提供了一些 Channel 實現(xiàn),比如 ServerSocketChannel(用于接收連接)纺弊、SocketChannel(用于 TCP 連接)牛欢、DatagramChannel(用于 UDP socket)和 EmbeddedChannel(用于測試)。
?Bootstrap
SwiftNIO 提供了一些 Bootstrap 對象淆游,用于簡化 Channel 的創(chuàng)建傍睹。有些 Bootstrap 對象還提供了其他的一些功能,比如支持 Happy Eyeballs犹菱。
目前 SwiftNIO 提供了三種 Bootstrap:ServerBootstrap(用于監(jiān)聽 Channel)拾稳,ClientBootstrap(用于 TCP Channel)和 DatagramBootstrap(用于 UDP Channel)。
?ByteBuffer
SwiftNIO 提供了 ByteBuffer腊脱,一種快速的 Copy-On-Write 字節(jié)緩沖器访得,是大部分 SwiftNIO 應(yīng)用程序的關(guān)鍵構(gòu)建塊。
ByteBuffer 提供了很多有用的特性以及一些“鉤子”陕凹,通過這些鉤子悍抑,我們可以在“unsafe”的模式下使用 ByteBuffer。這種方式可以獲得更好的性能杜耙,代價是應(yīng)用程序有可能出現(xiàn)內(nèi)存問題搜骡。在一般情況下,還是建議在安全模式下使用 ByteBuffer佑女。
?EventLoopPromise 和 EventLoopFuture
并發(fā)代碼和同步代碼之間最主要的區(qū)別在于并非所有的動作都能夠立即完成浆兰。例如磕仅,在向一個 Channel 寫入數(shù)據(jù)時,EventLoop 有可能不會立即將數(shù)據(jù)沖刷到網(wǎng)絡(luò)上簸呈。為此榕订,SwiftNIO 提供了 EventLoopPromise和 EventLoopFuture,用于管理異步操作蜕便。
EventLoopFuture實際上是一個容器劫恒,用于存放函數(shù)在未來某個時刻的返回值。每個 EventLoopFuture對象都有一個對應(yīng)的 EventLoopPromise轿腺,用于存放實際的結(jié)果两嘴。只要 EventLoopPromise 執(zhí)行成功,EventLoopFuture 也就完成了族壳。
通過輪詢的方式檢查 EventLoopFuture 是否完成是一種非常低效的方式憔辫,所以 EventLoopFuture 被設(shè)計成可以接收回調(diào)函數(shù)。也就是說仿荆,在有結(jié)果的時候回調(diào)函數(shù)會被執(zhí)行贰您。
EventLoopFuture負責處理調(diào)度工作,確甭2伲回調(diào)函數(shù)是在最初創(chuàng)建 EventLoopPromise 的那個 EventLoop 上執(zhí)行锦亦,所以就沒有必要再針對回調(diào)函數(shù)做任何同步操作。
SwiftNIO 的設(shè)計哲學(xué)
SwiftNIO 的目標是要成為強大的網(wǎng)絡(luò)應(yīng)用程序開發(fā)框架令境,但并不想為所有的層次抽象提供完美的解決方案杠园。SwiftNIO 主要專注在基本的 IO 原語和底層的協(xié)議實現(xiàn)上,將其他層次的抽象留給廣大的社區(qū)去構(gòu)建舔庶。SwiftNIO 將成為服務(wù)器端應(yīng)用程序的構(gòu)建塊抛蚁,但不一定就是應(yīng)用程序直接拿來使用的框架。
對性能有很高要求的應(yīng)用程序可能會直接使用 SwiftNIO惕橙,減少上層抽象所帶來的開銷篮绿。SwiftNIO 可以幫助這些應(yīng)用程序在提升性能的同時降低維護成本。SwiftNIO 還為某些場景提供了有用的抽象吕漂,高性能的網(wǎng)絡(luò)服務(wù)器可以直接使用這些抽象。
大家也可以看GitHub上面的原版介紹
目前有一些例子尘应,演示了如何使用 SwiftNIO惶凝。
聊天客戶端:
聊天服務(wù)器端:
Echo 客戶端:
Echo 服務(wù)器端:
Http 服務(wù)器: