Nie*_*sma 3 .net c# front-controller ihttphandler
我正在开发一个基于Martin Fowler(链接)模式的HTTP前端控制器.在我的情况下,控制器具有以下职责: - 解组封装的数据 - 授权请求 - 记录 - 将请求中继/转发到另一台服务器
以下是可能的解决方案: - (同步)IHttpHandler,使用WebClient或HttpWebRequest类转发请求 - (异步)IHttpListener(非IIS解决方案) - (异步)IHttpAsyncHandler
理想的情况是FC可以处理大量并发请求(> 10000 TPS)而不会烧毁CPU.
为了测试解决方案,我创建了一个小型框架,其中有3个客户端发出请求,一个位于中间的前端控制器和两个响应FC传递的请求的服务器.框架基准测试3场景,首先测试具有小有效载荷的快速响应,其次:具有大有效载荷(> 100KB)的快速响应以及最后具有慢响应(> 3秒)和小有效载荷的测试.
使用同步HTTP处理程序进行的最后一次测试,每秒事务数(TPS)降至最低值(<25 TPS).我的猜测是,这是由于处理程序在等待响应时阻塞线程.为了克服这个问题,我开始实现一个异步处理程序(参见下面的代码).问题是,它简单无效.
想到的最后一个(未经测试的)解决方案是使用HttpListener类.猜测这是一个更轻量级的解决方案,具有良好的粒度控制并发性.我已经看过使用JoséF.Romaniello(链接)的RX框架的示例实现.
我的问题是这样,为什么处理程序代码不起作用?,这是最有效的方法吗?或者我应该赞成HttpListener解决方案.
异步HTTP处理程序代码:
public class ForwardRequestHandler : IHttpAsyncHandler
{
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
var uri = GetForwardUriFor(context.Request.Url.PathAndQuery);
var proxy = HttpWebRequest.Create(uri) as HttpWebRequest;
return proxy.BeginGetResponse(new AsyncCallback(EndProcessRequest), new ForwardedRequestContext(context, proxy));
}
public void EndProcessRequest(IAsyncResult result)
{
var proxy = result.AsyncState as ForwardedRequestContext;
proxy.TransferResponse(result);
}
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
throw new NotSupportedException();
}
private Uri GetForwardUriFor(string path)
{
var loadbalancer = new RoundRobinLoadBalancer();
var endpoint = loadbalancer.GetRandomEndPoint();
return new Uri(
string.Format("http://{0}{1}", endpoint, path)
);
}
}
public class ForwardedRequestContext
{
private readonly HttpContext context;
private readonly HttpWebRequest forwarder;
public ForwardedRequestContext(HttpContext context, HttpWebRequest forwarder)
{
this.context = context;
this.forwarder = forwarder;
}
public void TransferResponse(IAsyncResult ar)
{
var response = GetResponse();
var result = forwarder.EndGetResponse(ar);
response.StatusCode = 200;
response.ContentType = result.ContentType;
response.AddHeader("Content-Length", result.ContentLength.ToString());
result.GetResponseStream().CopyTo(response.OutputStream);
response.Flush();
result.Close();
}
private HttpResponse GetResponse()
{
return context.Response;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
在return proxy.BeginGetResponse(new AsyncCallback(EndProcessRequest), ...你创建一个新的回调,ASP.net没有得到关于请求结束的通知,因此它无法停止处理thre请求(这至少是我通过许多并发请求观察到的).因此,请使用作为参数传入的回调.
return proxy.BeginGetResponse(cb, ...
Run Code Online (Sandbox Code Playgroud)
干杯
| 归档时间: |
|
| 查看次数: |
2591 次 |
| 最近记录: |