•26 min read

WASI0.2とWebAssemblyComponentModel:言語非依存のマイクロサービスとWITインターフェース

WASI0.2とWebAssemblyComponentModel:言語非依存のマイクロサービスとWITインターフェース

WebAssemblyコンポーネントモデルは、WASI 0.2 (Preview 2) と組み合わせることで、分散システムアーキテクチャに根本的な変化をもたらします。この進化により、真に言語非依存で構成可能なマイクロサービスが、ネイティブに近いパフォーマンスと前例のないコールドスタート特性で実現されます。このガイドでは、WIT (Wasm Interface Type) 定義、多言語コンポーネント開発、そしてwasmtimeおよびSpinランタイム内でのデプロイに焦点を当て、これらの技術の実践的な応用について詳しく説明します。

Audio Briefing
0:00 / 0:00

WebAssemblyコンポーネントモデル:パラダイムシフト

従来のマイクロサービスは、言語間の相互運用性、依存関係の肥大化、コンテナ環境に固有の遅いコールドスタート時間といった問題にしばしば直面していました。コンポーネントモデルは、WebAssemblyモジュール用の標準化された高レベルインターフェースを定義することでこれらの問題に対処し、ソース言語に関わらずシームレスな通信を可能にします。これは、言語非依存のインターフェース定義言語(IDL)であるWITを通じて実現されます。

WebAssemblyコンポーネントは、自己完結型でサンドボックス化された計算単位です。1つ以上のWasmコアモジュールと、その依存関係、そしてWITインターフェースを介して対話するための必要なグルーコードをカプセル化します。この構造は以下を促進します。

  1. 言語の相互運用性: Rustで書かれたコンポーネントは、Pythonで書かれたコンポーネントがエクスポートする関数を呼び出すことができ、その逆も可能です。これらはすべてWITによって仲介されます。
  2. モジュール性 & 構成可能性: コンポーネントは実行時またはビルド時にリンクされ、より小さく独立した単位から複雑なアプリケーションを形成できます。
  3. セキュリティ: Wasmランタイムによってきめ細かなパーミッションが強制され、コンポーネントのホストリソースへのアクセスが制限されます。
  4. 効率性: オーバーヘッドが最小限で、バイナリサイズが小さく、コールドスタートはミリ秒未満です。
Advertisement

WASI 0.2 (Preview 2):ホストインタラクションの標準化

WASI (WebAssembly System Interface) は、WebAssemblyモジュールがホストオペレーティングシステムと対話するための標準化されたAPIセットを提供します。WASI 0.2 (Preview 2) はこれを大幅に改良し、ケーパビリティベースのセキュリティモデルへと移行し、コンポーネントモデルと深く統合されています。広範なアクセスを許可する代わりに、コンポーネントは必要な特定のケーパビリティ(例:特定のディレクトリへのファイルシステムアクセス、特定のドメインへのネットワーク接続)を明示的に宣言します。これにより、セキュリティとポータビリティが向上します。

WASI 0.2の主な機能は以下の通りです。

  • wasi:cli: 標準化されたコマンドラインインターフェース。
  • wasi:filesystem: セキュアなケーパビリティベースのファイルシステムアクセス。
  • wasi:sockets: ネットワークI/O。
  • wasi:io: 基本的なI/Oストリーム。
  • wasi:random: 暗号学的に安全な乱数生成。

これらのAPIはWITで定義されており、ホストランタイムがこれらを実装し、コンポーネントがこれらをインポートできるようになっています。

WIT (Wasm Interface Type) を用いたインターフェースの定義

WITはコンポーネントモデルの要です。これは、コンポーネントがエクスポートおよびインポートする型と関数を記述するために使用されるテキストベースのIDLです。これにより、コンポーネントとホスト間の静的型チェックと効率的なデータマーシャリングが可能になります。

ユーザーデータを処理するシンプルなサービスを考えてみましょう。そのインターフェースをuser-processor.witで定義します。

// user-processor.wit
package locionic:user-processor;

/// Represents a user profile.
record UserProfile {
    id: u64,
    username: string,
    email: string,
    is-active: bool,
}

/// Defines the interface for user data processing.
interface processor {
    /// Processes a single user profile.
    /// Returns true if processing was successful, false otherwise.
    process-user: func(user: UserProfile) -> bool;

