3

我们将服务堆栈用于 Web 服务 API。我们编写了一个“获取文件”例程来获取文件,而不是让 IIS 直接提供文件,因为我们需要服务器端身份验证逻辑。

我们RestServiceBase<Foo>.OnGet通过返回一个来返回一个文件IStreamWriter,它是这样实现的:

public void WriteTo(Stream responseStream)
{
    Stream filedata = File.OpenRead(_filepath);
    filedata.CopyTo(responseStream);
}

问题:这比 IIS 直接提供文件要慢 50% 到 100%。

我是否从服务堆栈错误地返回了文件?我可以做些什么来加快速度吗?


或者,有什么方法可以将我们的身份验证方案(我们希望完全无状态,因此在服务器机器上没有缓存凭据)插入 IIS,以便 IIS 以某种方式调用我们的服务器来验证每个请求,然后提供文件本身?

4

2 回答 2

2

本机代码与托管代码

IIS 将使用本机代码来提供静态文件,并且可能会采用一些积极的内存缓存来实现其性能。

由于 ServiceStack 是一个 .NET 库,其代码直接写入 ASP.NET 的响应流,因此在托管 .NET 代码中流式传输文件时更难获得更快的速度。您可以通过将文件加载到内存中并改为写入原始字节来进一步提高性能。

利用 HTTP 缓存

这就是为什么如果您必须使用托管代码,您应该尽最大努力利用 HTTP 缓存,这是我们在StaticFileHandler中所做的- 即 ServiceStack 用于提供其静态内容的内容,例如 css/js/html 页面。

注册一个原始 HttpHandler

尽管 ServiceStack 的请求管道已经过高度优化(即不会增加太多开销),但您仍然可以通过注册自己的自定义来绕过它并自己IHttpHandler处理原始 ASP.NET 请求 - 这将是 .NET 代码中最快的选项,例如:

SetConfig(new EndpointHostConfig { 
    RawHttpHandlers = { MiniProfilerHandler.MatchesRequest },
});

这就是内置 MiniProfiler 用来提供其静态内容的内容。MatchesRequest只需要计算IHttpRequest它是否应该处理请求(通过返回 IHttpHandler 的实例)或不(返回 null):

public static IHttpHandler MatchesRequest(IHttpRequest request)
{
    var file = Path.GetFileNameWithoutExtension(request.PathInfo);
    return file != null && file.StartsWith("ss-") 
        ? new MiniProfilerHandler()
        : null;
}

除此之外,ServiceStack 的独立版本(即 HttpListener 主机)应该提供比 ASP.NET 更好的原始吞吐量。

于 2012-08-07T21:20:33.373 回答
0

在 IIS I/O 线程到 CLR 线程池上的线程的上下文切换中存在惩罚,如果您将 (asp config) MaxConcurrentRequestsPerCPU 设置为 0 您的 CLR 代码,您应该能够减轻这种情况(可能有其他后果尽管)

请参阅 http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx

我不知道windows是否允许“零复制”:文件(从不离开内核模式并跳过套接字上的缓冲区到文件句柄操作)但如果支持,IIS肯定会使用它(使其比用户中的CLR更快模式 .. )

于 2012-08-08T10:07:46.643 回答