服务器端Swift:制作机盖(1/6)

最近,我构建并发布了Canopy,该服务可通过Mac和iOS应用程序为您的GitHub存储库上的活动提供即时推送通知。

我多年没有在服务器端工作过,设置服务器和编写服务器端代码真的很有趣。 中断与事件驱动的类似应用程序的编程并做一些不同的事情是令人耳目一新的,但是我仍然必须用自己喜欢的语言编写它:JavaScript……只是在开玩笑,Swift。

客户端和服务器端都是Swift。

关于服务器端Swift的信息量很低,这不足为奇,但是我在这里告诉您,如果您已经了解Swift并且也了解macOS命令行的话,这并不是一件容易的事。

斯威夫特很棒

Swift并不是所有语言中最好的语言,但它是最佳的折衷方案,这使它成为目前所有事物(它支持)的最佳语言。 自宣布以来,Swift-Core清晰而谨慎的设计决定给我留下了深刻的印象,可以全心投入。 我已经用许多种语言进行编程,并且经常发现该语言及其标准库的质量不一致,Team-Swift对他们的语言及其标准库一无所知。

本周,我将重点介绍Swift为什么适用于服务器的一些细节。 显然,协议驱动的开发,功能编程,可选的选项,错误处理模型等使Swift总体上很棒,但是我不会特别指出。 当然,这些事情使写Canopy成为一种快乐。

没有JSON

应用程序和服务器使用JSON进行通信,但是我不知道或不在乎,因为它的两端都是Codable

创建我的结构,传输,接收我的类型安全的结构。 感觉很棒。

我几乎不需要做任何工作就可以进行固有的类型安全跨进程,这使我和服务器之间的1,000英里看上去与在视图控制器之间传递数据没有什么不同。

但是,缺乏动态性意味着即使向这些结构添加单个参数也意味着对端点进行版本控制或将新参数设置为Optional 。 并非全是玫瑰花,但坦率地说,版本管理工作得很好,这意味着我解释输入数据的代码不是if语句的逻辑炸弹,它是经过仔细地,单独封装和测试的,类型安全的端点。

正常运行时间

由于使用太多文件描述符,服务器代码在生产中一次“崩溃”,因为我不得不使用(C库)libcurl编写我的APNs(Apple Push Notification service)代码(我编写了Swift,而不是C,这是另一个很棒的功能Swift能够轻松地与C库接口),但我做错了,因为UnmanagedPointer很难。 因此内核终止了它。

一次崩溃:Swift很棒。 您必须积极地致力于编写不稳定的Swift代码。 当然,Swift可为您提供健壮的代码高性能。

很棒的开发者经验

Xcode非常棒(它很烂,但是考虑到同等的开发人员工具时,这是相当令人惊讶的),Swift软件包管理器意味着跨平台开发所需的工具随Swift发行版一起提供,没有成千上万个组件的史诗级工具链出问题并要安装,这是Mac上来自App Store的一个二进制文件,服务器上是swift.org的一个二进制文件。

您可以在Mac上开发测试服务器代码,同时运行客户端应用程序并使它们一起通信(仅使用Xcode)。

目前,这样做比我们想要的要笨拙,您必须让SwiftPM从描述服务器端应用程序的Package.swift中生成一个Xcodeproj( swift package generate-xcodeproj ),然后将其嵌入到.xcodeproj (拖放)到您的客户端应用程序。 Xcode知道此后该怎么办。 这样做还可以更轻松地在各种服务器和客户端应用程序之间共享代码。

由于SwiftPM并不真正支持iOS,但您仍然需要Carthage作为iOS应用程序的依赖项,但是,如果您制作的是macOS应用程序,则可以使用SwiftPM获取的依赖项(如果您正在使用类似的依赖项)。 当然,这是不理想的,但是到2020年会变得更好(所以我们被告知-更好的Xcode集成即将到来)。

必须在此时使用Xcode(我想您可能可以使用AppCode),因为愉快地使用Swift 绝对需要自动完成。 苹果公司承认这是阻碍其广泛采用的障碍,并且最近已承诺提供语言服务器协议服务,以便其他编辑者和其他平台可以为其开发人员提供一流的Swift体验。

在服务器端运行代码就像rsyncswift run foo一样简单。 显然,您应该有一个比这更好的部署过程,但是我试图证明它是多么简单。

守则第一次生效

我喜欢Swift的许多原因之一是在编写它之后感觉到,如果对其进行编译,它将可以正常工作。 显然,情况并非总是如此,但大多数情况是这样,对于Canopy,大多数情况下都是如此。 语言是严格的,可以使您严格地编写它,但是以某种方式仍然绝对是编写代码的乐趣。 在几周后的今天,我在生产中仅发生了一次崩溃,并且该系统几乎消耗了所有CPU或内存,但工作正常。 可靠,坚固,美观。

跨平台错误

