1Password工程副总裁:Rust用起来真香

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"本文最初发布于serokell.io网站,经网站授权由InfoQ中文站翻译并分享。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Rust已经席卷了编程语言世界。自2015年发布1.0版以来,它一直是最受欢迎的编程语言之一,且赢得了众多忠实的开发人员和贡献者。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"为什么那么多开发者喜欢Rust?本文试图回答这个问题。我们采访了1Password工程副总裁Michael Fey。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/5d\/5d4c899825183f185a88d76e16583e7f.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题1:能否介绍一下你所在的公司和担任的角色?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:1Password是一个密码管理器,获得数百万用户和70000家企业的信任,被用来保护他们的敏感数据。它会记住你所有的密码,这样你就不用费劲记下它们了。它提供了适用于所有主要浏览器、桌面和移动设备的应用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我是1Password客户端应用工程副总裁。如果你在Mac、Windows PC、iPhone、iPad、Android手机或平板电脑,或在浏览器中使用1Password,那么你使用的就是我们团队开发的产品。我们的故事从2004年一直延续至今,我们为构建精心设计的体验并确保人们的线上安全性而感到自豪。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题2:能谈谈1Password的技术栈吗?你们代码库有多少是用Rust编写的?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:过去几年,我们一直在1Password的生产环境中使用Rust。我们的Windows团队是这项工作的先行者,现在的Windows版1Password 7大约70%的代码是用Rust编写的。我们还在2019年底将1Password Brain(驱动我们浏览器填充逻辑的引擎)从Go移植到Rust,这样我们就能在我们的浏览器扩展中利用将Rust部署到WebAssembly的速度和性能优势。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这些代码已经投入生产环境有几年时间,我们取得巨大成功。工作非常顺利,所以我们现在几乎完全重写了整个产品阵容,而Rust是这个故事中的关键部分。我们正使用Rust创建一个无头的1Password应用,其中包含所有业务逻辑、加密、数据库访问、服务器通信,以及包装在我们的目标部署系统的一个原生UI层中的更多内容。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题3:将Rust用于1Password的决策是否考虑到Rust的优势?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:最初吸引我们进入Rust世界的主要因素之一是内存安全性;得知Rust可以帮助我们尽可能提高对客户敏感信息安全性的信心后,我们当然感到非常兴奋。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了内存安全性外,Rust生态系统还有很多打动我们的优点。因为Rust没有传统的运行时,因此性能有了显著提升。例如,我们不必担心垃圾收集器的开销。Rust提供了一种“程序正确性”的形式,并提供了许多在运行时避免未定义行为的保证。它的强类型系统在编译时强制执行这些规则。只要精心在应用程序逻辑中融合Rust的强类型规则,API就很难被误用,代码也能得到简化,因为代码无需在运行时检查约束和不变项;Rust的编译器可以在程序执行前确保其没有无效的运行时代码路径,让你的程序不会误入歧途。需要做的运行时状态验证变少了,于是我们就可以生成更简洁、更高效、更专注和更高质量的代码。与其他语言相比,Rust需要的运行时调试很少。如果代码可以编译,开发人员就可以肯定它不会表现出意外的行为。它可能不是你想要的,但会是“正确的”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Rust另一个非常强大(却经常被忽略)的特性是它的宏流程系统,它让我们能够编写一种工具,可以自动与客户端语言(Swift、Kotlin和TypeScript)共享Rust中定义的类型。该工具的输出会自动处理序列化\/反序列化过程,这意味着我们的客户端开发人员在与Rust库交互时可以继续使用他们选择的语言工作,并且避免了通过外部函数接口(FFI)解析JSON的麻烦。我们获得了所有这些优势,同时享受了在我们每一种目标语言中做编译时类型检查的好处。我们也已将这款工具集成到我们的持续集成服务器中,这意味着对Rust模型的更改可能会导致客户端应用程序的编译失败,而这种失败会在我们的审核流程中被捕获。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"该工具已成为我们开发流程中不可或缺的组成部分,让我们获得前所未有的前进速度。一旦我们在Rust中定义了类型,就可以立即用客户端语言生成等效的类型。这让我们的开发人员可以专注于解决问题,而无需手动编写样板代码以通过FFI通信。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题4:在开发1Password这样以安全为中心的应用程序时,Rust提供的支持(库和其他方面)有多好?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:Rust生态有足够的能力来建立以安全为中心的应用程序所需的大部分基础。有两个大型的顶尖加密平台("},{"type":"link","attrs":{"href":"https:\/\/github.com\/briansmith\/ring?fileGuid=RwXKW63W3XhC3WcC","title":"","type":null},"content":[{"type":"text","text":"ring"}]},{"type":"text","text":"和"},{"type":"link","attrs":{"href":"https:\/\/github.com\/RustCrypto?fileGuid=RwXKW63W3XhC3WcC","title":"","type":null},"content":[{"type":"text","text":"Rust Crypto"}]},{"type":"text","text":"group),它们共同提供了丰富的功能选项。正如我上面提到的,使用Rust编写代码本身就可以让你对内存使用有更多信心,并且减少了向应用程序中意外引入与内存相关漏洞的机率。还有一个完善的系统可以跟踪不时出现在Rust板条箱中的漏洞:"},{"type":"link","attrs":{"href":"https:\/\/rustsec.org\/?fileGuid=RwXKW63W3XhC3WcC","title":"","type":null},"content":[{"type":"text","text":"RustSec"}]},{"type":"text","text":"数据库,该数据库由其他Rust开发人员在社区提供,并经常更新一些可在CI审核扫描中使用的新信息。Rust和Cargo还带有功能丰富的测试框架,为开发人员提供了一种简便的方法来编写单元测试套件,以确保关键代码(例如你编写的各种加密函数)的行为正确。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"尽管支持所有功能的安全的原生Rust库还是一个梦想(它们迟早会成为现实),但总有一种选项可以轻松地使用C或原生平台库中的某些东西。我们将其用于Rust代码中,以高效实现诸如调用生物识别解锁的原生实现(Touch ID、Face ID、Windows Hello)以及平台特定的设置实现(例如苹果平台上的NSUserDefaults)之类的功能。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题5:有哪些Rust库是你特别推荐的?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:Tokio、Hyper\/Reqwest、Ring和Neon都在1Password中拥有一席之地,它们对于这个雄心勃勃的项目而言至关重要。你还应该在crates.io上查看我们的"},{"type":"link","attrs":{"href":"https:\/\/crates.io\/crates\/password-rules-parser?fileGuid=RwXKW63W3XhC3WcC","title":"","type":null},"content":[{"type":"text","text":"password-rules-parser"}]},{"type":"text","text":",它基于一套主要由苹果支持的规范。它们的工具和文档可以在"},{"type":"link","attrs":{"href":"https:\/\/developer.apple.com\/password-rules\/?fileGuid=RwXKW63W3XhC3WcC","title":"","type":null},"content":[{"type":"text","text":"这里"}]},{"type":"text","text":"找到。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题6:Rust用起来有哪些明显的优势,在你们的技术栈中有哪些不足?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:当我们开始这个项目时,Rust已经实现了我们期望的90%。我们已经能以某种形式将其部署到几乎每个目标平台上(Apple Watch除外)。这种语言本身的设计颇具现代感,并且每次更新发布时都在不断改进。它有着出色的文档资料和活跃的社区。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"尽管有无数可用的板条箱,但我们确实需要推出自己的日志记录和跟踪工具,以确保它们在1Password中可以安全使用。此外,我们构建了一个实质上本地化的实现,以满足我们产品的需求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它确实在一个关键方面无法满足我们的要求:我们希望WebAssembly在浏览器和浏览器扩展方面能提供比现在更强大的能力。WebAssembly作为一个函数库来说非常出色,但尝试在WASM中支持整个运行时一直是一个挑战。但我们遇到的许多问题并不是Rust本身的局限,而是WebAssembly作为部署平台存在的局限。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题7:用Rust开发1Password时遇到的最大挑战是什么?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:我们团队中的许多人都是Rust新手,他们经历了内存管理和所有权模型的典型学习曲线。我们还发现编译时间比较漫长,我们的CPU和风扇经受了不小的考验。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题8:你们对结果感到满意吗?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:毫无疑问是满意的。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"问题9:有哪些重要的收获?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答:如果你不熟悉Rust,请从小处入手,并以此为基础逐渐推进。当我们开始尝试探索基于Rust的解决方案所能提供的优势时,我们做了大量实验。当你的实验顺利进行时,请尝试重新思考一下你以前使用其他语言时的工作方式,看一看你的代码是否可以从Rust的理念中受益。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文链接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"https:\/\/serokell.io\/blog\/rust-in-production-1password?fileGuid=RwXKW63W3XhC3WcC"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章