Помимо браузера: начало работы с бессерверной WebAssembly

Опубликовано: 2022-03-10
Краткое резюме ↬ Вы, наверное, слышали о WebAssembly и о том, почему это мощный инструмент в браузере. В этой статье мы исследуем, почему бессерверная WebAssembly может быть столь же мощной вне браузера, и как начать ее использовать.

Теперь, когда WebAssembly поддерживается всеми основными браузерами и более чем 85% пользователей по всему миру, JavaScript больше не является единственным языком браузера в городе. Если вы не слышали, WebAssembly — это новый низкоуровневый язык, работающий в браузере. Это также цель компиляции, что означает, что вы можете компилировать существующие программы, написанные на таких языках, как C, C++ и Rust, в WebAssembly и запускать эти программы в браузере. До сих пор WebAssembly использовался для переноса в Интернет всевозможных приложений, включая настольные приложения, инструменты командной строки, игры и инструменты обработки данных.

Примечание. Для подробного изучения того, как WebAssembly можно использовать внутри браузера для ускорения работы веб-приложений, ознакомьтесь с моей предыдущей статьей.

WebAssembly вне Интернета?

Хотя большинство современных приложений WebAssembly ориентированы на браузер, сам WebAssembly изначально разрабатывался не только для Интернета, но и для любой изолированной среды. На самом деле, в последнее время наблюдается большой интерес к изучению того, как WebAssembly может быть полезен вне браузера в качестве общего подхода к запуску двоичных файлов в любой ОС или компьютерной архитектуре, если существует среда выполнения WebAssembly, поддерживающая эту систему. В этой статье мы рассмотрим, как WebAssembly можно запускать вне браузера в бессерверном режиме или по модели «Функция как услуга» (FaaS).

Еще после прыжка! Продолжить чтение ниже ↓

WebAssembly для бессерверных приложений

В двух словах, бессерверные функции — это вычислительная модель, в которой вы передаете свой код облачному провайдеру и позволяете ему выполнять и управлять масштабированием этого кода для вас. Например, вы можете попросить, чтобы ваша бессерверная функция выполнялась каждый раз, когда вы вызываете конечную точку API, или чтобы она управлялась событиями, например, когда файл загружается в вашу облачную корзину. Хотя термин «бессерверный» может показаться неправильным, поскольку серверы явно задействованы где-то на этом пути, с нашей точки зрения, это бессерверный вариант, поскольку нам не нужно беспокоиться о том, как управлять этими серверами, развертывать или масштабировать их.

