写点什么

Shopify 如何在浏览器之外使用 WebAssembly?

  • 2021-01-14
  • 本文字数:3888 字

    阅读完需:约 13 分钟

Shopify如何在浏览器之外使用WebAssembly?

Shopify 致力于让大多数商家都需要的功能变得简单易用,并通过接口在 Shopify 平台上执行查询、扩展和更改,进而为商家提供更多可能。借助这些接口,我们丰富的合作伙伴生态系统可以解决诸多问题。这一生态系统主要借助“App”(一个独立托管的 Web 服务)来运作。该 App 通过网络与 Shopify 进行通信。尽管这种模式很强大,但会带来一系列技术问题。我们的合作伙伴需要打造能够随 Shopify 规模扩展的 Web 服务,这让一些本就资源有限的合作伙伴越发捉襟见肘。即便合作伙伴有无限的资源,在与 Shopify 通信时产生的网络延迟也足以让我们的 App 在对时效性要求很高的用例中败下阵来。


我们希望我们的合作伙伴能够专注于利用他们的专长来解决问题,而不用花费时间管理可扩展的 Web 服务。为实现这一目标,我们保留了不受信任的合作伙伴代码的灵活性,并将其在我们的基础设施上运行。为了确保这些代码的性能、安全性与灵活性,我们选择了 WebAssembly 这种通用格式。

WebAssembly

什么是 WebAssembly?WebAssembly.org给出了如下定义:


”WebAssembly(缩写为 Wasm)是一种基于堆栈虚拟机的二进制指令格式。Wasm 是为编程语言设计的可移植编译目标,使客户端和服务器应用程序能够在 Web 上部署。“

 

如需详细了解 WebAssembly 及其历史,可以浏览由Mozilla的Lin Clark撰写的这篇图文并茂的文章。本文在此不做详述。


Wasm 通常都是与 JavaScript 一起在浏览器内运行,但 Shopify 却另辟蹊径,在浏览器之外运行 Wasm,并且不用到 JavaScirpt。作为一款高性能语言,Wasm 绝非 JavaScript 的单纯替代品:它面向Web和非Web的嵌入而设计,解决了广泛存在于浏览器和代码执行引擎中的一个难题,即如何在不受信任的环境中高效执行程序。Wasm 满足了我们的三大主要技术需求:安全性、性能和灵活性。

安全性

运行不受信任的代码具有极大的风险。从本质上来讲,这些代码不仅难以预测,并且还很有可能对整个 Shopify 平台造成损害。尽管市面上并没有百分之百安全可靠的应用,但我们还是要防范安全漏洞,并且在出现问题后采取措施来减轻其影响。


Wasm 将代码执行放到了一个基于堆栈的沙箱环境中,依靠显式导入来与主机进行通信。因此,我们无法在 Wasm 中写入任何恶意代码,只能使用提供的输入端口操作虚拟环境。在这一点上 Wasm 与字节码有所不同,字节码在语法中直接引用了它们希望在其中运行的计算机或操作系统。


Wasm 还有很多不同的功能,可让用户免受错误代码的影响,包括受保护地调用堆栈和运行时类型检查。WebAssembly.org 上提供了更多关于Wasm安全模型的详细资料

性能

在电商领域,较快的运行速度才是商家推动业绩增长时必备的利器。如果 Shopify 提供的功能无法兼顾加载时间和定制价值,那么这种功能压根就没有任何价值可言。


Wasm 本身的设计充分利用了常见的硬件功能,并在各种平台上发挥出最接近原生的性能。它面向追求最高性能、优化浏览器执行的开发者社区。因此,无论是现在还是未来,Wasm 和它的周边工具在设计上都会以性能优化为中心。

灵活性

能帮助开发者提高开发效率的代码执行服务才是真正有用的服务。Wasm 作为一款字节码格式,与多种编译器相兼容,为代码开发者提供了支持多种编程语言的一流开发体验。这也让我们能够在不改变底层执行模型的情况下,提供多语言支持。

基于社区

Shopyify 在发展目标和设计方面基本保持一致,这为我们选择 Wasm 提供了技术上的理由,但事实并不仅限于此:我们对 Wasm 的选择不仅关乎于技术,更关乎于人。如果 Wasm 生态系统无人问津,或者它仅在生死线上垂死挣扎,那么我们不会选择它。WebAssembly 的社区是个充满活力的社区,不断创新,它的潜力是无穷的。自从加入这个充满热情的社区,Shopify 就获益匪浅。


同样,我们也在为社区贡献出我们的力量。通过收集用户反馈,探讨功能缺陷,以及为我们使用的开源工具提交代码贡献。我们认为,这为我们与 WebAssembly 社区之间建立良好的互惠合作关系打下了坚实基础,我们也期望着在未来能够继续为这个鲜活的社区献出我们的力量。

代码执行服务的架构

在简单介绍过 WebAssembly 以及我们选择它的原因后,下一步就来深入探讨我们的运行方案。

 

我们使用的是最初由 Fastly 开发的开源工具Lucet。Fastly 这家公司为大批量寿命不长且不受信任的模块提供了一个可编程的边缘云平台,让它们可以在尽可能接近发起请求的地方执行请求。这与我们的合作方提供的代码所面临的问题相同,因此,我们自然而然就选择了 Lucet。

Lucet

Lucet 是 Wasm 的运行时和编译器。Wasm 中的模块确保了系统的安全性,由于我们无法在 Wasm 中写入恶意代码,因此 Lucet 利用 Wasm 模块的验证进行安全检查。在验证之后,模块会被编译为一个可执行的文件,其性能可以达到原生状态。另外,Wasm 还支持提前编译,可避免执行运行时编译带来的延迟。Lucet 容器在启动时无需执行任何操作,这让它拥有了令人惊叹的 35μs 启动时间。如果您对 Lucet 及其工作原理感兴趣,可以去看看 Fastly 的 CTO Tyler McMullan 的演讲视频


Shopify 中 Wasm 引擎的工作原理流程图

 

我们将 Lucet 包装在一个管理 I/O 和模块存储的 Rust Web 服务里,并将其称作是 Wasm 引擎。在运行时,Shopify 通过 Web 请求调用 Wasm 引擎以处理部分功能。引擎之后再调用站点的上下文中应用输出,这里的上下文可能会涉及到创建折扣、执行约束,或者是任何商家想要在平台中私人定制的同步服务。

运行性能

下图中是我们在最近一次的性能测试中提取到的一些指标。我们选择了一个很小的功能及逆行测试:让模块对用户购物车中添加的物品数量进行限制。在测试期间,每分钟执行十万个模块,持续时间约 5 分钟。


模块执行所需时间

 

该图表展示了执行一个模块所需时间的详细情况,其中包括容器的 I/O 和模块的执行。y 轴代表时间(单位:ms),x 轴代表测试运行的具体时间。

 

图中的浅紫色图例代表 Lucet 中执行模块需要的时间,其宽度大约在 100μs 左右徘徊。其余图标则是 I/O 的处理和引擎的具体情况,可以看出执行的全部时间大约在 4ms 左右。所有的时间显示都是第 99 位百分比(99p)。为了能更好地理解图中时间的含义,下面让我们将用 Shopify 中性能卓越的在线商店渲染服务Storefront Renderer的测试请求时间做比较。


Storefront Renderer 响应时间

 

这张图表中展示了 Storefront Renderer 在一段时间内的请求时间。y 轴代表请求时间(单位:秒),x 轴代表返回数值时的具体时间。浅蓝色线条代表在 700 毫秒左右的第 99 百分比。


如果将模块处理时间大致估算在 5 毫秒内,那么可以说 Lucet 执行时间带来的性能影响几乎可以忽略不计。

生成 WebAssembly

为了让我们性能卓越的执行引擎发挥作用,我们还需要授权开发者创建兼容的 Wasm 模块。Wasm 的作用并不是让用户亲自编写(想写当然是可以写的)代码,而是作为一个编译目标存在。这就会让我们思考以下问题:我们支持哪些编程语言,具体又要支持到什么程度。


理论上来说,任何有 Wasm 支持的开发语言都是可以的。但是,我们更希望开发者可以将精力集中在为商家解决问题上,而不是研究要如何符合我们的 API。这也是我们选择单一语言 Ruby 支持,并为开发者提供快速启动工具的原因。然而,由于 Ruby 动态语言的特性,我们并不能将其直接编译为 Wasm,而涉及编译解释器的解决方案会有严苛的性能惩罚。正因如此,我们最终决定采用静态编译的语言,并将动态语言编译的可能性留待未来。


通过我们的调研发现,Shopify 生态系统中的开发者大多能对 JavaScript 熟练应用。可惜的是,由于 JavaScript 与 Ruby 一样是动态语言,只得被排除在外。最终,我们选择了一种语法类似于 TypeScript 的开发语言:AssemblyScript

使用 AssemblyScript

