How to use layers to solve dependency package problem

Alibaba Cloud Function Compute をご利用の際に、以下の問題に遭遇したことがあれば、本記事が参考になります。

1. サードパーティ依存パッケージが大きすぎて、コードを更新するたびに時間がかかり、コードパッケージのサイズ制限を超えることさえあります。どうすればよいでしょうか。

2. サードパーティ依存パッケージをインストールした後、ローカルでは正常に実行できるのに、Alibaba Cloud Function Compute プラットフォームにアップロードするとエラーが発生します。これはなぜでしょうか。

3. 多くのユーザーが利用する共通の依存パッケージが多く存在します。Alibaba Cloud Function Compute の実行環境に事前に組み込めないのでしょうか。

4. 複数の関数で同じ依存パッケージを使用しています。これらの共通依存パッケージをどのように管理すればよいでしょうか。

レイヤーは、集中管理の方法を提供し、複数の関数間でコードとデータを共有する仕組みです。

2021 年 1 月、Alibaba Cloud Function Compute は「カスタムレイヤー」機能をリリースしました。これにより、ユーザーがレイヤーをカスタマイズし、関数間での共有をサポートできるようになりました。2022 年 8 月には「パブリックレイヤー」機能をリリースし、ユーザーが直接利用できる公式パブリックレイヤーを提供することで、ユーザー体験をさらに向上させました。

以下では、「カスタムレイヤー」の機能と役割について紹介します。

カスタムレイヤー

レイヤー機能がリリースされる前は、コードを依存関係と一緒にパッケージングしてデプロイする必要がありました。これらの依存関係は異なる関数間で同じである場合が多く、多くの場合、依存関係のサイズはコード自体のサイズをはるかに上回ります。

レイヤー機能のリリース後、コードの依存関係や複数関数の共有部分を Zip 圧縮ファイルにパッケージングし、Function Compute 用のカスタムレイヤーとして公開できるようになりました。異なる関数からこのカスタムレイヤーを利用できます。Alibaba Cloud Function Compute は、関数呼び出し時にレイヤーと関数コードを一緒にロードします。ドキュメント [1](記事末尾参照)を参照してカスタムレイヤーを作成し [2]、関数にカスタムレイヤーを設定できます。

カスタムレイヤーを使用する理由

カスタムレイヤーを使用すると、以下のメリットがあります。

関数間でのコード再利用

複数の関数から共通のコードやデータを抽出し、Zip パッケージにまとめてカスタムレイヤーとして作成することで、異なる関数から参照できるようになります。これにより、共通コードやデータを複数箇所で保守する手間が省けます。

同時に、依存関係とビジネスロジックの分離も実現し、ユーザーはコアとなるビジネスロジックに集中できます。

コードパッケージの軽量化

関数のコードパッケージが大きくなるほど、デプロイ速度は遅くなり、関数の保守やテストが困難になります。

また、関数コードパッケージのサイズには制限もあります。たとえば、Alibaba Cloud Function Compute のコードパッケージは 500MB に制限されています(2022 年 9 月時点)。レイヤーはこの制限を回避する手段の一つです。レイヤーにもサイズ制限があり、現在、単一レイヤーのコードパッケージサイズは 500MB に制限されています。単一関数には最大 5 つのレイヤーを設定でき、合計サイズは 2GB を超えることはできません。

コードデプロイの高速化と関数管理の簡素化

関数コードパッケージが小さいほど、コードパッケージのデプロイは高速になります。特に大規模な依存関係の場合、コア関数コードは数 MB であっても、依存関係は数百 MB に達することがあります。たとえば、Puppeter の依存パッケージは 100MB を超え、Alibaba Cloud DataX の依存パッケージは 800MB を超えます。

一般的に、これらの依存関係はあまり変更されないため、レイヤーにパッケージ化しておけば、コアコードの変更時に大規模な依存関係を頻繁に更新する手間を省けます。これらの依存関係を複数のレイヤーに分割し、関数を変更するたびに 1 つのレイヤーだけを更新するようにもできます。たとえば、カスタムランタイム Python 3.10 と互換性のある科学計算ライブラリ Scipy を実装する場合、カスタムランタイムと依存パッケージをそれぞれ別のレイヤーに分割できます。依存パッケージの更新時には、依存パッケージのレイヤーのみを更新すればよく、カスタムランタイムのレイヤーは変更不要です。

カスタムレイヤーの課題

レイヤー作成には一定のハードルがある

レイヤーの Zip パッケージには一定の形式仕様があり、ユーザーはこの仕様に従って作成する必要があります。Python の requests ライブラリを例にとると、パッケージ化後のファイル構造は以下のようになります。

my-layer-code.zip

└── python

└── requests

なぜこのような要件があるのでしょうか。これは、異なるランタイムでのサードパーティ依存パッケージの検索ロジックに関係します。たとえば、Python ランタイムは sys.path 内で依存パッケージを検索します。上記の Zip パッケージは関数インスタンスの /opt ディレクトリに展開されます。展開後、requests パッケージは /opt/python ディレクトリに配置されます。

次に、Function Compute プラットフォームは、ランタイム言語の依存検索パスに特定のディレクトリを追加します。たとえば、Python ランタイムは /opt/python を sys.path に追加するため、コード内で requests ライブラリを直接参照できます。他のランタイムでの使用方法については、ドキュメントを参照してカスタムレイヤーを作成してください。

もちろん、この形式仕様に従わずにレイヤーを作成することもできます。その場合は、コード内で対応する検索パスを追加する必要があります。詳しい方法については、ドキュメント「Custom Runtime でレイヤー内の依存関係を参照する方法」を参照してください。

レイヤーは指定されたオペレーティングシステムとプロセッサアーキテクチャで作成する必要があります。一部の依存関係は OS とプロセッサアーキテクチャに依存します。たとえば、Python の科学計算ライブラリ NumPy がそうです。M1 チップの macOS でインストールすると、そのバージョンは以下のようになります。

numpy-1.23.3-cp39-cp39-macosx_11_0_arm64

互換オペレーティングシステムは macOS、プロセッサアーキテクチャは arm64 であることがわかります。しかし、Function Compute プラットフォームのインスタンス環境は Linux x86_64 です。現在の OS ディストリビューションは Debian 9 であるため、M1 Mac でインストールした NumPy ライブラリは Alibaba Cloud Function Compute プラットフォームでは使用できません。

Debian 9 環境でのインストールを推奨しますが、ユーザーのローカル環境にこの環境がない場合もあります。オンラインの依存ライブラリビルドツールを利用するか、Function Compute の公式ランタイムイメージを使用して構築できます。ここでは詳細は省略します。

レイヤーには追加の共有動的ライブラリを含める必要があります。一部の依存ライブラリは追加の共有動的ライブラリのインストールを必要とし、レイヤーの Zip パッケージを構築する際にこれらの共有動的ライブラリも含める必要があります。たとえば、Node.js の依存ライブラリ Puppeter は 20 以上の追加共有動的ライブラリ(libxss1、libnspr4 など)のインストールを必要とし、これらをすべてレイヤーの Zip パッケージにパッケージングする必要があります。Puppeter ライブラリを正常にインストールする方法は、簡単なことではありません。

共有動的ライブラリは Zip パッケージの lib ディレクトリに配置することを推奨します。Function Compute プラットフォームは /opt/lib ディレクトリを LD_LIBRARY_PATH に追加します(組み込みランタイムのみ)。

アカウント間共有ができない

カスタムレイヤーは、デフォルトでは同じアカウントかつ同じリージョン内の異なる関数間でのみ共有可能であり、アカウント間での共有はできません。そのため、ユーザー A が作成したカスタムレイヤーをユーザー B が使用できず、ユーザーにとって重複作業をもたらすだけでなく、同じレイヤーのホスト上での再利用にも不利です。

パブリックレイヤー

カスタムレイヤーのこれらの課題を解決するため、Alibaba Cloud Function Compute は 2022 年 8 月にパブリックレイヤー機能をリリースしました。レイヤー間のアカウント間共有を実現し、ユーザーが直接利用できる公式パブリックレイヤーを提供することで、ユーザーが迅速にサンプルプロトタイプを開発できるようにしました。

Alibaba Cloud Function Compute プラットフォームは、主に 3 種類の公式パブリックレイヤーを提供しています。

・ カスタムランタイム(Python 3.10、Nodejs17、PHP 8.1、Java17、.NET 6 など)

・ 共通依存ライブラリ(PyTorch、Scipy、Puppeter など)

・ AliCloud SDK(AliCloud DataX など)

詳細については、公式ドキュメントを参照して、関数に公式パブリックレイヤーを設定してください。現在、公式パブリックレイヤーは引き続き拡充中です。公式パブリックレイヤーを通じて利用したいランタイムや依存ライブラリがある場合は、DingTalk 答疑グループ(グループ番号:11721331)からご連絡いただくか、github.com/awesome-fc/awesome-layers で直接 Issue を提出してください。

カスタムレイヤーの公開方法

現在、レイヤー公開機能は内部テスト中です。ご利用の必要がある場合は、DingTalk 答疑グループ(グループ番号:11721331)からご連絡ください。カスタムレイヤーの公開方法については、github.com/awesome-fc/awesome-layers を参照してください。

同時に、パブリックレイヤーをリポジトリ github.com/awesome-fc/awesome-layers にコントリビュートしていただくことも歓迎します。近く、リポジトリ内でパブリックレイヤーのコントリビューション方法とサンプルを提供する予定です。

使用例

公式パブリックレイヤーの最新バージョンと使用説明については、github.com/awesome-fc/awesome-layers を参照してください。ここでは、公式パブリックレイヤーを使用した代表的な例をいくつか紹介します。

使用例 1. Nodejs16 + Puppeter を使用したウェブページスクリーンショットのサンプルプログラム

Puppeter は、DevTools プロトコルを通じて Chrome(または Chromium)を制御する高度な API を提供する Node.js ライブラリです。一般的にはヘッドレス Chrome ブラウザであり、以下のような多くの自動化タスクを実行できます。

・ スクリーンショットや PDF の生成

・ フォームの自動送信、UI の自動テスト、キーボード入力のシミュレーションなど

・ その他多数...

この例では、Puppeter を使用してウェブページスクリーンショットのサンプルプログラムを作成します。

まず、組み込みランタイム Nodejs16 を使用して「start-poppeter」という関数を作成します。リクエストハンドラのタイプは「HTTP リクエストの処理」を選択します。

次に、詳細設定でメモリ仕様を 1GB に設定します。サンプルプログラムのメモリ使用量は約 550MB です。

作成が成功したら、コンソールで index.js ファイルを開き、以下のコードをコピーして上書きし、デプロイボタンをクリックします。

上記のコアロジックを簡単に説明します。まず、コードはクエリパラメーターを解析してスクリーンショット対象の URL アドレスを取得します(解析に失敗した場合は、デフォルトで Serverless Devs 公式ウェブサイトのホームページが使用されます)。次に、Puppeter を使用してウェブページのスクリーンショットを撮り、実行中のインスタンスの /tmp/example に保存してから、そのファイルを HTTP リクエストのレスポンスボディとして直接返します。

次に、Puppeter パブリックレイヤーを設定する必要があります。関数設定でレイヤーセクションを見つけ、編集をクリックし、公式パブリックレイヤーの追加を選択します。

使用例 2. 共通レイヤーを使用した .NET 6 カスタムランタイムの迅速な実装

まず、コンソールから .NET 6 のカスタムランタイムを作成します。画面上部で「カスタムランタイムを使用して作成」を選択し、「HTTP リクエストの処理」を選択し、.NET 6 ランタイムを選択します。その他の設定はデフォルト値を使用します。

作成が成功したら、WebIDE でサンプルコード Program.cs を確認できます。

サンプルコードには 4 つの注意点があります。

・ この例では 0.0.0.0 のポート 9000 をリッスンします。Custom Runtime で起動するサービスは、必ず 0.0.0.0:CAPort または *:CAPort ポートをリッスンする必要があり、127.0.0.1 や localhost は使用できません。詳細はドキュメント「Custom Runtime > 基本原則」を参照してください。

・ ルート / を追加し、文字列「Hello World。」を直接返します。

・ ルート /invoke を追加します。これはイベントリクエストハンドラーを使用する際のパスです。詳細はドキュメント「Custom Runtime > イベントハンドラ」を参照してください。

・ ルート /initialize を追加します。これは関数の初期化コールバックプログラムに対応するパスです。このメソッドはサンプルの初期化時に一度だけ実行されます。詳細はドキュメント「Custom Runtime > 関数インスタンスのライフサイクルコールバック」を参照してください。

まず、トリガー管理ページのテストアドレスを使用して直接テストします。この時点では PATH 情報を追加しません。結果は以下の図のようになります。

次に、/invoke パスを追加してテストします。このルーティングメソッドは POST なので、curl -XPOST を使用して直接テストします。

同じ方法で /initialize もテストしてみましょう。

注意:これはテストのためだけです。初期化コールバック関数は自ら呼び出す必要はありません。Function Compute プラットフォームはインスタンス起動後に自動的にコールバックメソッドを呼び出します(設定で初期化コールバックプログラムを有効にすることを忘れないでください)。

最後に、もう一つ小さなテストをしてみましょう。トリガー管理ページで HTTP トリガーを削除します。削除後、関数タイプはイベントリクエストハンドラーに変換されます。関数設定で初期化コールバックプログラムを有効にします。

コンソールで関数をテストすると、結果は以下の図のようになります。

リアルタイムログボタンをクリックすると、リクエスト実行前に Initialize コールバックメソッドが実行されたことを確認できます。

レイヤーのベストプラクティス