Хотя эти функции обычно пишутся на таких языках, как Python и JavaScript (Node.js), есть ряд причин, по которым вы можете вместо этого использовать WebAssembly:

  1. Более быстрое время инициализации
    Бессерверные провайдеры, поддерживающие WebAssembly (включая Cloudflare и Fastly, сообщают, что они могут запускать функции как минимум на порядок быстрее, чем большинство облачных провайдеров с другими языками. Они достигают этого, запуская десятки тысяч модулей WebAssembly в одном процессе, что Это возможно, потому что изолированная природа WebAssembly обеспечивает более эффективный способ получения изоляции, для которой традиционно используются контейнеры.
  2. Нет необходимости переписывать
    Одним из основных преимуществ WebAssembly в браузере является возможность переноса существующего кода в Интернет без необходимости переписывать все на JavaScript. Это преимущество остается в силе в случае бессерверного использования, поскольку облачные провайдеры ограничивают языки, на которых вы можете писать свои бессерверные функции. Как правило, они будут поддерживать Python, Node.js и, возможно, некоторые другие, но, конечно, не C, C++ или Rust. . Поддерживая WebAssembly, бессерверные провайдеры могут косвенно поддерживать гораздо больше языков.
  3. Более легкий
    При запуске WebAssembly в браузере мы полагаемся на компьютер конечного пользователя для выполнения наших вычислений. Если эти вычисления слишком интенсивны, наши пользователи не будут счастливы, когда вентилятор их компьютера начнет жужжать. Запуск WebAssembly вне браузера дает нам преимущества скорости и переносимости WebAssembly, сохраняя при этом легкость нашего приложения. Кроме того, поскольку мы запускаем наш код WebAssembly в более предсказуемой среде, мы потенциально можем выполнять более интенсивные вычисления.

Конкретный пример

В моей предыдущей статье здесь, в Smashing Magazine, мы обсуждали, как мы ускорили веб-приложение, заменив медленные вычисления JavaScript кодом C, скомпилированным в WebAssembly. Рассматриваемым веб-приложением было fastq.bio, инструмент для предварительного просмотра качества данных секвенирования ДНК.

В качестве конкретного примера давайте перепишем fastq.bio как приложение, которое использует бессерверную сборку WebAssembly вместо запуска WebAssembly внутри браузера. В этой статье мы будем использовать Cloudflare Workers, бессерверного провайдера, который поддерживает WebAssembly и построен на основе движка браузера V8. Другой поставщик облачных услуг, Fastly, работает над аналогичным предложением, но на основе среды выполнения Lucet.

Во-первых, давайте напишем код на Rust для анализа качества данных секвенирования ДНК. Для удобства мы можем использовать биоинформационную библиотеку Rust-Bio для обработки входных данных и библиотеку wasm-bindgen, которая поможет нам скомпилировать наш код Rust в WebAssembly.

Вот фрагмент кода, который считывает данные секвенирования ДНК и выводит JSON со сводкой показателей качества:

 // Import packages extern crate wasm_bindgen; use bio::seq_analysis::gc; use bio::io::fastq; ... // This "wasm_bindgen" tag lets us denote the functions // we want to expose in our WebAssembly module #[wasm_bindgen] pub fn fastq_metrics(seq: String) -> String { ... // Loop through lines in the file let reader = fastq::Reader::new(seq.as_bytes()); for result in reader.records() { let record = result.unwrap(); let sequence = record.seq(); // Calculate simple statistics on each record n_reads += 1.0; let read_length = sequence.len(); let read_gc = gc::gc_content(sequence); // We want to draw histograms of these values // so we store their values for later plotting hist_gc.push(read_gc * 100.0); hist_len.push(read_length); ... } // Return statistics as a JSON blob json!({ "n": n_reads, "hist": { "gc": hist_gc, "len": hist_len }, ... }).to_string() }

Затем мы использовали инструмент командной строки Cloudflare wrangler, чтобы выполнить тяжелую работу по компиляции в WebAssembly и развертыванию в облаке. После этого нам предоставляется конечная точка API, которая принимает данные секвенирования в качестве входных данных и возвращает JSON с метриками качества данных. Теперь мы можем интегрировать этот API в наше приложение.

Вот GIF приложения в действии:

GIF нашего приложения, выполняющего параллельные вызовы бессерверной функции WebAssembly и обновляющего графики возвращаемыми данными.
Вместо того, чтобы запускать анализ непосредственно в браузере, бессерверная версия нашего приложения выполняет несколько запросов POST параллельно с нашей бессерверной функцией (см. правую боковую панель) и обновляет графики каждый раз, когда возвращает больше данных. (Большой превью)

Полный код доступен на GitHub (с открытым исходным кодом).

Помещая все это в контекст

Чтобы представить бессерверный подход WebAssembly в контексте, давайте рассмотрим четыре основных способа создания веб-приложений для обработки данных (т. е. веб-приложений, в которых мы выполняем анализ данных, предоставленных пользователем):

На этом рисунке показаны четыре способа структурирования обработки данных в веб-приложении: на сервере (без WebAssembly), в браузере с использованием JavaScript, в браузере с использованием WebAssembly и без сервера WebAssembly.
Четыре различных варианта архитектуры, которые мы можем использовать для приложений, обрабатывающих данные. (Большой превью)

Как показано выше, обработка данных может производиться в нескольких местах:

  1. на стороне сервера
    Это подход, используемый большинством веб-приложений, где вызовы API, сделанные во внешнем интерфейсе, запускают обработку данных во внутреннем интерфейсе.
  2. Клиентский JavaScript
    При таком подходе код обработки данных пишется на JavaScript и запускается в браузере. Недостатком является то, что ваша производительность пострадает, и если ваш исходный код не был на JavaScript, вам придется переписать его с нуля!
  3. WebAssembly на стороне клиента
    Это включает компиляцию кода анализа данных в WebAssembly и запуск его в браузере. Если код анализа был написан на таких языках, как C, C++ или Rust (как это часто бывает в моей области геномики), это избавляет от необходимости переписывать сложные алгоритмы на JavaScript. Это также обеспечивает потенциал для ускорения нашего приложения (например, как обсуждалось в предыдущей статье).
  4. Бессерверная веб-сборка
    Это включает в себя запуск скомпилированной WebAssembly в облаке с использованием модели типа FaaS (например, эта статья).

Так почему же вы предпочли бессерверный подход другим? Во-первых, по сравнению с первым подходом у него есть преимущества, связанные с использованием WebAssembly, особенно возможность портировать существующий код без необходимости переписывать его на JavaScript. По сравнению с третьим подходом бессерверная WebAssembly также означает, что наше приложение более легкое, поскольку мы не используем ресурсы пользователя для обработки чисел. В частности, если вычисления достаточно сложны или если данные уже находятся в облаке, этот подход имеет больше смысла.

С другой стороны, теперь приложению необходимо устанавливать сетевые подключения, поэтому приложение, вероятно, будет работать медленнее. Кроме того, в зависимости от масштаба вычислений и возможности разбить его на более мелкие части анализа, этот подход может оказаться неприемлемым из-за ограничений, налагаемых поставщиками бессерверных облачных вычислений на время выполнения, использование ЦП и ОЗУ.

Заключение

Как мы видели, теперь можно запускать код WebAssembly в бессерверном режиме и пользоваться преимуществами как WebAssembly (мобильность и скорость), так и архитектур «функция как услуга» (автоматическое масштабирование и ценообразование по факту использования). ). Определенные типы приложений, такие как анализ данных и обработка изображений, могут значительно выиграть от такого подхода. Хотя время выполнения страдает из-за дополнительных обращений к сети, такой подход позволяет нам обрабатывать больше данных за раз и не истощать ресурсы пользователей.