昨天,我正式发布了奇点 2.6 版本,这个版本共历经 7 次拒绝打回审核的过程,可谓历经磨难。我也发觉我很久未写我的开发故事了,那么就择日不如撞日,写一篇背后的故事吧。

奇点 2.6 版本带来一个很特殊的功能,那就是「奇点推送」。没错,就是给奇点增加即时的消息推送的支持。除此之外,该「推送」还有一个功能,就是远程触发后台刷新,因而可以在不频繁使用奇点的情况下,也能保证不错过微博内容。结合奇点的「订阅」功能,真正做到了一个微博阅读器的工具。

开发动机

说起为什么要做这个功能,一个直接的原因当然是自己想要这个功能,其次可以作为一个很好的卖点,也算是奇点原先功能的一个拓展。

用过奇点的朋友都知道,它有一个「订阅」功能,也就是将未读微博按人或分组的形式排列,当积累了很多微博时,可以方便地只选择想看的人而点进去看。这样即使时间线被各种信息刷屏,也能找到自己想要看的对象。

然而这项功能需要用户不断去获取最新的微博,或者由系统触发后台刷新来获取微博,一旦消息流中断了,「订阅」也就有点名不其实了。

因此我心里埋下了要把这个功能做完美的想法。

开发初期

这个想法冒出来后,最初的 demo 在 2016 年 9 月 14 日就完成了,几乎整整半年多前…当时我用 Django + Crontab 自建了一个推送服务,完成了一个简单的远端服务器检测有没有新微博的功能,然后在 iOS 端处理远程发过来的「content-available」的推送,就这样完成了一个极简的只为后台获取新微博的功能,并在当日也给用户发了 TestFlight。

TestFlight 的用户应该知道,这个功能确实就是这么早就开始测试了,但是因为后来忙着其他事,也在同时实现其他新特性,这个静默推送功能没有机会进一步去打磨,因而之后的新版本临时上线前都是把推送功能隐藏掉,然后再正式发布的。

后来在测试中,也发现这个简陋的功能还有很多缺陷,Django + Crontab 的实现太简单粗暴,一是并行效率不高,二是进程时常僵死,有一次还把我的 Server 的内存弄爆了。无暇顾及的我只好暂时把这个功能给关掉了一阵子。

于是该功能的开发进入暂停期…现在我想想,为何我要完全自建该服务而不用第三方推送?应该也是因为自建成本更低,第三方接入反而麻烦的问题吧。

开发后期

后续的日子,虽然该功能的开发几乎暂停,但是脑子里基本上还是想着这件事情。后来在学习其他东西的时候,想到可以尝试玩玩「微服务」这个概念,顺便学个新语言之类的。于是就想到了用 Django 通过 RabbitMQ 来向微服务发异步消息,这样把耗时的操作和推送都放在 Web Server 无关的进程里,保证 Web Server 稳定运行,并实现相关独立业务的剥离。

后来我就用 Celery 架起了基于 RabbitMQ 的服务,并且用 Node.js (node-apns)完成了一个可以保持长连接的推送服务。就这样淘汰掉了之前简单粗暴的 Crontab 模式,构架上有了一个进步。

我又开始实现相关特性,除了静默推送以外,开始弄评论/转发的推送,功能渐渐补齐了。此时已到三月。

然而这段时间我的技术宅能量完全爆发了。用 Node.js 写完这个推送微服务后,我还不满意,这段时间恰好在接触 Golang,我一边如饥似渴地看各种 Golang 的资料,一边想着不如用 Golang 重写这个微服务吧。

作为已经长期使用编译型语言的人,看到 Golang 这种严格到几近无理的语言天然有好感(import 的东西、声明的变量不用居然是 error),而且那段时间我被 Swift 的编译慢折腾的不轻,迫切需要换个环境来调节一下心情。于是一边基于 VisualStudio Code 搭起来 Golang 的开发环境,一边很快地就用 Golang 重写了之前用 Node 写的那个微服务,同样基于 RabbitMQ 来接受异步消息和处理消息推送。

就这样,我从 Node.js 折腾到 Golang,对为了写这么一个几百行代码的微服务,也算入门了 Golang,甚为满意。接下去,就是正式向用户推出这荐服务了,等待我的,是 Apple…

历经磨难的审核

奇点原生就是一个免费+ IAP 的 App,用户可以免费试用,有些特殊功能则需要购买完整版本才能用。我以为推出一个订阅式收费的功能,也是这么简单,哪知我太天真了。

「订阅式内购」和「一次性内购」是完全不同的东西,Apple 对此的严格程度也完全不同,它对「订阅式内购」的各项规则要求之严格,让我对 Apple 这家公司有了新的看法——当然是好的方面。

Apple 不仅会对你的业务范围进行检查,它觉得不行的,就会拒绝。如果觉得经营业务可以,接下来它会从 Privacy Policy 和 Terms of Use 这两方面来刁难你:简单地说,它要求你必须将经营的业务的条款详详细细地列举出来告之用户,包括明确告之用户收费价格和时长、明确告之用户试用期、明确告之用户试用期后会自动扣款、明确告之用户自动续费的概念以及如何取消自动续费……

刚开始我偷懒,只起草了一个 Privacy Policy。Apple 打回说 metadata 信息不足。后来我又补上 Terms of Use,还把这两个东西放在最显眼的地方……就这样一来一回共七次,Apple 终于于昨天给我放开,我觉得,再拒一回,我就要崩溃了…

事后我认为,Apple 这样做也是应该的,用户确实必须得明确被告之该服务的方方面面,毕竟这不是一次性消费。就这样,我起草了 Privacy Policy 和 Terms of Use,通过了 Apple 的审核,终于将这个难产的功能推给了用户…

后记

写到这里,离 2.6 正式推出已经快 24 小时了。我简单统计了一下,已经有近 100 位用户购买了该推送服务,不多,但是足够我每月服务器的开销啦。但是前提是七天试用期后用户还满意。按付出的开发成本来说,应该是很难收回了😂

不过,学了很多新东西,学习并成功实践了新语言(Node、Golang),并且用它实现了一个用户满意的服务,这收获是不可计量的。

想体验的朋友可以下载奇点:App Store

放一张截图: