背景
在使用 Swift on Server 之前,我最熟悉的 Web Framework 是 Ruby on Rails,除此之外,我也使用过 Python,NodeJS,Elixir 和 Go 来编写后端,但给捧读编写后端服务的时候,我权衡再三,最终选择了 Swift on Server.
本章将分享当时我为何做了这个决定,以及这个决定在随后的三年为何被验证是正确的选择,如果你和我的情况类似,那么相信会有所收获。
捧读——一款基于机器学习技术的日语语法分析 App
从单机开始
捧读在 2019 年的研发之初,是作为一款单机产品设计的,初衷是希望即使我不在了,这款产品也依旧可以很好的运作,让用户实现真的一次购买,永久使用。
设计为单机产品主要起因于我两个想法
- 教育资源需要足够容易被获取,这样才公平
- 我需要把产品的运行成本降到足够的低,由此这款教育产品就可以被卖的足够便宜,让更多人可以用上
但随着时间的推移,捧读的机器学习模型更新给我带来了麻烦。
在单机的情况下,模型更新完全依赖于用户是否更新了 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 的世界,这个系列主要面向对服务器开发的初学者,因此除了功能的实现外,会写很多概念相关的内容。
总体来说,话题会涉及到以下方面
- 概念:什么是 Server App
- 概念:HTTP 请求的那些事
- Framework:选择你的框架 - Vapor
- Database:设计你的数据模型
- API:设计你的 API
- Auth:用户权限验证
- Test:测试你的 API
- CI:部署你的服务器
- 微服务:和其他语言一起工作
- 微服务:多人同时在线的聊天室
我会利用闲暇的时间,更新这个系列,希望能够完成每 1 - 2 周一更,欢迎持续关注!