Investigating Socket exception for ASP.NET applications in Azure App Service
In Azure App Service, the number of outbound connections are restrictive based on the size of the VM. Below are the machine wide TCP limits (as documented here.)
Limit Name | Description | Small (A1) | Medium (A2) | Large (A3) |
---|---|---|---|---|
Connections | Number of connections across entire VM | 1920 | 3968 | 8064 |
When an application initiates an outbound connection to a database or a remote service, it uses the TCP connection from a range of allowed TCP connections on the machine. In some scenarios, the number of available outbound ports might get exhausted and when the applications tries to initiate a new connection request, it might fail with this error:
Exception Details: System.Net.Sockets.SocketException: An attempt was made to access a socket in a way forbidden by its access permissions.
COMMON REASONS THAT CAUSE THIS ERROR:
- Using client libraries which are not implemented to re-use TCP connections.
- Application code or the client library is leaking TCP socket handles.
- Burst load of requests opening too many TCP socket connections at once.
- In case of higher level protocol like HTTP this is encountered if the Keep-Alive option is not leveraged.
TROUBLESHOOTING:
For a .NET application,the below code-snippet will log the active outbound connections and details about the external service to which it is connecting. This will not log database related connections as they do not use System.Net. You can create a page PrintConnectionsSummary.aspx under the site and place it under /wwwroot folder. When the application encounters the socket exceptions, the users can browse to the page PrintConnectionsSummary.aspx to see the connection count to the remote services.
Download source file: Click here
NOTE: This will work only when the application is using System.Net namespace to make an outbound connections. |
Below screenshot depicts the above code-snippet in action. It is printing the external connections that the app might be connecting to (via System.net)