重新思考适用于Swift的服务器架构
本文是我在东京-服务器端Swift聚会#5上演讲的幻灯片的英文摘要。
Swift中的并行性
DispatchQueue使我们能够轻松地在系统(或libdispatch)托管线程上进行多线程编程。 它具有两种执行属性。
- serial :在单独的线程上按顺序执行任务
- 并发:在单独的线程上并行执行任务
哪种服务器架构适合Swift?
基于上述内容,让我们考虑一种适用于Swift的服务器架构。 当然应该注意C10K问题。
(这一次,我坚持使用Swift的标准API创建服务器。由于它应该适合Swift,因此对Swift程序员很友好,而且很生态。)
我的答案之一是… 基于DispatchSource的EventDriven模型+基于DispatchQueue的工作线程模型体系结构
通过这种体系结构,您可以不加意识地使用GCD提供的大量功能。 当然,没有自己的线程管理,没有回调地狱(通常)并且有效地使用了系统资源。
你喜欢它?
GCD的问题
最后,我找到了Swifty服务器架构的答案之一。
但是..在GCD中……尤其是DispatchQueue有时会出现问题。
DispatchQueue问题
- 比赛条件
- 回调地狱
比赛条件
如果我们在并发模式下执行DispatchQueue.async并从多个队列访问变量,则可能发生竞争情况。 因此,我们必须对Mutex或Semaphore的每个操作都使用排他控制来避免这种情况。 但是,即使现在,独占控制仍然非常困难。
回调地狱
在事件驱动器范例中,回调地狱是一个严重的问题。 在Swift中,我们通常不必担心它,因为几乎所有操作都在阻塞。
但是,如果要异步访问文件系统或网络,还需要再次调用DispatchQueue.async。 我看到一个有10次嵌套回调的iOS应用…
避免回调地狱的现代方法
- 未来/承诺
- 异步/等待
但是Swift没有这些设备……所以我们应该放弃……?
不! 我们应该知道一种可以使用同步语法控制异步操作的语言……这是一种GO编程语言🐭
Go提供了称为Goroutines的原始并发/并行API。
它的行为就像在多个线程上多路复用的协程。 而Go可以避免Channel带来的比赛条件。 就像goroutine和goroutine之间的共享内存一样。
DispatchQueue也是基于线程的api,因此,如果我们将Goroutines和Channels之类的接口引入Swift,则使异步流控制变得容易,可读和安全。
简介
我实现了具有HTTP(S),TCP Server / Client和Go并发系统(称为Prorsum)的网络环境。 它的HTTP Server体系结构是EventDriven模型+工作线程模型,向您展示了上面的内容。
GitHub :https://github.com/noppoMan/Prorsum
像设备一样
使用Prorsum,我们可以像异步流控制一样轻松编写Go。
标杆管理
最后,我必须证明我所介绍的体系结构是否有效。 我认为,基准测试与其他语言或框架相比,是最简单的证明方法。
结果,Go的运行速度快得令人难以置信……👏,但是Prorsum在Request / sec中排名第二。 它比Kitura和Express快。 (Kitura和Express是Web框架,因此此基准测试并不完全公平。)
因此,它表明我提出的体系结构不是错误。
聚苯乙烯
它曾是怎样的? 我认为服务器架构没有正确的答案,但我认为我可以使用大量Swift的标准API为具有当前Swift架构的服务器提供适当的支持。 (但是我从GO获得了各种精髓……)
这是Prorsum的示例应用程序,它在Meetup上播放了演示。 https://github.com/noppoMan/TSSS-JSONRPCServer
感谢阅读!