Introduction
When using<span><span>HttpWebRequest</span></span> to initiate HTTP requests in C#, you can improve concurrency and performance in the following ways:
1. ServicePointManager Settings
<span><span>ServicePointManager</span></span> is a static class that provides properties and methods for managing HTTP connections. To enhance concurrent performance, you need to adjust the following key properties:
DefaultConnectionLimit: By default, the .NET Framework’s<span><span>ServicePointManager</span></span> limits the number of concurrent connections to the same domain (usually 2). You can increase this limit to allow for more concurrent connections.
ServicePointManager.DefaultConnectionLimit = 100; // A suitable value, e.g., 100
Expect100Continue: When you send a POST request, .NET first sends a request with the<span><span>Expect: 100-continue</span></span> header to ask the server if it is willing to accept the data. Disabling this option may improve performance.
ServicePointManager.Expect100Continue = false;
ReusePort: This is a setting in .NET Core. If you are using .NET Core, enabling this setting allows different HTTP requests to reuse the same local port.
ServicePointManager.ReusePort = true;
2. Asynchronous Programming Model
Using asynchronous methods of<span><span>HttpWebRequest</span></span>, such as<span><span>BeginGetResponse</span></span> and <span><span>EndGetResponse</span></span> or <span><span>GetResponseAsync</span></span>, allows your application to remain non-blocking while waiting for HTTP responses, which is crucial for improving concurrent performance.
3. Resource Utilization and Release
Ensure that you promptly release<span><span>HttpWebResponse</span></span> objects and other resources after the request is completed to avoid unnecessary resource consumption and memory leaks.
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { // Process response }
4. Parallel Processing
In .NET, you can use the<span><span>Parallel</span></span> class or the <span><span>Task</span></span> class to send multiple requests in parallel.
var tasks = urls.Select(url => Task.Run(() => {
// Send request using HttpWebRequest })).ToArray();
Task.WaitAll(tasks); // Wait for all requests to complete
5. Use HttpClient
If possible, consider using the<span><span>HttpClient</span></span> class instead of<span><span>HttpWebRequest</span></span>.
<span><span>HttpClient</span></span> is a more modern HTTP client that provides a cleaner API, better asynchronous support, and is configured by default for higher concurrent connection limits.
using (var client = new HttpClient()) { // Send request }
6. System-Level Configuration
Sometimes, operating system-level settings can also affect HTTP concurrent performance. For example, on Windows, you may need to adjust the<span><span>MaxUserPort</span></span> and <span><span>TcpTimedWaitDelay</span></span> values in the registry to increase the number of available ports and reduce the wait time before ports are released.
In Windows,<span><span>MaxUserPort</span></span> is a registry entry that determines the maximum user port number available. By default, the value of<span><span>MaxUserPort</span></span> is typically set to 5000, meaning the TCP/IP stack will use port numbers between 1024 and 5000 for user TCP/UDP connections.
If you need to adjust the value of<span><span>MaxUserPort</span></span> (for example, if you want to allow more concurrent network connections), you can modify it using the registry editor (regedit). Typically, the value of<span><span>MaxUserPort</span></span> is located at the following registry path:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters
After modifying the value of<span><span>MaxUserPort</span></span>, you usually need to restart the Windows operating system for the changes to take effect, as the TCP/IP stack needs to reload the configuration parameters.
For high-concurrency applications, the<span><span>MaxUserPort</span></span> value can be set higher to allow the system to open more dynamic ports. Theoretically, this value can be set to 65534 (since 0 to 1023 are reserved ports, and 65535 is the maximum port number), but in practice, the recommended maximum value is usually lower than this theoretical limit.
In practice, many Windows server administrators may set the<span><span>MaxUserPort</span></span> between 10000 and 60000, depending on application needs and system and network environments. Microsoft’s official documentation has suggested setting<span><span>MaxUserPort</span></span> to 32768, but this is not a hard limit, and actual applications should be set according to specific circumstances.
Be cautious when setting<span><span>MaxUserPort</span></span>, as very high values may lead to increased consumption of system resources (such as memory and handles). Additionally, this change may affect network security policies. Therefore, it is best to evaluate the actual needs of the application before adjusting this value and conduct thorough testing in a test environment.
After modifying<span><span>MaxUserPort</span></span>, you need to restart the system for the settings to take effect. It is also recommended to adjust the<span><span>TcpTimedWaitDelay</span></span> registry entry together, which can help recover ports in the TIME_WAIT state more quickly, allowing the system to reuse these ports. By default, the value of<span><span>TcpTimedWaitDelay</span></span> is 240 seconds, but it can be reduced to 30-60 seconds, especially in high-concurrency environments, which can help reduce connection issues caused by port exhaustion.
<span><span>TcpTimedWaitDelay</span></span> is an entry in the Windows registry that controls the time a port remains in the TIME_WAIT state after a TCP connection is closed. The TIME_WAIT state is a holding state after a TCP connection is terminated, ensuring that the final acknowledgment packet can arrive. This time is set to 240 seconds by default.
Reducing the value of<span><span>TcpTimedWaitDelay</span></span> can speed up port recovery, which is beneficial for high-concurrency applications that need to handle a large number of short connections. Typical settings for<span><span>TcpTimedWaitDelay</span></span> range between 30 seconds and 120 seconds.
To set<span><span>TcpTimedWaitDelay</span></span>, follow these steps:
1. Open the registry editor (<span><span>regedit</span></span>). This can be done by searching for “regedit” in the start menu or by pressing <span><span>Win + R</span></span> to open the run window, then typing <span><span>regedit</span></span> and pressing enter.
2. Navigate to the following path:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters
3. Look for the<span><span>TcpTimedWaitDelay</span></span> key value. If it does not exist, you need to create it:
4. Right-click on the<span><span>Parameters</span></span> directory, select <span><span>New</span></span> -> <span><span>DWORD (32-bit) Value</span></span>.
5. Name the newly created key value as <span><span>TcpTimedWaitDelay</span></span>.
6. Double-click the<span><span>TcpTimedWaitDelay</span></span> key value, then enter the number of seconds you wish to set in the “Value data” box (make sure you select decimal instead of hexadecimal).
7. Click “OK” to save the changes.
8. Close the registry editor.
9. To make the changes effective, you need to restart your computer.
Before adjusting<span><span>TcpTimedWaitDelay</span></span>, ensure you understand the impact of the changes and conduct thorough testing in a test environment before making changes in a production environment. Improper settings may lead to unexpected behavior, such as potential network issues or performance degradation.
7. Server Settings
The improvement of client performance also depends on server-side configuration. Ensure that the server can handle high concurrent connections and requests.
8. Performance Testing
Use stress testing tools (such as JMeter or LoadRunner) to perform stress tests on your application to determine the optimal concurrent settings. Testing can reveal performance bottlenecks, allowing you to adjust settings accordingly.
Notes
1. Setting<span><span>ServicePointManager.DefaultConnectionLimit</span></span> too high may increase server pressure and even lead to denial of service; it should be set cautiously based on actual conditions.
2. In high-concurrency scenarios,<span><span>HttpClient</span></span> is usually a better choice than<span><span>HttpWebRequest</span></span>.
3. When using asynchronous programming patterns, ensure you understand the async and await keywords to avoid common pitfalls, such as deadlocks.
Source: Eric Zhou
Link: cnblogs.com/tianqing/p/17868395.html
Reply [Close]Learn to permanently close app splash adsReply [Delete]Learn to automatically detect which WeChat friends have been deleted or blockedReply [Manual]Get a 30,000-word .NET, C# engineer interview manualReply [Help]Get 100+ commonly used C# helper librariesReply [Join Group]Join the DotNet learning exchange group