What to do, when your Azure Function/Azure Web App application, after some time running, starts failing outgoing connections (e.g. HttpClient requests) on SocketException, but after restart your app starts to work.
System.Net.Sockets.SocketException
Exception while executing function Function1: An exception occurred while opening a connection to the server.
An attempt was made to access a socket in a way forbidden by its access permissions.
The reason for this error is simple – you reached your’s sandbox (Project Kudu) currently opened outcoming sockets limit and sandbox disabled access for new sockets.
Azure connection limits
Limits per App Service Plans:
App Service Plan | Connection Limit |
---|---|
Free F1 | 250 |
Shared D1 | 250 |
Basic B1 1 Instance | 1920 |
Basic B2 1 Instance | 3968 |
Basic B3 1 Instance | 8064 |
Standard S1 1 Instance | 1920 |
Standard S1 2 Instances | 1920 per instance |
Standard S2 1 Instance | 3968 |
Standard S3 1 Instance | 8064 |
Premium P1 1 Instance (Preview) | 1920 |
Source: azurefieldnotes.com
How to solve this issue
Reason 1 – You really need so much connections
In case you really need so much connections opened at once, you have to upgrade you App Plan, according to limits table above.
Reason 2 – You have bug in you app
Check, if your application closes all the opened connections. For example in my application, source of this issue were not-released sockets by HttpClient.
How to use HttpClient (also) in Azure Functions/Web apps correctly
DON’T DO:
public static class HowToNotUseHttpClientInFunction
{
[FunctionName("HowToNotUseHttpClientInFunction")]
public static async Task Run(List urls, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach(var url in urls)
{
using (var client = new HttpClient())
{
var result = await client.GetAsync(url);
Console.WriteLine(result.Content);
}
}
}
}
Wrapping up HTTPClient into using() section will not work as you probably think – even the application exits, sockets stay to be opened and they will wait for OS’s timeout, after it can be reused. So in this case, function is going to allocate 10 sockets and will release them after timeout. You can read more details on aspnetmonsters.com.
DO:
public static class HowToUseHttpClientInFunction
{
public static HttpClient client = new HttpClient();
[FunctionName("HowToUseHttpClientInFunction")]
public static async Task Run(List urls, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach (var url in urls)
{
var result = await client.GetAsync(url);
Console.WriteLine(result.Content);
}
}
}
This way will open only one connection and reuse it for all HTTP requests needed by application, so you will not probably reach Kudu’s limits.