web-dev-qa-db-ja.com

AWS LambdaでSystem.Drawing.Common NuGetパッケージを使用すると、DLL 'libdl'をロードできません

.NET Core 2.0に更新しようとしているサムネイルジェネレータラムダ関数がありますが、Microsoftの_System.Drawing.Common_ NuGetパッケージを使用すると、次のエラーが発生しました。

TypeInitializationException

'Gdip'のタイプ初期化子が例外をスローしました。 System.Drawing.Bitmap..ctor(Int32幅、Int32高さ、PixelFormat形式)でSystem.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0(Int32幅、Int32高さ、Int32ストライド、Int32フォーマット、HandleRef scan0、IntPtr&ビットマップ)でTestFailExampleで.Function.FunctionHandler(String input、ILambdaContext context)in C:\ work\graphics\TestFailExample\Function.cs:line 25 at lambda_method(Closure、Stream、Stream、LambdaContextInternal)

のせいで

DllNotFoundException

ロードできませんDLL 'libdl':指定されたモジュールまたはその依存関係の1つが見つかりませんでした。\ n(HRESULTからの例外:0x8007007E)at Interop.Libdl.dlopen(String fileName、Int32フラグ)System.Drawing.SafeNativeMethods.Gdip.LoadNativeLibrary()at System.Drawing.SafeNativeMethods.Gdip..cctor()

this の質問を見ましたが、解決策はありませんでした。

問題を再現するための最小のコードは次のとおりです。

_public string FunctionHandler(string input, ILambdaContext context)
{
    using (var bmp = new Bitmap(100, 100))
    {
        return bmp.Width.ToString();
    }
}
_

単に.NET Core 2.0 Lambda関数プロジェクトを作成し、_System.Drawing.Common_ NuGetパッケージへの参照を追加して、関数ハンドラーを上記のコードに置き換えます。 AWSでそれをチャックして実行すると、エラーが発生します。パッケージを参照しても実際に使用するまで問題は発生しませんが、これはコンパイラの最適化に影響する可能性があります。

MCVEをプロジェクトにパッケージ化してGitHub here にアップロードしました。これは、問題を再現するために実行する必要がある手順を簡略化するためです。

_/lib64/libdl.so.2_は存在するが、_/lib64/libdl.so_は存在しないことがわかります。シンボリックリンクは可能ではないようです(読み取り専用ファイルシステム)。どうすれば解決できるかわかりません。 _LD_LIBRARY_PATH_にフォルダーを作成して_/tmp_環境変数を使用し、関数が最初に行うようにファイルをそこにシンボリックリンクしてみました。残念ながら、ここではすべてのライブラリが検索されるため、関数はまったく実行されません。また、_LD_LIBRARY_PATH_を_/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/tmp_に設定してみましたが、関数を再度実行することはできましたが、それでも解決せず、同じGdipエラーが発生しました。

/ var/task/libはすでにLD_LIBRARY_PATHに含まれているので、libdl.soとlibgdiplus.soを関数でパッケージ化しようとしましたが、これも失敗しました。今回は、GdiplusStartupが_libdgiplus.so_。これらのファイルはAmazon Linuxインスタンスからのものではなかったため、Monoをインストールして、Amazon Linuxインスタンスから取得しようとしました。これは役に立ちませんでした。

CoreCompat drawing library を試してみましたが、これを_libgdiplus.so_に関連する問題を報告します。

それ以来、自分のLinuxインスタンスで試してみましたが、_System.Drawing.Common_が機能することを確認できます。

AWS Lambdaで_System.Drawing.Common_を使用できるいくつかの巧妙なソリューションはありますか? libdlを使用して機能するようにラムダ関数を変更する別の方法はありますか?

更新:

私たちの最新の試みには、AWS Lambdaレイヤーを使用し、aptによってインストールされたすべてのパッケージをDocker Amazon Linuxイメージ内で慎重に抽出し、それらを独自のレイヤーに適用することが含まれていました。それでも、最終的には「libdl」問題に到達したため、諦めました。

人々が提案したライブラリに関する多くの問題は、彼らが日本語のテキストを正しくレンダリングしなかったことであり、これは私たちにとって重要です。これはAWS Lambdaで改善されない問題のようで、役に立たなかったため、C#を引き続き使用するよりもGoで関数を書き直す方が簡単でした。

以下の回答で言及されているライブラリは一般的な使用に適しているようであり、実際に日本語のテキストをサポートしている可能性があるため、AWS Lambdaで確実に機能するという回答を受け入れることにしました。

15
John

.NET Core Lambdaでの画像処理には SixLabors.ImageSharp を使用します

以下は、最近のAWS re:Inventの講演で使用した、画像処理の場合にログを記録するコードです。

var imageBuffer = new MemoryStream();

var resizeOptions = new ResizeOptions
{
    Size = new SixLabors.Primitives.Size { Width = this.TileSize, Height = this.TileSize},
    Mode = ResizeMode.Stretch
};
image.Mutate(x => x.Resize(resizeOptions));
image.Save(imageBuffer, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder());

imageBuffer.Position = 0;
0
Norm Johanson

Dotnetコア2.1.500バージョンを実行しているUbuntu 18サーバーにアプリケーションをアップロードした後、同じ問題が発生しました。このソリューションでこの問題を解決しました https://github.com/dotnet/dotnet-docker/issues/618 MichaelSimonsの提案を使用して。

私は走った

#Sudo apt-get update
#Sudo apt-get install -y --allow-unauthenticated \
        libc6-dev \
        libgdiplus \
        libx11-dev \ 
#Sudo rm -rf /var/lib/apt/lists/*

これで問題は解決しました。

3
Fidelis Kalu

私はこの問題の解決策を見つけました:

最初にSystem.Drawing.Commonライブラリをプロジェクトから削除し、次にライブラリをインストールしました ここ 。同じクラスを使用します。

using System.Drawing
...
var bmp = new Bitmap(100,100);

ついに私は this LinuxとLambdaで描画ライブラリを使用するために必要なすべてのdllを含む他のライブラリをインストールしました。この手順を実行することで、コードを問題なくAWSにアップロードできます。

1
Alex HG