虽然 WebAssembly 支持大量开发语言,但其中有两大类编译器是我们无法使用的:

  • 生成环境或开发语言特定产物的编译器,即节点或浏览器。(例如AsteriusBlazor

  • 只适用于特定运行时的编译器。这些编译器生成的模块依赖于特定语言的特定导入,通常是为了支持某些特定语言的标准库,让他们能够在系统调用或运行时功能可用而存在的。因为我们并不想被锁死在某一特定语言上,所以这类编译器就不在我们的考虑范围内了。(例如Lumen

 

这些功能强大的编译器在其他情况下或许能够发挥奇效,但可惜无法为我们所用。我们需要能够生成 WebAssembly 的工具,而不是由 WebAssembly 支持的工具。AssemblyScript 便是被我们选中的工具。

与 WebAssembly 中的其他工具一样,AssemblyScript 还在开发过程中。它缺乏一些诸如闭包支持等关键功能,在边缘情况下仍会报错。这时候就显现出了社区的重要性。


开发语言 AssemblyScript 和它的周边工具拥有一个用户活跃的爱好者和维护者社区,自从 2019 年 Shopify 首次使用 AssemblyScript 以来,他们就一直在支持着我们。而我们也通过OpenCollective长期贡献代码以支持社区。我们编写完成了一个语言服务器,在实现闭包方面也取得里一些进展,也为编译器和周边工具提供了错误修复。


我们还将 AssemblyScript 融入了我们早期的工具之中。在Shopify CLI中,我们通过集成 AssemblyScript,允许开发者通过命令行创建、测试和部署模块。为了提高开发效率,我们提供了可以处理 Shopify 定义对象(例如“Money”)底层实现的 SDK。除了这些工具,我们还搭建了一个允许合作伙伴监控模块的系统,方便他们在模块出现故障时收到警报。我们的最终目标是让合作伙伴们能够在不失去代码在原生平台上灵活性和可观察性的前提下,将他们的代码迁移到我们的平台之上。

新功能,新机遇

通过连接商家和合作伙伴,Shopify 做到了商家与企业的对接,解决了双方各自面对的问题。如果你对我们的代码执行服务感兴趣,觉得这些对您或者您的 App 很有用,欢迎在推特上 @ShopifyEng。如需了解更多关于 Shopify 及我们 App 的信息,请访问我们的开发者页面

 

原文链接:

https://shopify.engineering/shopify-Webassembly

2021-01-14 12:002374

评论

发布
暂无评论
发现更多内容

2. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识yml

MASA技术团队

【堡垒机】2022年云堡垒机品牌排名大比拼!

行云管家

云计算 网络安全 堡垒机 企业安全

尚硅谷Flink(Java)新版视频教程发布

@零度

flink 大数据开发

VuePress 博客之 SEO 优化(二)重定向

冴羽

Vue 前端 vuepress SEO 重定向

天翼云中南数字产业园落地长沙“天心数谷”初具雏形

天翼云开发者社区

大数据培训面试Flink八股文分享

@零度

flink 大数据开发

微服务中台技术之视频处理

小江

架构 ffmpeg 视频处理 电商系统

对话|鲜丰水果:“看不见”的门店数字化

阿里云云效

云计算 阿里云 云原生 持续交付 数字化运维

它来了,它来了!开源圈 KOL 的江湖对谈第二季要来了!

OpenTEKr

开源 程序员人生 开源社区 开源软件 优秀开源项目

云管平台提供的功能一般包括哪些?采购需求主要是什么?

行云管家

云计算 企业上云 云管平台 云管理

在页面中直接嵌入vue-sfc的方法

CRMEB

缓存最关心的问题是什么

华为云开发者联盟

Java 缓存 堆内存 缓存命中率 回收策略

液冷数据中心如何构建,蓝海大脑液冷技术保驾护航

GPU算力

液冷服务器

为什么要进行企业知识管理,这三个重点问题要明确

小炮

web前端培训Node.js和JavaScript的关系

@零度

JavaScript node.js 前端开发

加密市场普跌 虎符交易所平台币HOO却能连续2个月逆势上涨

区块链前沿News

Hoo 虎符交易所 平台币

4个迭代,从批量交付到持续交付转型

阿里云云效

云计算 阿里云 云原生 研发团队 研发

云原生技术赋能ISV实现应用现代化

York

云原生

【C语言】猜数字小游戏

謓泽

3月月更

OpenVSCode云端IDE加入Rainbond一体化开发体系

北京好雨科技有限公司

全运会开幕!天翼云全力打造“智慧赛事”

天翼云开发者社区

从“半部电台”到“云监工” 天翼云助力红色电信启航新征程

天翼云开发者社区

如何在 Go 代码中运行 C 语言代码

宇宙之一粟

C语言 Go 语言 3月月更

源码详解数据结构Linked List

华为云开发者联盟

Java ArrayList 框架 linkedlist 双向链表

测试在项目流程中的那些事儿

有道技术团队

观点丨新经济 DTC 转型,一个简单而强大的数据平台至关重要

PingCAP

AI+生物计算:用计算机视觉技术理解细胞生命

百度大脑

沈阳飞桨领航团Meetup邀请你来,探索AI如何赋能智慧城市

百度大脑

Java培训JVM 高频面试题

@零度

JVM JAVA开发

微博评论高性能高可用计算架构

李大虾

#架构实战营 「架构实战营」

创新的力量天翼云推动科技创新技术实践落地

天翼云开发者社区

Shopify如何在浏览器之外使用WebAssembly?_大前端_Duncan Uszkay_InfoQ精选文章