SwiftNIO 学习

NIO, Non-Blocking I/O, 是指以非阻塞方式实现I/O操作。这一概念在利用率极低的场景下如HTTP服务器能够显著提升性能。相比原地等待网络数据,非阻塞式实现方式在需要等待的情况下转而去做别的事情,并要求内核在数据准备好之后提醒它,从而继续之前的工作。

SwiftNIO是一个底层框架,利用它可以构建更高层级的框架,如Web框架。普通用户一般不会直接用SwiftNIO,而是转而使用基于SwiftNIO的高级框架,如Kitura、Perfect、Vapor等。

SwiftNIO有8种基础性的对象类型:
EventLoopGroup接口
EventLoop接口
Channel接口
ChannelHandler接口
Bootstrap多种数据结构
ByteBuffer结构体
EventLoopFuture通用类
EventLoopPromise通用结构体
所有的SwiftNIO软件都最终由这8种组件构成。

SwiftNIO中的I/O原型基础是event loop。Event loop等待event带来然后触发相应的callback function。Event loop数量不多,一般每个CPU核心只会有1-2个。过多的Event loop没有意义反而会增加内核调度event loop线程的开销而降低性能。通常来说event loop会贯穿整个生命周期,持续不断地调度各种events。

Event loops构成多个event loop groups。Groups负责向event loops分发工作,可以理解为负载均衡器。

SwiftNIO当前有1个EventLoopGroup和2个EventLoop实现。对于生产应用,MultiThreadedEventLoopGroup首先是EventLoopGroup,然后它能够使用POSIX协议的pthreads库创建多个线程,最后在每个线程上跑一个SelectableEventLoop。SelectableEventLoop是一种event loop,它使用selector(在不同平台上分别用kqueue和epoll实现)来管理I/O events,从文件描述符一直管理到dispatch。此外,还有一种EmbeddedEventLoop,只用于测试目的。

EventLoop有一系列重要的特性。最重要的一点,为了确保线程安全,SwiftNIO上的任何工作都必须通过EventLoop来调度。通过EventLoop对象,我们可以访问SwiftNIO中几乎一切资源,因此充分理解EventLoop的运行模式对于构建高性能SwiftNIO应用至关重要。

尽管EventLoop至关重要,大多数用户除了创建一个EventLoopPromise外,并不怎么直接和它打交道。日常,我们更多时间会处理Channel和ChannelHandler相关的事情。

SwiftNIO中几乎每个文件描述符都有一个对应的Channel。Channel拥有这个文件描述符,并处理这个文件描述符上的I/O事件。Event Loop接收到event后,会找到对应的文件描述符,然后文件描述符对应的Channel。

ChannelPipeline由一系列ChannelHandler组成,它们负责处理Channel上的events。ChannelHandlers按照顺序逐个处理events,对event完成变更和传递工作。这可以理解为数据处理流水线,所以叫作ChannelPipeline。

ChannelHandler分为inbound handler和outbound handler,还可以两个都是。