使您的错误可Codable ,然后将其从服务器发送到客户端。 极乐 。 选择正确的堆栈,您甚至可以在服务器端throw异常,并将其神奇地显示在客户端的catch语句中。

仍然仍然需要手动编写Codable实现因为您可能正在使用带有关联值的Swift的(超级) enum ,而Swift无法为这些值自动生成Codable实现。 再说一次,不是所有的玫瑰。 Sourcery可能可以解决此问题(更新:可以)。

跨平台路线

我有一个定义服务器路由的枚举(例如server.com/foo),并且在客户端和服务器上都使用了它。 没有错别字的机会,用法是类型安全的。 两端的Swift都能给您带来另一件事。

统一码

Swift默认情况下支持unicode,其他语言通常会要求您跳过(至少某些)篮球(包括JavaScript,Ruby,Python等)。 这会表现出奇怪的错误,除非您编写更多的测试,否则您可能只会在生产中看到这些错误。 完全不必担心这一点,因为Swift-Core非常担心它,这是每个人都应该从其语言和标准库中获得的要求。

基础

与Swift相比,您可能在服务器端使用的大多数语言的标准库要有限得多,这使得您无法确定应该使用数十种选择中的哪一种来进行诸如解析JSON,处理unicode甚至经常是联网等选择。 Swift具有基金会,尽管在Linux上有些不完整,但它提供了解决常见问题的解决方案,其API已有20年的成熟,因此经过20年的考验。 这仅适用于API,因为Linux Foundation最初启动时几乎是空的,需要社区加紧编写它,但是针对既定蓝图的编写进展很快。

尽管您可以在这里选择Java,但是我将重点放在比(相对)古老的Java更现代的替代方案上,从而导致缺少我们想要的现代语言功能。

Foundation为复杂的场景提供了彻底的解决方案,例如语言环境(例如,格式,货币,语言环境感知的字符串排序等),日期,时区,货币,网络,IPC / XPC等。这真是太棒了。

与C库轻松集成

Foundation中的漏洞包括加密技术(由macC上的CommonCrypto提供,但Apple封闭源代码),但是由于Swift 可以轻松地与OpenSSL之类的系统库集成,因此人们迅速加紧将这些功能提供给SwiftPM,因此我们已经成熟加密功能,而无需任何人去完成从头开始编写此类代码的艰巨任务。

可以肯定的是,密码学太重要了,不能依靠没有经过古老和考验的东西。

性能

我的实例几乎没有占用百分之几的CPU,最多使用了10%的可用内存。 云服务旨在提供像JavaScript和Ruby这样的饥饿语言所需要的资源,Sw​​ift勉强可以触及表面。 缩减实例并享受成本节省。 与使用脚本语言相比,可扩展10倍,而无需考虑诸如负载平衡之类的复杂解决方案。

坏人

没有一件事情是伟大的,否则任何告诉你的人都变得迟钝。

Linux上的Swift不如macOS上的Swift完整。 例如,Linux Foundation不完整。 在开发过程中,由于URLSession有一些NSNotImplemented致命错误,这些错误会不NSNotImplemented出现,因此我的正常运行时间会很NSNotImplemented 。 如果您查看源代码,将会看到Foundation for Linux的网络层是基于libcurl构建的,并且它是不完整的。

我将网络从Foundation迁移到了Foundation,而不是使用我选择的服务器平台提供的库(之所以提供它是因为 Foundation在Linux上比较薄弱)。

这是不幸的,但是在接下来的几年中这将成为过去,这是为Swift本身做出贡献的绝好机会,在这种情况下,我会这样做,但似乎苹果计划使用最近解决的问题自行解决发布了Swift-NIO。

尽管如此,调试跨平台代码(在不同平台上的行为方式不同)仍然很困难,而在Linux上进行调试则是超级麻烦。 我根本无法使调试器正常工作,而是放弃了使用总print语句和我通常缺乏的东西:耐心。

在Linux上缺少一些基金会桥接(在as NSSomething就是as NSSomething ),并且只有在Linux上编译时才知道,这很糟糕,但这是一个相当罕见的问题。

必须为从GitHub获得的所有JSON编写Codable也是一种PITA(GitHub提供了43种不同的Webhook负载),但总的来说,我比拥有快速编码替代方案更具有类型安全结构使用JSON进行操作时,JavaScript甚至ObjC都允许。 好吧,让我们明确一点:编写Codable s是翻译中相当快的练习; Swift编译器完成大部分工作。

在Linux上,Swift最糟糕的部分将在接下来的几周内发布,因为它们关系到构建系统和一般的Linux问题。

嘿!

我是Max Howell,我想专职从事开放源码的写作,写作和全部工作。 我从事开源工作已有15年了,您可能已经使用过其中的一部分(有人自制吗?)。 我需要您的帮助才能继续,任何贡献都值​​得欢迎。 非常感谢。

https://patreon.com/mxcl

第二部分

云平台的选择。