    /// Retrieves a user profile by ID.
    /// Returns an optional UserProfile, which is `none` if not found.
    get-user-by-id: func(id: u64) -> option<UserProfile>;
}

world user-service {
    export processor;
    import wasi:cli/environment; // Example of importing a WASI interface
}

説明:

  • package locionic:user-processor;: コンポーネントのパッケージ名前空間を定義します。
  • record UserProfile { ... }: 構造化データ型を定義します。WITは様々なプリミティブ型(u8、s32、string、bool)、レコード、バリアント(和型)、列挙型、リスト、オプションをサポートしています。
  • interface processor { ... }: 関連する関数をグループ化します。
  • process-user: func(user: UserProfile) -> bool;: process-userという関数を宣言し、UserProfileを受け取り、boolを返します。
  • option<UserProfile>: ヌル許容型を表します。
  • world user-service { ... }: worldはコンポーネントの完全なインターフェースを定義します。コンポーネントがどのインターフェースをエクスポートし、環境(ホストまたは他のコンポーネント)から何をインポートするかを指定します。
  • export processor;: コンポーネントはprocessorインターフェースをエクスポートします。
  • import wasi:cli/environment;: コンポーネントはwasi:cliパッケージからenvironmentインターフェースをインポートし、環境変数にアクセスできるようにします。

多言語コンポーネント開発

user-processorインターフェースを実装するRustコンポーネントと、それを消費する(またはそれを呼び出す別のコンポーネント)Pythonコンポーネントの2つを構築してみましょう。

Rustコンポーネント: user-processorの実装

まず、Rustとwasm-toolsがインストールされていることを確認してください。

rustup target add wasm32-wasi
cargo install wasm-tools

新しいRustライブラリを作成します。

cargo new --lib user-processor-rust
cd user-processor-rust

Cargo.tomlにwit-bindgenを追加します。

# Cargo.toml
[package]
name = "user-processor-rust"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
# wit-bindgen is used to generate Rust bindings from WIT
wit-bindgen = { version = "0.11.0", features = ["macros"] }

[build-dependencies]
wit-bindgen = { version = "0.11.0" }

user-processor.witからRustバインディングを生成するためにbuild.rsを作成します。

// build.rs
fn main() {
    println!("cargo:rerun-if-changed=../user-processor.wit");
    wit_bindgen::generate("user-processor.wit")
        .expect("wit-bindgen failed to generate code");
}

次に、src/lib.rsにprocessorインターフェースを実装します。

// src/lib.rs
wit_bindgen::generate!({
    path: "../user-processor.wit",
    world: "user-service",
});

struct UserProcessorRust;

impl guest::locionic::user_processor::processor::Processor for UserProcessorRust {
    fn process_user(user: guest::locionic::user_processor::processor::UserProfile) -> bool {
        println!("Rust component: Processing user: id={}, username={}, email={}, active={}",
            user.id, user.username, user.email, user.is_active);
        // Simulate some processing logic
        user.is_active // Return true if user is active
    }

    fn get_user_by_id(id: u64) -> Option<guest::locionic::user_processor::processor::UserProfile> {
        println!("Rust component: Retrieving user by ID: {}", id);
        if id == 123 {
            Some(guest::locionic::user_processor::processor::UserProfile {
                id: 123,
                username: "rust_user".to_string(),
                email: "rust@example.com".to_string(),
                is_active: true,
            })
        } else {
            None
        }
    }
}

// This macro generates the necessary boilerplate for the component to export its functions.
export!(UserProcessorRust);

コンポーネントをビルドします。

cargo build --target wasm32-wasi --release

これによりtarget/wasm32-wasi/release/user_processor_rust.wasmが生成されます。これはコアWasmモジュールです。これをコンポーネントにするには、wasm-toolsを使用します。

wasm-tools component new target/wasm32-wasi/release/user_processor_rust.wasm \
  --adapt wasi_snapshot_preview1 \
  -o user_processor_rust.wasm

--adapt wasi_snapshot_preview1フラグは非常に重要です。これは、コアWasmモジュール(通常は古いwasi_snapshot_preview1 ABIを使用)をコンポーネントモデルのWASI 0.2インターフェースに適応させます。

Pythonコンポーネント: user-processorの利用

コンポーネントモデルのPythonサポートは急速に進化しています。この例では、wasmtimeのPythonバインディングとcomponentize-pyを使用します。

