我正在使用 System.Net.HttpListener BeginGetContext/EndGetContext 来同时处理多个 http 请求。这在我的 16 核 Windows 7 SP1 桌面上运行良好,它同时处理 16 个请求。在 Windows Server 2012 R2 16 处理器 VM 上,20 个请求中的前 2 个是并发处理的,然后是顺序处理的请求,例如第三个请求的响应必须在查看第四个请求的请求之前发送。
我希望服务器以类似于桌面 m/c 的方式处理请求。在 8 秒内处理 20 个请求,而不是当前的 95 秒。
以下日志显示了 Windows 7 机器上的行为(良好)。客户端和服务器进程都在 Windows 7 m/c 上运行。
这是客户端日志。每行包含客户端的原始请求,服务器回显并加上服务器处理请求的时间。原始请求包含序列号和客户端发出请求的时间。
请注意,所有请求均在整点 12:46 分发出,16 点在 12:51 得到响应,最后一个在 12:54 得到响应。
http://localhost:8894/dostuff?val=1-client-12:46-server-12:51
http://localhost:8894/dostuff?val=17-client-12:46-server-12:51
http://localhost:8894/dostuff?val=15-client-12:46-server-12:51
http://localhost:8894/dostuff?val=2-client-12:46-server-12:51
http://localhost:8894/dostuff?val=7-client-12:46-server-12:51
http://localhost:8894/dostuff?val=3-client-12:46-server-12:51
http://localhost:8894/dostuff?val=13-client-12:46-server-12:51
http://localhost:8894/dostuff?val=18-client-12:46-server-12:51
http://localhost:8894/dostuff?val=9-client-12:46-server-12:51
http://localhost:8894/dostuff?val=14-client-12:46-server-12:51
http://localhost:8894/dostuff?val=0-client-12:46-server-12:51
http://localhost:8894/dostuff?val=6-client-12:46-server-12:51
http://localhost:8894/dostuff?val=10-client-12:46-server-12:51
http://localhost:8894/dostuff?val=5-client-12:46-server-12:51
http://localhost:8894/dostuff?val=19-client-12:46-server-12:51
http://localhost:8894/dostuff?val=11-client-12:46-server-12:51
http://localhost:8894/dostuff?val=12-client-12:46-server-12:52
http://localhost:8894/dostuff?val=16-client-12:46-server-12:53
http://localhost:8894/dostuff?val=8-client-12:46-server-12:53
http://localhost:8894/dostuff?val=4-client-12:46-server-12:54
以下日志显示了 Windows Server 2012 计算机上的行为(错误)。客户端和服务器进程都在 Windows Server 2012 m/c 上运行。
请注意,前 2 个请求是并发处理的,但每个后续请求需要连续 5 秒。
请注意,前 2 个请求是并发处理的,但每个后续请求需要连续 5 秒。所有请求均在整点后 46 分 39 秒发送。前 2 个请求在每小时 46 分 44 秒得到响应,但最后一个响应在每小时 48 分 14 秒收到。
http://localhost:8895/dostuff?val=5-client-46:39-server-46:44
http://localhost:8895/dostuff?val=1-client-46:39-server-46:44
http://localhost:8895/dostuff?val=2-client-46:39-server-46:49
http://localhost:8895/dostuff?val=6-client-46:39-server-46:54
http://localhost:8895/dostuff?val=3-client-46:39-server-46:59
http://localhost:8895/dostuff?val=4-client-46:39-server-47:4
http://localhost:8895/dostuff?val=7-client-46:39-server-47:9
http://localhost:8895/dostuff?val=9-client-46:39-server-47:14
http://localhost:8895/dostuff?val=8-client-46:39-server-47:19
http://localhost:8895/dostuff?val=10-client-46:39-server-47:24
http://localhost:8895/dostuff?val=11-client-46:39-server-47:29
http://localhost:8895/dostuff?val=12-client-46:39-server-47:34
http://localhost:8895/dostuff?val=13-client-46:39-server-47:39
http://localhost:8895/dostuff?val=14-client-46:39-server-47:44
http://localhost:8895/dostuff?val=15-client-46:39-server-47:49
http://localhost:8895/dostuff?val=16-client-46:39-server-47:54
http://localhost:8895/dostuff?val=18-client-46:39-server-47:59
http://localhost:8895/dostuff?val=17-client-46:39-server-48:4
http://localhost:8895/dostuff?val=19-client-46:39-server-48:9
http://localhost:8895/dostuff?val=0-client-46:39-server-48:14
下面的代码可能会提供一些线索,但我怀疑它更有可能是服务器上的一些配额或节流问题。
// SERVER build with "csc program.cs" run as program.exe
using System;
using System.Net;
using System.Text;
using System.Threading;
class Program
{
static void Main(string[] args)
{
HttpListener listenerLocal = new HttpListener();
listenerLocal.Prefixes.Add("http://*:8895/");
listenerLocal.Start();
while (true)
{
//var result = listener.BeginGetContext(RequestCallback, listener);
var resultLocal = listenerLocal.BeginGetContext((result) =>
{
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
Thread.Sleep(5000);
byte[] buffer = Encoding.UTF8.GetBytes(
context.Request.Url.OriginalString + string.Format(
"-server-{0}:{1}", DateTime.Now.Minute, DateTime.Now.Second));
context.Response.ContentLength64 = buffer.Length;
System.IO.Stream output = context.Response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}
, listenerLocal);
resultLocal.AsyncWaitHandle.WaitOne();
}
}
}
// CLIENT build with "csc program.cs" run as program.exe
using System;
class Program
{
static void Main(string[] args)
{
for (int ii = 0; ii < 20; ii++)
{
var thr = new System.Threading.Thread((ctr) =>
{
var data = new System.Net.WebClient().OpenRead(
string.Format("http://localhost:8895/dostuff?val={0}-client-{1}:{2}"
,ctr, DateTime.Now.Minute, DateTime.Now.Second));
var reader = new System.IO.StreamReader(data);
Console.WriteLine(reader.ReadToEnd());
data.Close();
reader.Close();
});
thr.Start(ii);
}
Console.ReadLine();
}
}
最佳答案
ThreadPool
不是突发任务的最佳选择,您可以使用普通的 Thread
将它用于您的服务器
using System;
using System.Text;
using System.Net;
using System.Threading;
class Program
{
static void Main(string[] args)
{
HttpListener listenerLocal = new HttpListener();
listenerLocal.Prefixes.Add("http://*:8895/");
listenerLocal.Start();
int count = 0;
while (true)
{
if (count == 20)
continue;
Interlocked.Increment(ref count);
var thr = new Thread(ctr =>
{
var l = ctr as HttpListener;
HttpListenerContext context = l.GetContext();
Thread.Sleep(5000);
byte[] buffer = Encoding.UTF8.GetBytes(context.Request.Url.OriginalString + string.Format(
"-server-{0}:{1}", DateTime.Now.Minute, DateTime.Now.Second));
context.Response.ContentLength64 = buffer.Length;
System.IO.Stream output = context.Response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
Interlocked.Decrement(ref count);
});
thr.Start(listenerLocal);
}
}
}
关于.net - 异步使用的 HttpListener 同步运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36941154/