Serverless 简介

随着 PaaS、BaaS、SaaS 的流行,服务端开发和维护的工作变得更加便捷,大部分创业公司不再需要专职的运维,服务端开发人员即能搞定日常的服务器维护工作。而近几年,像 Parse、Firebase、CloudKit 这类连服务端开发人员都能省掉的方案更是受到不少创业公司的青睐。做一个 App 不再需要一堆人,试错的成本大大降低。 而各种容器技术的不断进步,利用譬如 Docker 容器实现轻量级的服务器单元,一个新的服务端形态正在成形 —— Serverless,或称 FaaS (Functions as a Service)。下面从我个人的观感随便聊一下我理解的 Serverless。 Serverless 主要应用表现为,功能以 function 为最小的单元,用户访问某个 function 时启动一个容器执行 function 内的程序,执行结束回收这个容器,整个过程快至几个毫秒就能完成。在某些应用场景下,能很好的代替持续在线的服务。 目前最具代表性的 Serverless 解决方案当属亚马逊的 AWS Lambda,中小型的服务商如 Webtask、hyper.sh 等,Google Cloud Platform 也正在进行 Cloud Function 的内测。 这些服务有类似的收费政策:按需付费,额度内免费,超额后每次请求计费。 目前我了解到的使用场景不多,从 AWS Lambda 提供的各种介绍来看,我脑补一下 Serverless 适用场景: 运算密集 —— 如图片压缩、数据分析。因为使用 Serverless 方案同一秒里可以运行千上万个 Lambda,能轻易实现传统架构无法实现的超强处理能力,并且只在使用时收费。 为其它服务提供编程支持 —— 例如,当 AWS DynamoDB 数据发生变化时,调用 AWS Lambda 生成 PDF 报表。再如,为 AWS API Gateway 提供自定义权限验证脚本。 定时任务 —— 以往使用 cron 编写的定时任务可以改用 AWS Lambda 实现,很明显的好处是任务不执行的时候完全不收费。 »

Author image Lex Tang

为什么改用 Carthage

在这个几乎每一个开源 iOS 第三方组件都支持 CocoaPods 的时代,为什么要选择另一个组件支持数量少、项目配置相对繁琐、无法直接查看组件源码的包管理工具呢? Carthage 到底好在哪呢? 最初看到 Carthage 第一眼就被「去中心化」这个高大上的名词给吓到了,但是它并不是个很复杂的事。在项目中,原来我们把一个组件做成 Pod,需要写 Podspec,用 development pod 或者更新 Specs 仓库的项目,私有组件还要更新、指定自己的 Specs 源。 最早 CocoaPods 还没有流行的时候,我曾是 CocoaPods/Specs 仓库的主要贡献者之一。当时第三方组件默认的安装方式就是拖拽和 git submodule,CocoaPods 为了推广自己,有一个建议第三方仓库支持 CocoaPods 的文字模板,以 issue 的形式发到对方的仓库里。让仓库拥有者辛辛苦苦地写一个 podspec,还要更新 README 一般都要等上好几天,而且很难一次就做对。所以最好都是帮对方写好 podspec,改好 README,发 Pull Request,再代为更新 CocoaPods/Specs 仓库,非常费事费力。 而组件支持 Carthage 的唯一要求就是,项目的里有一个 shared Framework target 存在。每次更新组件都不需要去更新任何 Podspec 或 Specs 仓库。私有仓库不需要额外设置 Specs 仓库,不需要 pod trunk。去中心化,意义非凡。 另一个 Carthage 的设计优势是,先天只支持 Dynamic Framework,只在更新时编译,这是为 Swift 项目量身定制的特性。在发版本时不需编译所有依赖,在项目 clean 时不需要重新编译所有依赖,开发者只有在用 carthage update 更新组件后才需要重新编译组件,而且一般只做一次。 另外组件作者可以进一步提供编译好的 Framework 压缩包,随 release 发布,节省使用者的编译时间。试想如果项目中的每一个依赖都这么做了,carthage update 会像 apt-get 一样又快又好用。 »

Author image Lex Tang

我的 Linux 一万小时

