重新思考适用于Swift的服务器架构

本文是我在东京-服务器端Swift聚会#5上演讲的幻灯片的英文摘要。

Swift中的并行性

DispatchQueue使我们能够轻松地在系统(或libdispatch)托管线程上进行多线程编程。 它具有两种执行属性。

  1. serial :在单独的线程上按顺序执行任务
  2. 并发:在单独的线程上并行执行任务

哪种服务器架构适合Swift?

基于上述内容,让我们考虑一种适用于Swift的服务器架构。 当然应该注意C10K问题。

(这一次,我坚持使用Swift的标准API创建服务器。由于它应该适合Swift,因此对Swift程序员很友好,而且很生态。)

我的答案之一是… 基于DispatchSource的EventDriven模型+基于DispatchQueue的工作线程模型体系结构

通过这种体系结构,您可以不加意识地使用GCD提供的大量功能。 当然,没有自己的线程管理,没有回调地狱(通常)并且有效地使用了系统资源。

你喜欢它?

GCD的问题

最后,我找到了Swifty服务器架构的答案之一。

但是..在GCD中……尤其是DispatchQueue有时会出现问题。

DispatchQueue问题

  1. 比赛条件
  2. 回调地狱

比赛条件

如果我们在并发模式下执行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

感谢阅读!

Interesting Posts