我们有一个缩略图生成的 lambda 函数,我正在尝试将其更新为 .NET Core 2.0,但是在使用 Microsoft 的 System.Drawing.Common
NuGet 包时遇到了以下错误:
TypeInitializationException
The type initializer for 'Gdip' threw an exception. at System.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0(Int32 width, Int32 height, Int32 stride, Int32 format, HandleRef scan0, IntPtr& bitmap) at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format) at 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':找不到指定的模块或其中的一个。 (HRESULT 异常:0x8007007E) at Interop.Libdl.dlopen(String fileName, Int32 flag) at System.Drawing.SafeNativeMethods.Gdip.LoadNativeLibrary() at System.Drawing.SafeNativeMethods.Gdip..cctor()
我看过这个问题,但没有解决方案。
复现此问题的最小代码如下:
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打包起来,但这也失败了,这次指出在libdgiplus.so中未找到入口点"GdiplusStartup"。这些文件不是来自Amazon Linux实例,因此我现在尝试安装Mono并从Amazon Linux实例获取它们。这没有帮助。
我尝试使用CoreCompat drawing library,但即使我尝试将其与函数捆绑在一起,它也会报告涉及libgdiplus.so的问题。
我之后在自己的Linux实例上尝试了一下,可以确认System.Drawing.Common有效。
有没有一些聪明的解决方案可以让我在AWS Lambda上使用System.Drawing.Common?还有其他方法可以欺骗我的lambda函数具有libdl并工作吗?
更新:
我们的最新尝试涉及使用AWS Lambda Layers,并小心地提取Docker Amazon Linux映像中apt安装的所有包,然后将其应用于它们自己的层。最终我们仍然遇到了“libdl”问题,所以我们放弃了。
人们建议的许多库的问题在于它们无法正确呈现日本文字,这对我们很重要。这似乎是一个不会在AWS Lambda上得到改善的问题,这没有帮助,最终更容易以Go重新编写我们的函数而不是继续使用C#。
由于下面的答案提到的库似乎适用于一般用途 - 可能现在支持日本文字 - 我选择接受我确信可以在AWS Lambda上工作的答案。
libdl.so
。请查看此链接:https://github.com/dotnet/corefx/issues/25102 - Gusman