这不是一篇鸡汤文,因为我并没有在使用 Linux 一万小时后成为 Linux 达人,甚至在很多方面,我连新手都算不上。我走的这些弯路能篇成一本很有参考价值的反面教材,下面,我来讲讲我用 Linux 都折腾了啥。 Gentoo 在 Ubuntu 还没有出生的年代,各种发行版百花齐放。以包管理机制区分的话,可以分为两派:直接安装二进制可执行文件的和下载源码自行编译的,Gentoo 算是后者中一个比较知名的项目。为了使硬件发挥出更好的性能,Gentoo 的 emerge 命令提供了不少编译参数让用户调教。从内核到日常用的所有工具,都需要用包管理工具自动下载源码后编译,这对于像我这样的 Linux 新人来说的确能被动学习不少知识。而且每次编译满屏幕日志飞滚非常酷,改用绿色文字就有种黑客帝国的即视感。 不过,这个机制有个显而易见的缺点,有时候做一些很小的事情都需要花上好长时间编译大量的依赖包。而像我这样的强迫症,总觉得下一次编译换一个参数也许可以使程序运行得更快,以至于很多常用工具我都编译了不下三遍。另外编译内核和格式化硬盘重装 Gentoo 的事真是数也数不清了。最惨的是,有次同事让我帮忙装一台 1U,他用 Debian 可以分分钟把 LAMP 搞定上架,而我硬是想用 Gentoo 压榨性能。我编译了一个下午,反复编译内核浪费了大量时间没能把两块网卡搞定,最后无奈的让他上了 Debian。 Gentoo 给我的教训是,大量零散的编译调优时间累积在一起会消耗很多宝贵的青春和电费,它们带来的收益微乎其微,不如直接买更好的硬件。选一个有成熟包管理机制,社区活跃的发行版能节省大把精力把真正要做的事做好。这也是后来我只用 Debian 的一个主要原因。 桌面美化,WM 曾经每天看 DistroWatch.com,除了了解各种发行版的动向,还希望看到一个界面更加美观的发行版,因为感觉大部分发行版的开发者审美太非主流。我用了很长时间尚且还看得过去的 XFCE 和 FVWM-Crystal,也用过臃肿浮夸的 KDE 和 Gnome。试了不少布局和配置,下载过很多 GTK 皮肤和图标库,玩过酷炫的 Compiz,调教过中文字体的显示效果。但不管怎么改都感觉哪儿不完美,直到后来接触到同事 Apple iBook G4 上的 Mac 系统,便掉进了在 Linux 上模仿 Mac 系统界面的深渊。这个 Flickr 相册 里有不少那些年的痕迹。 这同样是一件没有什么收益的事情,2006 年后我放弃治疗,改用 Mac 系统。 wine 周围的人问我为什么不用 Windows 这种主流的操作系统,倒喜欢用小众的操作系统的时候,我都只是一笑而过,后来我用 Mac 的时候也常常遇到这样的问题。有意思的是,现在这个问题在大部分互联网公司里变成了:『为什么你不用 Mac?』 我一开始用 Linux 作为开发主力机的确发现有诸多不便。比如同事给我发个 Microsoft Office 生成的文件;比如做网页要在 Internet Explorer 里调试;比如要上 QQ。不过我并没有感觉到 Linux 不主流,有很多在线论坛有大量热心的 Linux 用户能帮你解决各种技术问题。而同一时期那些 Windows 相关的社区全在共享盗版软件。 »

Author image Lex Tang

Android 开发从入门到放弃

