gpt4 book ai didi

c# - 使用 IHttpAsyncHandler 高效转发 HTTP 请求

转载 作者:行者123 更新时间:2023-11-30 14:37:01 39 4
gpt4 key购买 nike

我正在开发一个基于 Martin Fowler (link) 模式的 HTTP 前端 Controller 。就我而言, Controller 具有以下职责:- 解码封装数据- 授权请求- 记录- 将请求中继/转发到另一台服务器

想到以下可能的解决方案:- (同步)IHttpHandler,用WebClient或HttpWebRequest类转发请求- (异步)IHttpListener(非 IIS 解决方案)- (异步)IHttpAsyncHandler

理想情况是 FC 可以处理大量并发请求 (>10000 TPS) 而不会消耗 CPU。

为了测试解决方案,我创建了一个小型框架,其中有 3 个发出请求的客户端、一个位于中间的前端 Controller 和 2 个响应 FC 传递的请求的服务器。该框架对 3 种场景进行了基准测试,首先是使用小负载进行快速响应测试,其次是使用大负载(> 100KB)进行快速响应测试,最后是使用慢速响应(> 3 秒)和小负载进行测试。

在使用同步 HTTP 处理程序进行的最后一次测试中,每秒事务处理量 (TPS) 降至最低值 (<25 TPS)。我的猜测是这是由于处理程序在等待响应时阻塞了线程。为了克服这个问题,我开始实现一个异步处理程序(参见下面的代码)。问题是,它简单行不通。

想到的最后一个(未经测试的)解决方案是使用 HttpListener 类。猜测这是一个更轻量级的解决方案,具有对并发的细粒度控制。我看过 José F. Romaniello ( link ) 使用 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;
}
}

最佳答案

return proxy.BeginGetResponse(new AsyncCallback(EndProcessRequest), ... 中,您创建了一个新的回调,并且 ASP.net 没有收到有关请求结束的通知,因此它可以'不要停止处理 thre 请求(这至少是我从许多并发请求中观察到的)。因此请改用作为参数传入的回调。

return proxy.BeginGetResponse(cb, ...

干杯

关于c# - 使用 IHttpAsyncHandler 高效转发 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9800347/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com