全球区块链监管查询平台

简体中文
下载WikiBit

氧化海妖

海妖交易所

相关类型: 其它

2021-02-20 01:31

Simon Chemouil –核心后端工程总监 两年多来, Kraken的Core Backend团队一直使用Rust来使最初用PHP编写的服务现代化,同时构建新产品,扩展功能集并支持加密货币交易活动的不断增长。 嗨?!我是Kraken的工程总监Simon,领导核心后端团队。我想回顾一下Core Backend团队在最近两年中对Rust的使用情况,并与我们一起大规模地分享我们的观点。有许多很棒的在线资源介绍了Rust的不同之处以及为什么它是一门伟大的语言。但是,这不是这样的博客文章。我们希望本文将对考虑使用Rust进行开发的公司以及想要投入时间来学习该语言的开发人员有所帮助。最后,这也非常感谢所有帮助使Rust成为可能的人,也是Kraken为这一运动做出积极贡献的一种方式。 重写核心服务 通常,从头开始构建解决方案来替代一个问题会给我们带来另一个问题。当原始开发人员不参与新解决方案的设计和实现时,这种情况尤其常见。有时,新的解决方案从理论上讲会更好,但是要准备好太多的时间,这会减慢主动服务请求的系统的进度。尽管我们可以确保避免这些常见的陷阱,但是首先挑战进行重写的需求非常重要。 Kraken于2011年成立时,PHP提供了执行安全性,速度和生产率的完美结合。令人印象深刻的是在早期建立了多少功能。但是,从那以后,Kraken取得了长足的发展,并且很难扩展PHP代码库,共享专有技术并安全地进行较大的更改。这些核心服务处理分布式数据存储,加密和信息安全性方面的考虑,这在PHP开发人员中不太可能是常见的技能,而PHP开发人员通常更专注于在现有Web和电子商务框架上进行构建。 更普遍的是,Kraken进入了高速增长的阶段,在此阶段,代码库和工具都需要跟上发展。在这方面,动态类型的编程语言非常适合开始构建,但是随着代码库和工程师人数的增加,维护代码变得更加困难。强类型提供了保证(和正式文档),这些保证使快速开发和更多开发人员可以在单个代码库上工作。 我们重写核心服务的主要目标是: 1. 保持系统尽可能安全 2. 即使系统变得越来越大,也使系统更具可维护性和鲁棒性, 3. 允许更好的性能。 早在2018年就已经意识到,保留PHP并不是实现这些目标的最佳长期解决方案。为什么生锈? 2018年初,Kraken已经提供了用Go和C ++编写的生产服务。尽管Rust保证了性能,安全性和现代语言的结构,但将其作为重写核心服务的语言是一个赌注。 Kraken非常注重安全性。因此,我们不想让C ++代码针对用户输入运行。即使是世界上最好的C ++团队(例如构建Windows™或Chrome™的团队),也会在代码中产生约70%的CVE是由于内存安全性问题而产生的-诸如释放后使用,缓冲区溢出,两次释放,这可能会导致特权Java,Go或Rust等语言完全禁止升级或访问内存。 尽管Go可以防御此类特定的漏洞,但它没有提供诸如通用或求和类型之类的现代编程功能,这些功能最终会导致数据建模问题或重复。 Kotlin提供了一个更复杂的类型系统,并且像Go一样,它使异步编程相对容易,但是带有一个带有许多遗留物的Java生态系统。 输入Rust。它的可靠性和性能使其在加密货币和区块链项目中取得了成功。一些Kraken工程师开始进行试验,并视其为构建满足Kraken后端需求的持久系统的机会:类似于C ++的性能,现代语言构造有助于准确地建模业务逻辑和错误情况,计划的对异步编程的一流支持,编译时线程安全和充满活力的生态系统。 Rust的价值主张和社区取得的成功使Kraken开始在2018年中开始重写Rust的核心服务。两年后 Core Backend团队已经成长,如今负责现代的Rust核心服务和仍在重写的遗留PHP服务。同时,Rust已被其他团队成功使用:Kraken Futures团队加入了我们的行列,该团队独立地开始将其所有后端堆栈迁移到Rust, Cryptowatch选择了Rust作为其桌面应用程序,Kraken迁移了其Rust的冷库系统,Rust正在建立Kraken Digital Asset Bank 。该语言本身已得到显着改进,从而使编写异步网络服务比以往更加容易。 总的来说,我们一直很忙:Core Backend团队的Rust git存储库保存了约500,000行代码-比PHP多,即使许多功能仍在PHP中实现。这部分是由于编写了更多的基础代码,测试和全新功能,而且还因为PHP与其他动态类型化的编程语言一样,不需要键入结构定义(包括错误),而该结构定义弥补了错误的大部分。 Rust代码。在PHP中没有那些显式的结构使得重写几乎是逆向工程中的一种练习。 从策略上讲,我们决定重写Rust中完全相同的功能:由于所有PHP服务都是无状态的,因此可以轻松地将逻辑(逐个端点)移植到Rust。这样一来,新聘的团队就可以获得有关底层系统的更多知识,并可以进行增量部署以及轻松回滚。我们已经构建了一个全面的集成测试套件,该套件需要针对PHP和Rust服务进行传递,以确保行为相似。将功能移植到Rust后,可以更轻松,更安全地进行扩展。 尽管重写的主要目标不是性能,但很高兴看到Rust提供开箱即用的惊人速度。我们的Tokio驱动的RPC服务器并未进行特别优化(尽管我们通常对内存使用模式非常谨慎),每个实例支持150k请求/秒的吞吐量,同时将p99.9延迟保持在3ms以下。系统的运行速度与其最慢的部分一样快,尽管我们的PHP核心服务不是Kraken的唯一瓶颈,但它们的IO性能低于Rust的性能,并且对负载更敏感。在将整个端到端路径迁移到Rust并消除瓶颈之后,我们的客户应该会看到巨大的进步。同时,我们通过将端点移至Rust,重新设计数据库和扩展服务来尽一切努力来提高性能和可靠性。 这是将端点移植到Rust时响应时间的变化应用程序服务的Rust Rust通常被吹捧为一种出色的系统编程语言,非常适合于低级任务,命令行实用程序和网络服务(例如负载平衡器)。许多人认为Rust的复杂性对于常规业务逻辑而言是一笔交易的破坏者,而工作市场池太小,无法使用该语言来完成诸如构建用户管理系统或REST API之类的常见任务。 虽然锈病是编程中,我们也一直在使用它对于在考虑更高层次的如Java,Ruby或打字稿语言通常实现的应用服务系统非常适合。正确性在Kraken中绝对至关重要,Rust的现代语言结构使编写正确,健壮的代码变得更加容易。缺少垃圾收集通常在编写不需要“关心”内存管理的通用逻辑时被认为是一个弊端,实际上这并不是问题,因为我们正在构建无状态服务,而存储循环数据从来都不是问题。 。 但是,Rust需要精度,我想说这是该语言最有益的方面:它的显式性(受其强大的类型系统支持)导致表达性代码易于查看且运行时可靠。在这方面,我认为Rust比Java和相同类别的其他语言低层次和高层次。 Core Backend团队还开发了一些其他技术服务,例如负载平衡器或服务监视流,它们需要良好的性能,并且非常实用,不必在系统和应用程序逻辑语言之间进行切换,也不必重用库和模式。 随着团队和代码库的增长,有效审查代码的能力至关重要。 Rust出色地表现出使行为孤立地表现得非常明显,这意味着无需过多考虑系统的其他部分-当前功能通常就足够了。在检查代码时,我们会看到一个差异(已更改的行和周围的上下文),虽然可能需要更多时间来深入研究更改,但是对于可以迅速获得反馈的开发人员而言,更快的审阅是一个很大的动力。在Rust中,可以肯定的是,编译后的更改将没有数据争用(并发错误的一个显着根本原因)和内存安全(我们在大部分时间都保留在Rust上)。我可以很容易地发现可能导致恐慌的函数‒在没有其他选择的情况下,Rust会中止执行的方式‒,发现无用的内存副本,并且通常会收集开发人员的意图。 Rust的linter夹Clippy有助于统一代码样式,并导致更加惯用的,一致的代码库。与过去使用任何其他主流编程语言相比,最近两年来,我以极大的信心审查了数千个合并请求。 Rust是一种复杂的大型语言,很容易在细节上迷失方向。幸运的是,没有必要知道所有的细节以提高效率。根据我们的经验,Rust是一种非常有生产力的语言:它具有出色的工具,可以迫使我们彻底建模问题,节省宝贵的调试时间和潜在的生产问题,并且对于代码重用(生产力乘数)非常有用。最后,我觉得有必要揭穿“与借阅检查器打交道”的传奇,这是一个将Rust编译器描述为布尔客的故事:以我的经验,它主要发生在初学者和1%试图对代码进行微优化或推送的人。边界。大多数有经验的Rust开发人员确切地知道如何以一种不会浪费时间在编译器上解决设计问题的方式来建模代码,并且一眼就能发现反模式,就像大多数人都知道如何正确地驾驶汽车一样避免事故发生,注意那些没有的人!建立一个Rust团队 在这两年中,我们已经建立了现代Kraken后端堆栈的基础,将现有功能重写为Rust,建立了新的Rust服务和功能,还建立了由30多名工程师组成的Core Backend团队。最初,一些开发人员被聘为PHP开发人员,并在加入团队时学到了Rust。值得一提的是,Kraken是一家全球分布的远程第一公司,Core Backend团队拥有来自12个国家的15个国家的工程师。 Rust吸引了热情的开发人员,他们通常对系统编程,分布式系统或密码学感兴趣。我们目前的Core Backend工程师中有很大一部分是Rust爱好者,他们通过各种Rust在线资源发现了机会,从Reddit到This Week in Rust ,我们的工作机会被多次推荐(谢谢!),这使Kraken在招聘方面颇有名气Rust开发人员已经有很长时间了。 我们的核心后端角色将竞争激烈的市场中充满挑战的技术和业务问题结合在一起,在世界各地进行远程工作,并提供与位置无关的高额基本报酬和慷慨的选择权,并几乎全职撰写Rust 。对于申请了这两年的许多候选人并没有失去这一事实,这使得组建世界一流的工程团队成为可能。 尽管我们最初是对感兴趣的招聘开发人员开放,但对Rust并没有实际经验,但我们很快意识到它并不总是很成功,学习曲线取决于个人。有趣的是,Rust吸引了来自非常不同的静态和动态类型语言的开发人员。很难说那些来自特定背景的人是否有较难的学习曲线,但有些人会在几周内变得有效,而另一些人在几个月后仍会挣扎。那些习惯于依赖文档并且对语义学有正式理解的人最有可能赶上。像许多快速发展的公司一样,我们需要新员工才能在实际问题上立即提供帮助。因此,我们需要可证明的Rust经验,并且需要进行测试以全面了解Rust的类型系统以及标准库和普通包装箱的实践知识。 我相信使用Rust可以帮助人们成为更好的开发人员,因为它推动了简洁的设计和精度。但是,仅了解Rust并不能使他成为一名出色的工程师。我们看到的许多候选人对Rust都很满意,但是在构建后端系统方面经验有限。我们雇用了许多具有巨大潜力的初级开发人员,因为在组建团队时,平衡是成功的关键。经验丰富的开发人员通常是出色的导师:他们通常具有使事情简单的智慧,学会了不要过于信任自己,以及如何最大限度地发挥其对业务的影响。 考虑到该语言如何解决C ++,Java或Go的痛点,我希望有更多经验丰富的开发人员能有所作为。我来自Java开发十多年,我对过度炒作的新技术表示怀疑,但是我现在害怕回到一种与Rust的品质不符的语言-特别是它如何让我专注于手头的模块,而不是需要不断考虑许多隐式不变式,例如该代码段是否从另一个线程调用,以及我需要使其成为线程安全的事实。我们希望,随着越来越多的公司现在从Discord和Deliveroo到亚马逊和微软more在Rust上进行大量投资,我们可以帮助发出一个信号,表明Rust的工作很多,并且花时间学习这种语言不会浪费。许多经验丰富的开发人员更愿意留在他们作为专家的堆栈上,但是有些人可能仍然喜欢尝试摆脱自己的舒适区并挑战自己。锈是伟大的,不是完美的! Rust使我们能够构建许多运行良好的高性能生产代码。我们有一个庞大的团队,其中许多人在后端的非常不同的部分上工作。大多数代码都非常健壮:我们还没有经历过Rust核心服务的一次崩溃或恐慌(大致相当于运行时异常)。总而言之,我可以说我们仅遇到业务逻辑问题,配置错误问题,并且遇到了与在Musl libc上运行Tokio以及特定内核配置有关的一般性能问题,一旦使用perf工具确定了该问题,就可以轻松修复该问题。 虽然语言很棒,但也有一些被广泛认为是局限性的事情也困扰着我们。 - 理想情况下,每个易错函数都具有自己的错误枚举,以精确捕获其错误并进行处理,但实际上,它过于冗长,导致使用不太精确的错误特征或每个模块使用一个枚举。该语言可以更好地支持这一点:有许多倡议和宏对此进行了探索。 - 在设计库箱时,缺乏专业化和通用关联类型(GAT)可能会受到很大限制。 我们首先将Future Rust组合器与async Rust配合使用,并在每晚降落时使用async / await支持。这是一项非凡的功能,它使我们能够使用Tokio构建大规模的并发应用程序。我们从不需要花费很多时间来使我们的服务器处理超过10K的并发连接或实施背压。但是,它仍然可以变得更好: - 与Rust的大多数部分不同,异步函数看起来有点像常规函数,但是它们可能不会完全执行(更确切地说,它们返回的Future可能不会被轮询完成) ,因为它们看上去与常规函数无害。这需要格外小心,以处理清理逻辑,清理逻辑目前本身不能异步进行。正在进行的支持异步删除的工作有望提供一部分解决方案。关于如何使问题更加明显仍是一个悬而未决的问题。属性可以清楚地表明Future是否可以取消,而棉绒警告会告诉我们吗? - 尽管情况越来越好,但异步框架的分裂已严重损害了生态系统。该语言将从提供的结构中受益匪浅,该结构将使任务调度子系统抽象而无需额外开销,因此人们可以选择使用自己喜欢的执行程序,并将任务执行程序传递给库,或者自行驱动Future 。 - 当前静态初始化的任务执行器的设计使得通过简单地拉出依赖关系而容易地错误地运行多个执行器。线程局部变量的普遍使用使调试更加困难。 - 能够在特征中设计异步函数而无需装箱,并能够引用结果类型,这绝对是对性能敏感的代码的一项重大改进。 - 我们也希望看到围绕ioing的工作有望带来巨大的性能改进,而又不会造成生态系统的进一步分裂。 在工具方面,Cargo和Rustup使得设置和编译项目变得无关紧要。 RustAnalyzer进行了惊人的改进,并提供了很棒的IDE体验,并且会变得更好。编译时间通常会减少:它们可能会更短,但是使用增量构建和sccache不会花费太多时间。优化的构建确实速度很慢,但是总体来说要付出很小的代价才能获得性能和安全性。具有许可支持的私人货运登记处一定会对Rust在企业中有所帮助。我们一直在使用git依赖项运行,但是缺少语义版本支持使更新很痛苦。那里有一些开源的Cargo注册中心,但是Cargo本身不支持访问令牌或凭证。我们很乐意赞助这项工作。海妖❤️锈病 考虑到所有因素,Rust非常成熟,并且大多数痛点会以其他主流语言的一种或另一种形式存在。 Rust使重用变得微不足道,并允许我们在主动开发下安全地处理大型代码库,而又不牺牲性能。 对我们而言,使用Rust不再是实验或赌注。这是我们正在建立的可靠技术,Core Backend团队正在寻求工程师的帮助。如果不提及Rust之外的团队价值观,这张照片是不完整的:Core Backend团队利用Rust的工程价值和受Netflix影响的高性能团队文化,扩展了Kraken的文化‒以及对我们使命的承诺。我们相信超越代码的工程,拥有所有权。我们拒绝傲慢自大。我们不断相互学习。不共享办公室将使我们面临的挑战更加严峻,而蓬勃发展的个人则是工程师,他们能够自我驱动,技术精湛,能够在需求和技术解决方案之间架起桥梁,从而能够自主前进。我们将聪明和努力的工作结合在一起,但保持了良好的工作与生活平衡并保持健康。我们关心他们正在建设什么,并帮助他们的队友取得成功。我们认识到完美是善的敌人(众所周知,铁锈开发人员是完美主义者!?)。最后,我们相信团队会不断自我完善:如果技术或组织方面出现问题,我们会予以解决。 我们在核心后端团队中为中级和高级后端工程师以及站点可靠性工程师提供了空缺,这些人员可帮助支持和改善我们的运营,工具和CI。我们还将聘请处于测试阶段的软件工程师来帮助我们使用Rust和Cucumber测试我们的API。 Kraken的其他团队也一直在寻找优秀的工程师,他们选择Rust作为其构建强大和响应系统的首选工具: - Kraken Digital Asset Bank是一家特殊用途的托管机构,可以在Rust中建立现代银行和支付系统,并正在寻找高级工程师; - Kraken期货团队两年来一直使用Rust作为主要语言来建立衍生品交易,来自Java和Kotlin,他们正在寻找后端工程师; - 我们的交易技术团队在建立现货交易的同时,还使用C ++和Rust运行大量服务,并正在招聘后端工程师; - 当Cryptowatch构建轻量级的桌面交易应用程序时,他们也在雇用Rust GUI开发人员。 - 请务必检查我们的其他开口! 最后,我们想帮助Rust成长。我们已经通过Kraken Grants计划赞助了一些开放源代码的工作,例如冰镇的GUI框架。我们很乐意赞助Rust项目或关键相关项目的个人贡献者。如果您正在为Rust生态系统做出重要贡献并需要资金,请联系!同时, RustAnalyzer团队所做的出色工作给我们留下了深刻的印象,这些工作直接使整个社区受益,并将为该项目捐款5万欧元! 分享这个: - 推特 - Facebook - 像这样:喜欢加载...