自定义 C# 模块与 Azure Function on Edge
Custom C# module vs. Azure Function on Edge
目前有两个主要选项可用于在 Azure IoT Edge 上创建基于代码的自定义模块:
- 自定义模块(目前是 .NET Core,很快 Python 等等)
- Azure Functions(目前只有 .NET Core)
所以现在我的问题是,当我想在 .NET Core (C#) 中编写自定义代码时,使用一个比另一个有什么好处?
函数所需的样板代码少得多,但性能等方面如何?
我不知道。让我们板凳! ...在 Windows 因为那是我手边的东西。 CPU 是酷睿 i7-3770K。
.NET Core Web API(v2.1.3,中间件是 dotnet new webapi
连接的任何东西)—
public class ValuesController : Controller
{
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
Azure Functions 脚本宿主 (v2.0.11587.0) —
// run.csx
public static IEnumerable<string> Run(HttpRequest req)
{
return new string[] { "value1", "value2" };
}
// host.json
// Default "consoleLevel" is verbose which blocks on flushing stdout,
// performance suffered unnecessarily so i switched to "error".
{
"tracing": {
"consoleLevel": "error",
"fileLoggingMode": "debugOnly"
}
}
结果:
// .NET Core Web API
C:\lab\bomb>bombardier-windows-amd64.exe -n 654321 http://127.0.0.1:5000/api/values
Bombarding http://127.0.0.1:5000/api/values with 654321 requests using 125 connections
654321 / 654321 [===================================] 100.00% 23s
Done!
Statistics Avg Stdev Max
Reqs/sec 27744.21 6713.91 124074.44
Latency 4.45ms 200.44us 46.97ms
HTTP codes:
1xx - 0, 2xx - 654321, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 6.69MB/s
// Functions script host with .csx
C:\lab\bomb>bombardier-windows-amd64.exe -n 654321 http://127.0.0.1:7071/api/HttpTrigger
Bombarding http://127.0.0.1:7071/api/HttpTrigger with 654321 requests using 125 connections
654321 / 654321 [===================================] 100.00% 5m31s
Done!
Statistics Avg Stdev Max
Reqs/sec 1976.64 181.69 4213.32
Latency 63.23ms 20.74ms 2.12s
HTTP codes:
1xx - 0, 2xx - 654321, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 492.23KB/s
为了科学起见,我也使用预编译函数 (.DLL) 对 v2 (.NET Core) 和 v1 (.NET Full Framework) 进行了测试 运行 运行时间。
TL;DR
.NET Core Web API (v2.1.3): 27744 requests/sec
Functions script host (v2.0.11587.0) .csx: 1976 requests/sec
Functions script host (v2.0.11587.0) precompiled DLL: 2062 requests/sec
Functions script host (v1.0.11535.0) precompiled DLL: 4734 requests/sec
YMMV。如果您实际上 c运行ch 一些 IO 而不仅仅是 return 16 字节,那么事情可能看起来会有所不同。但是它就是这样啊。如果您不需要 Functions 提供的额外功能,请使用原始 dotnet。
除了性能方面我没有得到更多答案,这是我最后的看法:
- 函数非常适合以下情况:
- 首先:代码不需要执行得太频繁(例如,不要通过函数路由所有消息),因为性能可能是一个限制因素
- 您的代码需要某种 HTTP 接口。只需使用 HTTP 触发函数,您无需担心在自定义代码中打开和维护 Web 服务器
- 您需要执行一些时间触发(预定)代码。构建一个时间触发函数,一切就绪
- 您不喜欢任何样板代码 ;-) 从您真正只需要编写和维护自己的代码的意义上来说,函数很棒。但由于自定义模块的模板带来了所有必需的样板代码,我不认为这是一个太大的优势。
对于任何其他自定义模块,我很可能会去构建您自己的东西。如前所述,从模板开始,编写自己的模块非常简单。
希望对其他人也有帮助! (这不是微软的官方回答;))
您可以在我的 github 存储库中找到一些不同触发边缘函数的示例:https://github.com/sebader/azureiotedge/tree/master/edge-functions
目前有两个主要选项可用于在 Azure IoT Edge 上创建基于代码的自定义模块:
- 自定义模块(目前是 .NET Core,很快 Python 等等)
- Azure Functions(目前只有 .NET Core)
所以现在我的问题是,当我想在 .NET Core (C#) 中编写自定义代码时,使用一个比另一个有什么好处?
函数所需的样板代码少得多,但性能等方面如何?
我不知道。让我们板凳! ...在 Windows 因为那是我手边的东西。 CPU 是酷睿 i7-3770K。
.NET Core Web API(v2.1.3,中间件是 dotnet new webapi
连接的任何东西)—
public class ValuesController : Controller
{
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
Azure Functions 脚本宿主 (v2.0.11587.0) —
// run.csx
public static IEnumerable<string> Run(HttpRequest req)
{
return new string[] { "value1", "value2" };
}
// host.json
// Default "consoleLevel" is verbose which blocks on flushing stdout,
// performance suffered unnecessarily so i switched to "error".
{
"tracing": {
"consoleLevel": "error",
"fileLoggingMode": "debugOnly"
}
}
结果:
// .NET Core Web API
C:\lab\bomb>bombardier-windows-amd64.exe -n 654321 http://127.0.0.1:5000/api/values
Bombarding http://127.0.0.1:5000/api/values with 654321 requests using 125 connections
654321 / 654321 [===================================] 100.00% 23s
Done!
Statistics Avg Stdev Max
Reqs/sec 27744.21 6713.91 124074.44
Latency 4.45ms 200.44us 46.97ms
HTTP codes:
1xx - 0, 2xx - 654321, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 6.69MB/s
// Functions script host with .csx
C:\lab\bomb>bombardier-windows-amd64.exe -n 654321 http://127.0.0.1:7071/api/HttpTrigger
Bombarding http://127.0.0.1:7071/api/HttpTrigger with 654321 requests using 125 connections
654321 / 654321 [===================================] 100.00% 5m31s
Done!
Statistics Avg Stdev Max
Reqs/sec 1976.64 181.69 4213.32
Latency 63.23ms 20.74ms 2.12s
HTTP codes:
1xx - 0, 2xx - 654321, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 492.23KB/s
为了科学起见,我也使用预编译函数 (.DLL) 对 v2 (.NET Core) 和 v1 (.NET Full Framework) 进行了测试 运行 运行时间。
TL;DR
.NET Core Web API (v2.1.3): 27744 requests/sec
Functions script host (v2.0.11587.0) .csx: 1976 requests/sec
Functions script host (v2.0.11587.0) precompiled DLL: 2062 requests/sec
Functions script host (v1.0.11535.0) precompiled DLL: 4734 requests/sec
YMMV。如果您实际上 c运行ch 一些 IO 而不仅仅是 return 16 字节,那么事情可能看起来会有所不同。但是它就是这样啊。如果您不需要 Functions 提供的额外功能,请使用原始 dotnet。
除了性能方面我没有得到更多答案,这是我最后的看法:
- 函数非常适合以下情况:
- 首先:代码不需要执行得太频繁(例如,不要通过函数路由所有消息),因为性能可能是一个限制因素
- 您的代码需要某种 HTTP 接口。只需使用 HTTP 触发函数,您无需担心在自定义代码中打开和维护 Web 服务器
- 您需要执行一些时间触发(预定)代码。构建一个时间触发函数,一切就绪
- 您不喜欢任何样板代码 ;-) 从您真正只需要编写和维护自己的代码的意义上来说,函数很棒。但由于自定义模块的模板带来了所有必需的样板代码,我不认为这是一个太大的优势。
对于任何其他自定义模块,我很可能会去构建您自己的东西。如前所述,从模板开始,编写自己的模块非常简单。
希望对其他人也有帮助! (这不是微软的官方回答;))
您可以在我的 github 存储库中找到一些不同触发边缘函数的示例:https://github.com/sebader/azureiotedge/tree/master/edge-functions