前のセクションでは、カスタムレイヤーとは何か、カスタムレイヤーを使用する理由、パブリックレイヤーとは何かを紹介し、公式パブリックレイヤーを使用した 2 つの使用例も紹介しました。しかし、レイヤーの使用についてまだいくつかの疑問が残っているかもしれません。たとえば、どのようなシナリオでレイヤーの使用を推奨するのか。レイヤーとコードパッケージの違いは何か。レイヤーに類似した機能はあるのか。これらの類似機能と比較して、レイヤーのメリットとデメリットは何か。以下でこれらの質問に答えていきます。

どのようなシナリオでレイヤーが推奨されるか

現在、レイヤーを使用するシナリオは主に 2 つのカテゴリに分けられます。1 つはユーザー定義ランタイム、もう 1 つは各言語の依存ライブラリです。ユーザー定義ランタイムについては、レイヤーでの構築と使用を強く推奨しますが、各言語の依存ライブラリについては、以下の推奨事項を参照してください。

・ 公式パブリックレイヤーの優先利用を推奨します

・ コンパイル不要な言語の依存ライブラリはレイヤーでの管理を推奨します。コンパイラ言語は実際の状況に応じて判断する必要があります(たとえば、カスタムランタイムで Java プログラムを JAR パッケージで実行する場合、レイヤー内の依存関係を導入できません。ドキュメント「Custom Runtime でレイヤー内の依存関係を参照する方法」を参照してください)

・ 依存ライブラリが大きく、レイヤーのサイズ制限を超えない場合は、レイヤーの使用を推奨します

・ 依存ライブラリが追加の共有動的ライブラリのインストールを必要とする場合は、レイヤーの使用を推奨します(構築が複雑な場合は、Function Compute チームに連絡して作成を依頼してください)

・ 複数関数やアカウント間でコードやデータを共有する必要がある場合は、レイヤーの使用を推奨します

レイヤーとコードパッケージの違い

直感的には、レイヤーは元のコパッケージの一部を分割して新しいコードパッケージを構築するだけです。なぜレイヤーを構築するのでしょうか。ここでの主な違いは、レイヤーとコードパッケージの設計思想が異なることにあります。

・ レイヤーはよりシンプルなバージョン管理方式を備えています

レイヤーのバージョンは 1 から自動的にインクリメントされます。現在、1 つのレイヤーは最大 100 の利用可能なバージョンをサポートできます(削除されたバージョンを除く)。一方、コードパッケージにはバージョンの概念がなく、サービスレベルでのみ管理されます。相対的なレベルでのバージョン管理はより複雑になります。

・ レイヤーバージョンは読み取り専用で不変です

レイヤーの内容は作成後に変更できません(権限を除く)。レイヤーの内容を変更したい場合は、新しいバージョンを公開するしかありません。レイヤーバージョンの読み取り専用機能により、レイヤー変更が関数に与える影響を回避できます。

・ レイヤーの共有機能

レイヤーは関数間およびアカウント間で共有可能ですが、コードパッケージは共有をサポートしていません。

・ レイヤーバージョンのソフト削除ポリシー

レイヤーバージョンを削除しても、既にそのレイヤーバージョンが設定されている関数の正常な動作には影響しません。なぜなら、レイヤーバージョンを削除する際、Alibaba Cloud Function Compute プラットフォームはレイヤーバージョンのコードを直接削除せず、まずソフト削除操作を実行するからです。これにより、削除されたレイヤーバージョンが新しい関数に使用されるのを防ぎます。そのレイヤーバージョンを参照する関数がなくなった時点で初めて、レイヤーバージョンを完全に削除できます。

おわりに

Alibaba Cloud Function Compute において、レイヤーの位置づけは不変のインフラストラクチャです。レイヤーバージョンの読み取り専用性により、レイヤーの一貫性と信頼性が保証されます。本記事では、まずカスタムレイヤーの特徴と課題を紹介し、次に最近リリースされたパブリックレイヤー機能について紹介し、公式パブリックレイヤーを使用して実装した 2 つのサンプルプログラムを詳しく解説し、最後にレイヤーのベストプラクティスについて議論しました。読者の皆様が本記事を通じて、レイヤーの概念とその応用シナリオをより深く理解できるよう願っています。

レイヤー機能は引き続き改善中です。今後は以下の方向性に焦点を当てて最適化していく予定です。

・ 公式パブリックレイヤーの体験を向上させ、より多くの共通依存ライブラリやカスタムランタイムを公式パブリックレイヤーとして追加し、完全なアプリケーションサンプルを提供します。

・ パブリックレイヤーのコントリビューション方法とサンプルを提供し、パブリックレイヤーのオープンソース化と共同構築を推進します。

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00

phone お問い合わせ
Hi, I'm Alibaba Cloud AI Assistant!
I can help with questions and solutions.