谁都不是生来就是 Android 黑啊,我也不例外。 我曾抱着成为移动端全能的梦想,决心补上 Android 开发这块短板,收集了不少 Android 开发的资源,花了几十分钟下载 SDK,信心满满地编译 Hello World。然后,对着屏幕看了十分钟不止才看到结果。Google 的文档可不会告诉你直接插 USB 真机测试会快很多啊,也没有说推荐用友商的 GenyMotion,当时我的心是凉的。 后来为了有愉快的开发体验,搞了台当时算速度不错的 SONY Xperia Z1 防水手机,一心想做个适合在水里用的 Android App。一个人脑暴了很久,想了很多不靠谱的 idea,终因忙 iOS 项目,没有一个做出来。 不过在使用 SONY Xperia Z1 的过程中,我发现有些我在 Motorola XT301 上遇到过的问题在这几年里并没有改善。 比如说,市场混乱。你会发现几乎每个手机厂家都喜欢出自己的 App 市场,并且自带的 ROM 不带 Google Play。甚至于某些和运营商合作的手机,会自带两个市场。再加上一些被公认做得还不错的既不是手机厂也不是运营商的市场,XXX 手机卫士,一台 Android 手机带数个市场算是很正常的事。这些市场并没有哪个处于绝对的垄断地位。虽说竞争是好事,但这种鱼龙混杂的场面,让用户在选择时有些许迷茫。同时,开发人员发布 apk 也是件很累的事。所以有人做了 Android 多渠道打包工具,还有些提供代发布的服务如 酷传 等。而这些市场中,有很多一看就是垃圾的应用,居然通过了市场的审核发布了。我曾经搜索「招商银行」找到五个长得差不多的 Android App,看到过大量审美超出普通人接受范围的 Android App,下载到不少安装时问你要几乎所有权限的 Android App。 二是,界面设计、交互体验没有统一的范式,大部分 App,需要有个「用熟」的过程。各家都在培养自家 App 的用户习惯,但好在他们之间会时不时地互相取长一下,某些交互趋同,某些则向 iOS 看齐。即便后来有了 Material Design,市场中界面美观、交互优雅附合新用户预期的 App 依旧还是少数。另外,可笑的是,系统皮肤的排行里,仿 iOS 的皮肤总能在前十中占上三四个位置。 再说硬件,除非你用亲儿子,或者一些比较开放的友商的手机,不然你想刷官方 ROM 是一件很难的事。这看起来并不是什么坏事,直到 Android 6. »

Author image Lex Tang

两周 React Native 开发小结

将原有的 Swift 代码改成 React Native 是个不小的动作,我们选择了一些对主要功能影响不大的页面定点重构,主要考虑到 React Native 的几个优点: 跳过 App Store 审核,远程更新代码,提高迭代频率和效率; 减少编译时间,开发效率更高; 组件化开发,更高的复用率; 相对其它 Hybrid 方案,React Native 性能更好,用户体验更接近原生。 经过我一个人两周的折腾,发现这些优势并不能在我们的 App 里最大化。最后我把所有 React Native 写的代码全部删除,花了两天时间用 Swift 重写了一遍。 下面,我来聊聊为什么我们的 App 没能享受这些优势。 迭代频率和效率 为了更好地发布版本,我使用了 react-native-auto-updater,这是一个比较成熟的更新方案。我把 jsbundle 放在 AWS S3 上,每次发布更新 metadata.json。用户启动 App 时检查是否有适合当前 App 版本的新 jsbundle,如果有,则偷偷地更新,并在下一次启动时使用新版。我们用的这个算是比较保守的更新策略,缺点是用户不能第一时间用上新版,好处是不会因为在使用中更新而产生副作用。 虽然不再经过 App Store 慢长的审核(平均一周),但是新的版本也要测试吧,也要有个发布的周期吧,在只有我一个人写 jsx 的情况下,发布周期控制在几天内合适呢?我能很快地更新一个页面,修正某个逻辑错误,但是,首先,我们用 JSPatch | WAX | Rollout 等方案也能(但相对略费力地)达到这个目的;其次,我们做的不是电商,并没有这样频繁的更新需求。 减少编译时间,开发效率更高 几乎可以略过不计的编译时间的确能诱惑大部分被 Swift 慢长的编译时间摧残过的灵魂。Live Reload 功能让你在每次保存后都能立刻看到更新后的页面。0.23.0 新增的 Hot Reload 功能可以在不刷新页面的情况下看到更新后的结果。但其实编译在整个开发过程中只占很小的比例,尤其是对于小 App 来说。更何况,现在可以用 InjectionForXcode 在运行时注入更新的代码,可以用 Stevia 实现 Hot Reload 布局。再者,有 FLEX 和 Reveal 等调试工具可以辅助开发,新版本 Xcode 编译 Swift 也越来越快(不是幻觉吧),Swift 写的 Playground 开始支持用户交互,所以我并不觉得 React Native 在这一项上占有绝对优势。 »

Author image Lex Tang

Hello world

我总是能很快地学会一门技术、一项手艺,并通过它们收获经验。 如果它们是我喜欢的事,在持续不断地收获经验后,我成为这个领域的熟练工。 我没能成为专家是因为,我没有在这个过程中思考并洞见整个领域的发展规律,以及这些技能的共性。 写作是一种很好的思考方式,我想通过这个站点来总结这些共性,分享我的想法,并利用好这个简短的域名。 »

Author image Lex Tang