まず、componentize-pyをインストールします。

pip install componentize-py

Pythonモジュールuser_consumer.pyを作成します。

# user_consumer.py
from typing import Optional
from componentize_py import componentize

# Define the WIT interface directly in Python for componentize-py
# In a real scenario, you'd likely generate this from a .wit file
# For demonstration, we'll define a simple interface that imports
# the user-processor and exports a 'run' function.

# This is a simplified representation for componentize-py.
# The actual WIT definition would be in user-processor.wit
# and componentize-py would generate the Python types.
# For this example, we'll define a 'world' that imports our Rust component.

# We need to define the types that the imported component uses.
class UserProfile:
    id: int
    username: str
    email: str
    is_active: bool

    def __init__(self, id: int, username: str, email: str, is_active: bool):
        self.id = id
        self.username = username
        self.email = email
        self.is_active = is_active

# This is the Python code that will be componentized.
# It will import the 'processor' interface from our Rust component.
class UserConsumer:
    def run(self) -> None:
        # This part assumes the 'processor' interface is available
        # in the current scope due to how componentize-py generates bindings.
        # In a real scenario, you'd access it via a generated module.
        print("Python component: Starting user consumption...")

        # Simulate calling the imported Rust component's functions
        # These types (UserProfile) would be generated by wit-bindgen for Python
        # For this example, we'll manually construct them.

        # Call process_user
        test_user = UserProfile(id=456, username="python_test", email="py@example.com", is_active=True)
        # The actual call signature depends on the generated bindings.
        # For componentize-py, it often looks like this:
        # from locionic.user_processor.processor import process_user, get_user_by_id, UserProfile
        # For this example, we'll mock the call.

        # In a real componentized Python, you'd have:
        # from locionic.user_processor.processor import process_user, get_user_by_id, UserProfile
        # result = process_user(test_user)
        # print(f"Python component: Processed user (Python): {result}")

        # For demonstration without full componentize-py binding generation setup:
        # We'll assume the host will link the Rust component and provide its functions.
        # The Python component itself will just print.
        print(f"Python component: Would call process_user with {test_user.username}")

        # Call get_user_by_id
        # user_from_rust = get_user_by_id(123)
        # if user_from_rust:
        #     print(f"Python component: Retrieved user from Rust: {user_from_rust.username}")
        # else:
        #     print("Python component: User 123 not found by Rust component.")

        print("Python component: Would call get_user_by_id(123)")

# This is the WIT definition for the Python component's world.
# It imports the 'processor' interface from our Rust component.
# This WIT defines what the Python component *expects* from its environment.
python_consumer_wit = """
package locionic:user-consumer;

import locionic:user-processor/processor;

world python-consumer {
    import processor; // Import the interface from the Rust component
    export run: func();
}
"""

# Componentize the Python module
componentize(
    "user_consumer.py",
    wit=python_consumer_wit,
    world="python-consumer",
    output="user_consumer.wasm",
)

このコマンドはuser_consumer.wasmを生成します。componentize-pyはまだ活発に開発中であり、正確な呼び出し方や生成されるコードは異なる可能性があることに注意してください。重要な点は、Pythonコンポーネントのworldがlocionic:user-processor/processorインターフェースを明示的にインポートしており、リンクされるとRustコンポーネントの関数を呼び出せるようになることです。

Advertisement

wasmtimeでコンポーネントを実行する

wasmtimeは、コンポーネントモデルとWASI 0.2を完全にサポートする主要なWebAssemblyランタイムです。

まず、wasmtimeをインストールします。

curl https://wasmtime.dev/install.sh -sSf | bash

Rustコンポーネントを実行するには:

wasmtime run user_processor_rust.wasm --invoke process-user '{ "id": 789, "username": "test_user", "email": "test@example.com", "is-active": true }'

これは、user-serviceワールドによってエクスポートされたprocess-user関数を直接呼び出します。JSON文字列は自動的にUserProfileレコードにマーシャリングされます。

PythonコンポーネントがRustコンポーネントを消費するデモンストレーションを行うには、それらをリンクする必要があります。これは通常、ホストランタイムによって行われます。

両方のコンポーネントをロードしてリンクするシンプルなホストアプリケーションをRustで作成してみましょう。

// host_app.rs
use anyhow::Result;
use wasmtime::{component::*, Config, Engine, Store};

// Define the WIT types for the host to interact with
wit_bindgen::generate!({
    path: "user-processor.wit",
    world: "user-service",
    // This tells wit-bindgen to generate types for the host side
    // so it can interact with the component.
    // We need to define the types for the Python consumer as well if we want to call it.
    // For simplicity, we'll just call the Rust component directly from the host.
});

#[tokio::main]
async fn main() -> Result<()> {
    let mut config = Config::new();
    config.wasm_component_model(true); // Enable Component Model support
    config.async_support(true); // Enable async for WASI futures

    let engine = Engine::new(&config)?;
    let mut store = Store::new(&engine, ()); // No host state needed for this example

    // Load the Rust component
    let component = Component::from_file(&engine, "user_processor_rust.wasm")?;

    // Instantiate the component
    let (instance, _exports) = UserService::instantiate_async(&mut store, &component, &[])
        .await?;

    // Access the exported 'processor' interface
    let processor = instance.processor();

    // Call process_user
    let user_profile = locionic::user_processor::processor::UserProfile {
        id: 101,
        username: "host_caller".to_string(),
        email: "host@example.com".to_string(),
        is_active: true,
    };
    let success = processor.process_user(&mut store, &user_profile).await?;
    println!("Host app: Processed user via Rust component: {}", success);

    // Call get_user_by_id
    let retrieved_user = processor.get_user_by_id(&mut store, 123).await?;
    if let Some(user) = retrieved_user {
        println!("Host app: Retrieved user from Rust component: id={}, username={}", user.id, user.username);
    } else {
        println!("Host app: User 123 not found by Rust component.");
    }

    Ok(())
}

このホストアプリケーションを実行するには:

cargo add anyhow wasmtime wasmtime-wasi tokio --features "macros,rt-multi-thread"
cargo run --bin host_app

これは、ホスト(Rustアプリケーション)がWITインターフェースを介してRustベースのWasmコンポーネントと対話する方法を示しています。PythonコンポーネントがRustコンポーネントを呼び出すためには、wasmtimeランタイムがそれらをリンクし、Pythonコンポーネントのインポートにprocessorインターフェースを提供する必要があります。このリンクは通常、ランタイムによるインスタンス化時に行われます。

Spinでコンポーネントを実行する

Spinは、WebAssemblyでイベント駆動型マイクロサービスを構築および実行するためのフレームワークです。コンポーネントモデルとWASI 0.2を広範囲に活用しています。SpinはWasmコンポーネントのデプロイとオーケストレーションを簡素化します。

まず、Spinをインストールします。

curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash

Rustコンポーネント用のspin.tomlを作成します。

# spin.toml
spin_version = "1"
authors = ["Locionic Engineering <engineering@locionic.com>"]
description = "User Processor Service"
name = "user-processor-service"
trigger = { type = "http", base = "/" }

[[component]]
id = "user-processor-rust"
source = "user_processor_rust.wasm"
# This is a placeholder for how Spin would expose the WIT interface
# and allow other components to call it.
# For HTTP triggers, Spin automatically maps HTTP requests to component functions.
# For component-to-component calls, Spin's linking mechanism would be used.
# For this example, we'll expose a simple HTTP endpoint.
trigger = { route = "/process", executor = { type = "wagi" } }
# Environment variables or other capabilities can be configured here
# environment = { MY_VAR = "value" }

RustコンポーネントをHTTPサービスとして実行するには:

spin up

その後、curlを使用して対話できます。

curl -X POST -H "Content-Type: application/json" -d '{"id": 999, "username": "spin_user", "email": "spin@example.com", "is-active": true}' http://127.0.0.1:3000/process

これは、SpinがWasmコンポーネントをHTTPマイクロサービスとしてホストおよび公開し、基盤となるWASIおよびコンポーネントモデルの複雑さを抽象化する方法を示しています。

ベンチマーク:コールドスタートレイテンシ

WebAssemblyコンポーネントの最も魅力的な利点の1つは、そのコールドスタートパフォーマンスです。

機能WebAssemblyコンポーネント (WASI 0.2)OCIコンテナ (例: Docker)
コールドスタートレイテンシ< 1 ms (多くの場合 < 100 µs)100 ms - 5秒以上
バイナリサイズキロバイトから数メガバイト数十から数百メガバイト
メモリフットプリント低 (MB単位)中程度から高 (100MB以上)
分離サンドボックス (ケーパビリティベース)OSレベル (名前空間、cgroups)
言語サポート多言語 (WIT経由)任意 (コンテナ内)
ポータビリティWasmランタイム (例: wasmtime)コンテナランタイム (例: containerd)
相互運用性WIT定義インターフェースRPC, HTTP, メッセージキュー

コールドスタートベンチマークの方法論:

  1. Wasmコンポーネント:
    • wasmtimeを使用して、シンプルなコンポーネント(例:文字列を返すだけのもの)をインスタンス化して呼び出します。
    • wasmtime::component::Component::instantiate_asyncから最初の関数呼び出し完了までの時間を測定します。
    • 多数回繰り返し、平均を算出します。
  2. OCIコンテナ:
    • 最小限のコンテナ(例:Python FlaskアプリまたはRust Actix-webアプリ)を構築します。
    • docker runから最初の成功したHTTPレスポンスまでの時間を測定します。
    • 多数回繰り返し、平均を算出します。

期待される結果:

  • Wasmコンポーネント: 一般的なコールドスタート時間は数十から数百マイクロ秒の範囲です。これは、バイナリサイズが小さく、OSレベルの仮想化がなく、効率的なランタイムロードによるものです。
  • OCIコンテナ: コールドスタート時間は通常、イメージサイズ、アプリケーションの起動ロジック、および基盤となるインフラストラクチャに応じて、数百ミリ秒から数秒の範囲です。これには、OSの起動、プロセスの起動、およびアプリケーションの初期化が含まれます。

この顕著な違いにより、WebAssemblyコンポーネントは、レイテンシが重要なイベント駆動型サーバーレス関数に最適です。

本番環境での落とし穴とトラブルシューティング

  1. wasm-tools component newアダプテーションの問題:

    • 問題: コアWasmモジュールが適応に失敗するか、適応されたコンポーネントが実行されない。「missing imports」や「unresolved symbols」として現れることが多い。
    • 原因: コアWasmモジュールがwasi_snapshot_preview1 ABIでコンパイルされていないか、--adaptフラグが間違っているか欠落している。一部の言語/ツールチェーンは、アダプターと直接互換性のないWasmを生成する可能性がある。
    • 解決策: Rustの場合、ターゲットがwasm32-wasiであることを確認する。wasm-toolsのバージョンを確認する。古いツールチェーンを使用している場合は、wasi_snapshot_preview1を明示的にリンクするか、別のアダプターを使用する必要があるかもしれない。Goのような言語の場合、WASIをターゲットとするWasm互換SDKを使用していることを確認する。
  2. WIT型不一致/バージョン管理:

    • 問題: コンポーネントがリンクまたは通信に失敗し、実行時に型エラーを報告する。
    • 原因: 異なるコンポーネントのコンパイルに使用されたWIT定義が同期していないか、ホストランタイムがコンポーネントが期待するWITインターフェースの古い/新しいバージョンを使用している。
    • 解決策: WITファイルをAPI契約として扱う。慎重にバージョン管理する。共有WIT定義のための一元化されたリポジトリを使用する。すべてのコンポーネントとホストがまったく同じWITファイルに対してビルドされていることを確認する。コンポーネントのエクスポート/インポートされたWITを検査するためにwasm-tools component witを使用する。
  3. ケーパビリティベースのセキュリティエラー (WASI 0.2):

    • 問題: コンポーネントがリソース(例:ファイル、ネットワークソケット)にアクセスしようとして、ホスト環境が許可しているように見えても、パーミッション拒否エラーが発生する。
    • 原因: コンポーネントのWITにおけるworld定義が、必要なWASIケーパビリティを明示的にインポートしていないか、ホストランタイムがそのケーパビリティを付与するように設定されていない。
    • 解決策: コンポーネントのworld定義を確認する。wasmtimeの場合、--mapdir、--env、--netなどのフラグを使用して特定のケーパビリティを付与する。Spinの場合、spin.tomlの[component]セクションをfiles、environment、allowed_http_hostsなどで設定する。WASI 0.2はデフォルトで拒否することに注意する。
  4. Python componentize-py開発の変動:

    • 問題: componentize-pyコマンドや生成されたコードが新しいバージョンで動作しなくなる。
    • 原因: Pythonコンポーネントモデルのツールは急速に進化している。APIや機能は頻繁に変更される可能性がある。
    • 解決策: componentize-pyを特定のバージョンに固定する。最新のcomponentize-pyドキュメントと例を参照する。初期段階のツールでは破壊的な変更があることを覚悟する。Pythonツールが安定するまで、重要なコンポーネントにはRustの使用を検討する。
  5. 過剰なデータコピーによるパフォーマンス低下:

    • 問題: コールドスタートは速いが、大量のデータ構造を伴う高スループットのコンポーネント間インタラクションが遅くなる。
    • 原因: ホストとコンポーネント間、またはコンポーネント間のデータマーシャリングは、Wasmリニアメモリ境界を越えてデータをコピーすることを伴う。非常に大きなデータの場合、このオーバーヘッドが蓄積される可能性がある。
    • 解決策: データ構造を最適化する。可能な場合は、完全なデータではなく参照やIDを渡す。非常に高帯域幅のシナリオでは、共有メモリ技術(より複雑だが)を検討する。コンポーネント間のインタラクションをプロファイリングしてボトルネックを特定する。

