背景

在使用 Swift on Server 之前,我最熟悉的 Web Framework 是 Ruby on Rails,除此之外,我也使用过 Python,NodeJS,Elixir 和 Go 来编写后端,但给捧读编写后端服务的时候,我权衡再三,最终选择了 Swift on Server.

本章将分享当时我为何做了这个决定,以及这个决定在随后的三年为何被验证是正确的选择,如果你和我的情况类似,那么相信会有所收获。

捧读——一款基于机器学习技术的日语语法分析 App

从单机开始

捧读在 2019 年的研发之初,是作为一款单机产品设计的,初衷是希望即使我不在了,这款产品也依旧可以很好的运作,让用户实现真的一次购买,永久使用。

设计为单机产品主要起因于我两个想法

  1. 教育资源需要足够容易被获取,这样才公平
  2. 我需要把产品的运行成本降到足够的低,由此这款教育产品就可以被卖的足够便宜,让更多人可以用上

但随着时间的推移,捧读的机器学习模型更新给我带来了麻烦。

在单机的情况下,模型更新完全依赖于用户是否更新了 App,因此,我无法保证每个用户都能及时使用上最新的模型,获得最好的体验,除此之外,用户会逐渐积累很多学习数据,如果不提供云同步功能,用户难以跨设备使用,更是容易产生丢失数据的问题。

因此,为了解决「用户体验」和「单机」之间的冲突,在 2021 年的时候,我决定给捧读设计一个后端。

需求驱动的选择

在调研技术方案前,我们先来看下捧读服务端有哪些需求

  • 捧读的算法逻辑已经用 Swift 写完了,能不重写可以极大的加快我的研发效率
  • 捧读使用了很多 C 库来支撑算法的实现,因此和 C 库的集成方式要足够简单
  • 服务端的性能一定要足够好,让用户几乎不需要等待
  • 服务端运行时的资源占用要足够的小,这样我在配置多节点实现高可用的时候,就不需要花大价钱买高配的服务器

Ruby on Rails 的优缺点

以 Ruby on Rails 来说,这是一个我从 2013 年就开始使用的 Web 框架,也一直是它的拥趸,那么,先来看一下它的优劣

优点:

  • 可以非常高效的完成业务需求
  • 生态完善,常规业务功能都有现成的开源实现
  • 很容易找到使用这个技术的小伙伴
  • 很容易找到学习资料

缺点:

  • 性能一般(可以通过把耗费算力的用其他编译型语言写成模块优化)
  • 内存占用比较高
  • 和 C 库的互调比较麻烦
  • 并发能力弱(可以通过多线程、多实例、多节点的方式优化)

Swift on Server 的优缺点

反观 Swift on Server,它的优缺点有哪些呢?

优点:

  • 可以复用 iOS App 和 Swift 生态的代码
  • 编译型语言非常稳定
  • 和 C 库的集成非常容易自然,今年 Swift 5.9 又完善了和 C++ 的集成
  • 性能极好的同时,内存的占用非常低,这意味省大量的钱
  • 整个生态都使用了 Non-Blocking I/O 的设计理念,高并发的支持非常好

缺点:

  • 作为服务端是一个非主流,大部分服务都没有对应的 SDK
  • 很难找到学习 Swift on Server 的小伙伴
  • 学习资料很少

除此之外,Swift 对我来说还有三个加分项

  • Swift 这门语言写起来愉悦性很强
  • Swift 的社区很活跃
  • Apple 对其投入足够大,每年都有很多惊喜

因此,Swift on Server 对我来说,只要扬长避短,克服这些缺点,就是一个完美的选择。

克服 Swift on Server 的先天劣势

就像脚本语言借用其他语言来补全自己的短板一样,Swift 也同样可以借助其他语言的生态来补全自己的短板,在这个 Cloud Native 的时代,借助微服务和 Serverless 的帮助,我们可以很轻易的解决这些问题。

解决缺少第三方服务 SDK 的问题

以 Azure 为例,Azure TTS 并没有提供 Swift 的服务端 SDK,但可以很容易的找到其他语言的,比如 Python 和 NodeJS.

我的解决方案是用 JS 把和 Azure TTS 打交道的功能,部署到 AWS 的 Lambda 上,当 Server App 需要和 TTS 打交道的时候,就用 HTTP 请求这个 Lambda Function.

这个方案的优点如下

  • Lambda Function 可以写的足够简单,比如在 TTS 这件事上,我只有 60 行代码
  • Lambda Function 的运行环境和我们的 Server App 是完全分离的,因此不占用额外资源,运行时相互之间也不会产生影响
  • AWS Lambda 的免费额度足够多,你几乎不需要付出金钱

解决技术包容性的问题

我们很容易面临一个这样的问题,我喜欢 Swift,他可能喜欢 Rust,其他人则可能喜欢 Go 或其他语言。

当我选择了 Swift on Server 的时候,是否和其他人的世界就无缘了呢?

当然不是!通过一个精巧且合理设计的微服务架构,你可以很轻松的在不同的业务模块里,使用完全不同的语言和技术,相较于使用一门语言实现一个大单体应用,这样带来的直接好处有两点

  • 每个语言都有自己最擅长的领域,借助微服务可以轻松整合不同技术一起工作
  • 每个人都可以选择自己最喜欢的技术来完成他的目标,这样会很开心

使用 Swift on Server 的三年

从 2021 年服务器上线至今,已经高效,稳定的运行了 3 年,在这期间,业务从仅有的用户系统和语法分析,拓展到了支付系统,账单系统,以及后来的生词本和学习系统,在未来,我也会继续使用 Swift on Server 完成其他的产品需求。

之所以开启这个系列,是希望将我使用 Swift on Server 的经验系统的分享出来,让更多的人可以从中受益。

诚然,Swift on Server 不会是适合每个人的方案,因此我也列了一个画像,如果你符合这些条件,那么请持续关注这个系列的文章。

谁适合使用 Swift on Server

符合下列任何一条皆可

  • 已经在使用 Swift 语言
  • 有自己的 iOS App 希望开发后端
  • 对 Swift 语言充满热情
  • 关注性能和高并发

系列预告

本系列文章的会以一个 Micro Blog Server 为示例,和你一起畅游 Swift on Server 的世界,这个系列主要面向对服务器开发的初学者,因此除了功能的实现外,会写很多概念相关的内容。

总体来说,话题会涉及到以下方面

  1. 概念:什么是 Server App
  2. 概念:HTTP 请求的那些事
  3. Framework:选择你的框架 - Vapor
  4. Database:设计你的数据模型
  5. API:设计你的 API
  6. Auth:用户权限验证
  7. Test:测试你的 API
  8. CI:部署你的服务器
  9. 微服务:和其他语言一起工作
  10. 微服务:多人同时在线的聊天室

我会利用闲暇的时间,更新这个系列,希望能够完成每 1 - 2 周一更,欢迎持续关注!