Swift

从苹果在 2015 年 WWDC 正式发布 Swift 起,大家冷嘲热讽的就是苹果爸爸一年出一个新语言,梗的来源其实是因为 Swift 早期几个版本 API 变化非常大,很多开发者对其吐槽。

随后在 16 年的时候苹果正式成立 swift-server 工作组,核心成员由几个主流 Swift Web Framework 核心开发者组成并且同样由社区驱动,主要目标是建立基于 Swift 的服务器基础功能,包括基础网络、安全和加密、HTTP 和 WebSocket。

接下来我们来看看到这个工作组具体做了些什么,以及目前开源社区活跃的 Web 框架对比。

image.png | left | 748x263

跨平台

Swift 最早设计之初的核心目标之一就是跨平台,能在苹果的 darwin、Linux 甚至 Windows 上运行。

Darwin 是由 Apple 于 2000 年所发布的一个开源类 Unix 操作系统,是 macOS 和 iOS 操作环境的操作系统部分。

Swift 在 Darwin 和 Linux 最底层实现了一层统一的系统框架,并在其之上建立了一套标准库(包括 Foundation、Dispatch),但是像 iOS/macOS 中的 GCD (Grand Central Dispatch) 最初只能跑在苹果自家系统之上,所以后来通过开源并移植出了 Linux 的 apple/swift-corelibs-libdispatch,加上其他一些标准库的不对齐问题导致这部分在两边的结构上有些区别,所以最上层再通过一层统一包装统一差异。

image.png | left | 748x421

交互

大致的客户端-服务端-三方服务交互流程如下,我们通过 App 发起请求,到自己的 Swift 应用服务器,通过路由分发到对应的处理逻辑,然后按需调用其他三方服务,比如文件存储、数据库等等,最后再返回给 App 客户端。

image.png | left | 748x217

Server APIs Project

Core

  • Low-level Access
  • Sockets
  • HTTP parsing and security
  • High level server frameworks [X]
  • Deliver via Swift Package Manager

Base Networking

  • Network I/O (TCP/UDP)
  • IPv4 / IPv6
  • Synchronous and asynchronous non-blocking connections

Security and Encryption

  • SSL/TLS

Core Team

现状

然后看看 Swift server project 具体做了些什么事,其实除了基础的 HTTP 服务,还有一部分很重要的就是安全/加密库的方案,

swift-server/http

HTTP API 的早期实现,swift-server/http 与其他 Web Framework 最大的不同即是它只包含了非常精简的基础网络,可以先感受一下,所有的处理都从唯一的 handler 作为入口进行处理,缺少路由、过滤等能力。

import Foundation
import HTTP

func hello(request: HTTPRequest, response: HTTPResponseWriter ) -> HTTPBodyProcessing { 
    response.writeHeader(status: .ok) 
    response.writeBody("Hello, World!") 
    response.done() 
    return .discardBody 
} 

let server = HTTPServer()
try! server.start(port: 8080, handler: hello)

RunLoop.current.run()

swift-server/TLSService

从 IBM-Swift/BlueSSLService Fork 过来的 SSL/TLS 支持库。

image.png | left | 748x421

swift-server/security

目前没有一个兼容 Swift 所支持的所有平台的标准安全库,导致项目缺少安全功能要么自己开发,要么使用如 OpenSSL、LibreSSL 等开源安全库,可能会造成的问题:

  • 依赖关系不兼容
  • 不安全(未打补丁或不安全的库)
  • 难维护(使用非标准库)
  • 更复杂的代码(不同的代码针对不同平台实现)

LibreSSL 是 OpenSSL 加密软件库的一个分支,为一个安全套接层(SSL)和传输层安全(TLS)协议的开源实现。

目标:

  • 支持 Apple 和 Linux
  • 系统平台集成,免去安装维护
  • 本地动态链接,以便及时更新安全补丁
  • 跨操作系统 API 一致性
  • 去掉通信协议,只包含数据流交互

解决方案:

不同平台分别对下层进行包装,提供一个 Swift 轻量层

  • Linux - 使用 OpenSSL (libssl / libcrypto)
  • Apple - [CommonCrypto -> OpenSSL's libcrypto], [Secure Transport -> OpenSSL's libssl]
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
    import CommonCrypto
#elseif os(Linux)
    import OpenSSL
#endif

OpenSSL由两个独立的库组成:libcrypto 和 libssl。

  • libcrypto 是一个通用的密码学库,可以单独使用。
  • libssl 是一个依赖于 libcrypto 的用于支持 TLS 的库。
为什么不创造一个统一安全裤?

OpenSSL 统一、跨平台,但是各个版本缺乏 API 兼容性,Apple 从 OS X v10.7 开始不推荐使用 OpenSSL。

截至 2014 年,据估计至少有 66% 的互联网服务器使用 OpenSSL(Apache/nginx)。

为什么不用其他开源安全裤?
LibreSSL

14 年在 OpenSSL 爆出心脏出血漏洞后,OpenBSD 开发团队从 OpenSSL 开出一个分支起名 LibreSS,但其不支持 FIPS (联邦资料处理) 标准,LibreSSL故意删除了OpenSSL 的 FIPS 模块,使库更加精简,从而提高了安全性和性能。

BoringSSL

Google 根据 OpenSSL Fork 出的一个分支,旨在满足 Google 的需求,也没有 API/ABI 稳定性保证,不建议第三方使用,同样不支持 FIPS。Chrome / Chromium 和 Android (not NDK) 一些应用中使用。

FIPS是美国政府(NIST)的密码标准,是大多数政府机构和许多企业的要求。
获得认证的过程艰难,昂贵且耗时,只能由供应商和大型组织完成。

那 MacOS 升级了 LibreSSL 不支持 FIPS 咋办?
所以有了 CoreCrypto 和 CoreCrypto,其内核进行验证。

Web Frameworks

顺带我们来看看目前开源社区主流的几个 Swift Web 框架,其中 IBM 的 Kitura 算是布道者,在框架本身的设计思想和 Swift 周边的支持服务对社区都起到很大帮助作用,很多东西也直接被 Swift 官方融合了进去,比如 BlueSSLService。

image.png | left | 748x421

Vapor

颜值最高的 Web Framework,官网设计很好看,当初用它就是因为这个,文档也比较全,配套的依赖、编译工具比较完善;在模版、数据库连接、测试、WebSocket、日志等方面都有全面支持;在官方 vapor.university ​中有很多学习资源,iOS 开发著名博客 Ray Wenderlich 为其录制了一系列快速上手视频教程。

import Vapor

let drop = try Droplet()

drop.get("hello") { req in
    return "Hello, world."
}

try drop.run()

Kitura

IBM 之作,受 Express.js 启发的一个元老级框架,比较注重稳定性、安全性,提供可插拔式的中间件机制,同时也支持 FastCGI,可以轻松集成到标准的 Web 服务器环境(Nginx/Apache);早期版本 Kitura 自成一套编程模型,且没有利用 Swift 本身一些语言优势,在 Kitura 2.0 中新引入 Codable Routing 特性,充分利用了 Swift 4 的 Codable 特性。IBM Cloud 也为其提供专有容器,可以一键部署到云端,同时也提供 Swift 和 Kitura 商业级支持。

import Kitura

let router = Router()

router.get("/") {
    request, response, next in 

    response.send("Hello world!")
    next()
}

Kitura.addFastCGIServer(onPort: 9000, with: router)

Kitura.run()

Perfect

出自于一个来自加拿大的创业公司,最初的版本其实在 Swift 开源之前,当时只支持 macOS,后来随着 Swift 开源跨平台;提供两个版本的服务器,一种是基于FastCGI,通过 mod_perfect 嵌入Apache,另一种是自身提供的独立 HTTP/s 服务器程序;官方强烈推荐使用 Docker 和 Heroku 进行部署。
其大而全的设计思想,类似于 Python 中的 Django 框架,支持 FastCGI,中文文档支持友好。

Zewo

单线程应用,Zewo 没有使用 GCD 作为并发库,而是选择了基于 libmill 提供类似 Go-lang 的 CSP 并发模型,目前基本停滞更新。

CSP 模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享的通讯 channel(管道)进行通信的并发模型。 CSP中 channel 是第一类对象,它不关注发送消息的实体,而关注与发送消息时使用的channel。

Golang实现了 CSP 并发模型做为并发基础,底层使用 goroutine 做为并发实体,goroutine非常轻量级可以创建几十万个实体。实体间通过 channel 继续匿名消息传递使之解耦,在语言层面实现了自动调度,这样屏蔽了很多内部细节,对外提供简单的语法关键字,大大简化了并发编程的思维转换和管理线程的复杂性。

性能对比:

由于 Swift 语言本身静态特性,单从性能指标和一些动态语言的 Web 框架进行对比会有明显差距,但是我们知道一个优秀的 Web 框架除了性能也有其他更多值得关注的东西,比如开发效率、设计哲学、社区文档支持、可扩展性、易用性以及各个其他方面的技术指标等等,不过个人认为最终还是归于 “合适而不是最好”的理念。

不过这里有一篇比较详细的 Swift Web Framework 对比 Node.js 的文章可以给大家一个直观的感受:Benchmarks for the Top Server-Side Swift Frameworks vs. Node.js

其他

目前来看官方的 Swift server 项目进展缓慢,主要由社区进行贡献,反观社区早已存在的主流 Web Framework 发展比较活跃,以 Swift server project 的定位来看以后一定是提供底层基础的服务器能力,让第三方框架建立其之上。

They will not provide high level server frameworks such as web frameworks. Instead, they serve as a foundation to enable those frameworks to be developed by others.

有什么 Web 项目使用 Swift 写的?

参考