问题描述
在使用Azure Function时,启用了多个槽(slot),方便在部署生产环境的时候直接切换。
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", "Schedule_Timer": "*/30 * * * * *" } }
在使用C#进程外模式( dotnet-isolated )分别部署了生产槽和预生产槽后,发现预生产槽的Function启动日志中,由警告错误端口启用的消息:
ExtensionWarningEvent -- Failed to open local port 4001. This was attempt #1 to open a local port.
对比可以正常运行的生产槽日志,就是
[Information] Opened local gRPC endpoint: http://localhost:4001. InstanceId: . Function: . HubName:fun001slot. AppName: fun001. SlotName: 2ndslot. ExtensionVersion: 2.13.0. SequenceNumber: 0.
这个4001端口,是什么情况呢?
问题解答
端口 4001 用于与进程外模式(dotnet-isolated)的 gRPC 进程间通信的。
Function在运行的时候,会首先尝试绑定到 4001端口,因此它可能在大多数情况下都能正常绑定。但是,当该端口被占用时,它将开始尝试获取 30000 - 31000 范围内的随机端口。继续查看Failed to open local port 4001之后的日志,就可以发现它第二次尝试的时候,已经改变端口并绑定成功。
1)Failed to open local port 4001. This was attempt #1 to open a local port.. InstanceId: . Function: . HubName: fun001slot. AppName: fun001. SlotName: 2ndslot. ExtensionVersion: 2.13.0. SequenceNumber: 0.
2)Opened local gRPC endpoint: http://localhost:30721. InstanceId: . Function: . HubName: fun001slot. AppName: fun001. SlotName: 2ndslot. ExtensionVersion: 2.13.0. SequenceNumber: 1.
所以,这个错误只是一个警告。并不会影响Funciton的正常运行。
参考资料
Change Grpc port #145 : https://github.com/microsoft/durabletask-dotnet/issues/145
The functions extension code will first attempt to bind to 4001, so it may work for you most of the time. But when that port is reserved it will start trying to get random ports in the 30000 to 31000 range.