よくある質問

  1. WasmのモジュールとWasmのコンポーネントの違いは何ですか? Wasmのモジュールは、WebAssemblyバイトコードの低レベルで自己完結型のバイナリ単位であり、通常は単一のソースファイルまたはライブラリからコンパイルされます。フラットなインポート/エクスポート名前空間を持ち、生のC言語のようなABIを使用します。Wasmのコンポーネントは、1つ以上のWasmモジュールの上に構築された高レベルの抽象化です。WITを使用して構造化された型付きインターフェースを定義し、言語非依存の相互運用性ときめ細かなケーパビリティベースのセキュリティを可能にします。コンポーネントは構成可能性のために設計されています。

  2. 既存のライブラリ(例:numpy、serde)をWasmコンポーネント内で使用できますか? はい、ただし注意点があります。Rustの場合、wasm32-wasiにコンパイルされ、プラットフォーム固有のシステムコール(WASIの範囲外)に依存しないライブラリは一般的に動作します。Pythonの場合、純粋なPythonライブラリまたはWasm互換のC拡張を持つライブラリは動作する可能性があります。しかし、複雑なC/C++依存関係を持つライブラリや、WASIでカバーされていない直接的なOS呼び出しを行うライブラリは、おそらく失敗するか、大幅な移植作業が必要になります。コンポーネントモデルの強みは、インターフェースを定義することにあり、必ずしも任意の既存のバイナリを実行することではありません。

  3. コンポーネントモデルは非同期操作をどのように処理しますか? WASI 0.2は非同期プリミティブを導入しており、WITではしばしばfuture<T>として公開されます。wasmtimeのようなランタイムは非同期サポートを提供し、コンポーネントが非ブロッキングI/Oを実行できるようにします。コンポーネントが非同期ホスト関数を呼び出すと、Wasm実行は一時停止され、ホスト操作が完了したときに再開できます。これにより、Wasmエンジン全体をブロックすることはありません。

  4. WebAssemblyコンポーネントモデルは2026年に本番環境で使用できますか? はい。仕様はまだ進化中ですが(WASI 0.2は「Preview 2」)、wasmtimeのような主要なランタイムやSpinのようなフレームワークは、堅牢で本番環境に対応した実装を持っています。多くの組織が、コールドスタート、セキュリティ、ポータビリティが最重要視されるサーバーレス、エッジコンピューティング、プラグインアーキテクチャなどの特定のユースケースでWasmコンポーネントをすでにデプロイしています。ツールエコシステム(bindgen、componentizers)も急速に成熟しています。

  5. コンポーネントモデルはgRPCや他のRPCフレームワークと比較してどうですか? どちらも言語非依存の通信を目指しています。gRPCはIDLにProtocol Buffersを使用し、ネットワーク通信(HTTP/2)に依存します。コンポーネントモデルはIDLにWITを使用し、コンポーネント間、またはコンポーネントとホスト間の直接的なプロセス内関数呼び出しを最小限のオーバーヘッドで可能にします。これにより、ローカル通信では大幅に高速になります。ネットワークを介した分散通信の場合、Wasmコンポーネメントの上にRPC(gRPCやHTTPなど)を重ねて使用することになります。その場合、コンポーネント自体がRPCエンドポイントを実装します。

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement