Swift Server-side

isaced發表於2018-04-16

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 寫的?

參考

相關文章