.net HttpClient在服务器上启用缓存

.net HttpClient在服务器上启用缓存,.net,caching,asp.net-web-api,dotnet-httpclient,.net,Caching,Asp.net Web Api,Dotnet Httpclient,我正在尝试启用System.Net.HttpClient的客户端缓存。我有一个端点,需要1秒的响应时间,它会将缓存头发送回 如果我有这个密码 static async Task MainAsync() { var client = new HttpClient(new WebRequestHandler { CachePolicy = new HttpRequestCachePolicy() }) { BaseAddress = new Uri("http://localhost:83/

我正在尝试启用System.Net.HttpClient的客户端缓存。我有一个端点,需要1秒的响应时间,它会将缓存头发送回

如果我有这个密码

static async Task MainAsync()
{
    var client = new HttpClient(new WebRequestHandler { CachePolicy = new HttpRequestCachePolicy() }) { BaseAddress = new Uri("http://localhost:83/api/") };
    for (int i = 0; i < 20; i++)
    {
        var response = await client.GetAsync("test");
        var res = await response.Content.ReadAsStringAsync();
        Console.WriteLine(res);
    }
}
执行需要一秒钟

如果我将相同的代码放入api控制器中

    static HttpClient client = new HttpClient(new WebRequestHandler {CachePolicy = new HttpRequestCachePolicy() }) { BaseAddress = new Uri("http://localhost:83/api/") };
    public async Task<string> Get()
    {
        for (int i = 0; i < 20; i++)
        {
            var response = await client.GetAsync("test");
            var res = await response.Content.ReadAsStringAsync();
        }
        return "ok";
    }
并将其托管在IIS中—响应需要20秒


要从服务器应用程序启用客户端缓存,我需要做什么?

网站运行的应用程序池没有与其关联的用户配置文件,或者配置文件中的某个位置禁止缓存

为了利用IIS中的缓存机制,您需要将用户配置文件与应用程序池相关联,以便您的网站可以利用该配置文件的临时文件文件夹。更多细节请参见Chris Oldwood的文章。MSDN第页的相关报价:

用户配置文件 IIS不会加载Windows用户配置文件,但某些应用程序可能会利用它来存储临时数据。SQL Express就是这样一个应用程序示例。但是,必须创建一个用户配置文件,以便在配置文件目录或注册表配置单元中存储临时数据。网络服务帐户的用户配置文件由系统创建,并且始终可用。但是,通过切换到唯一的应用程序池标识,系统不会创建任何用户配置文件。只有标准应用程序池DefaultAppPool和Classic.NET AppPool在磁盘上具有用户配置文件。如果管理员创建新的应用程序池,则不会创建用户配置文件

但是,如果需要,可以通过将LoadUserProfile属性设置为true,将IIS应用程序池配置为加载用户配置文件


嵌入式缓存机制也可以通过web或机器配置文件中的标志禁用。您也需要检查此设置,因为无法通过编程方式覆盖此设置。

网站运行的应用程序池没有与其关联的用户配置文件,或者配置文件中的某个位置禁止缓存

为了利用IIS中的缓存机制,您需要将用户配置文件与应用程序池相关联,以便您的网站可以利用该配置文件的临时文件文件夹。更多细节请参见Chris Oldwood的文章。MSDN第页的相关报价:

用户配置文件 IIS不会加载Windows用户配置文件,但某些应用程序可能会利用它来存储临时数据。SQL Express就是这样一个应用程序示例。但是,必须创建一个用户配置文件,以便在配置文件目录或注册表配置单元中存储临时数据。网络服务帐户的用户配置文件由系统创建,并且始终可用。但是,通过切换到唯一的应用程序池标识,系统不会创建任何用户配置文件。只有标准应用程序池DefaultAppPool和Classic.NET AppPool在磁盘上具有用户配置文件。如果管理员创建新的应用程序池,则不会创建用户配置文件

但是,如果需要,可以通过将LoadUserProfile属性设置为true,将IIS应用程序池配置为加载用户配置文件


嵌入式缓存机制也可以通过web或机器配置文件中的标志禁用。您也需要检查这一点,因为无法通过编程方式覆盖此设置。

您可能应该切换到WinHTTP并使用另一个HTTP缓存实现

.NET Framework使用两种HTTP客户端API。一个由WinINet提供,另一个由WinHTTP提供。NET Framework默认使用WinINet。但WinINet是为在客户端应用程序中工作而开发的,它不应该在服务器环境中工作。MSDN第页的相关报价:

如适用 WinINet不支持服务器实现。此外,不应从服务中使用它。用于服务器实现或服务使用

因此,在Web API中,您需要使用WinHTTP。我知道切换的唯一方法是使用NuGet包中的WinHttpHandler。但目前该处理程序不使用HTTP缓存。它无法设置缓存策略,并且会忽略HttpClientHandler尊重的所有设置。请参阅GitHub上的问题

要解决这个问题,您可以实现自己的缓存机制或使用现有的类似项目的缓存机制。它有内置内存存储和自己的HttpClient DelagatingHandler实现。 请注意,当前存在一些兼容性问题,在安装System.NET.Http.WinHttpHandler和CacheCow.Clien NuGet软件包之前,需要手动从Web API项目中删除对.NET Framework System.NET.Http的引用。以下截取的代码演示了从CacheCow.Clien NuGet包中使用WinHttpHandler和CachingHandler:

static HttpClient client = new HttpClient(new CachingHandler { InnerHandler = new WinHttpHandler() })
{
    BaseAddress = new Uri("http://localhost:83/api/")
};
有关更多信息,请查看:

和CC Hameed的文章 阿利奥斯塔德的文章 MSDN页面
可能您应该切换到WinHTTP并使用另一个HTTP缓存imp 营养素

.NET Framework使用两种HTTP客户端API。一个由WinINet提供,另一个由WinHTTP提供。NET Framework默认使用WinINet。但WinINet是为在客户端应用程序中工作而开发的,它不应该在服务器环境中工作。MSDN第页的相关报价:

如适用 WinINet不支持服务器实现。此外,不应从服务中使用它。用于服务器实现或服务使用

因此,在Web API中,您需要使用WinHTTP。我知道切换的唯一方法是使用NuGet包中的WinHttpHandler。但目前该处理程序不使用HTTP缓存。它无法设置缓存策略,并且会忽略HttpClientHandler尊重的所有设置。请参阅GitHub上的问题

要解决这个问题,您可以实现自己的缓存机制或使用现有的类似项目的缓存机制。它有内置内存存储和自己的HttpClient DelagatingHandler实现。 请注意,当前存在一些兼容性问题,在安装System.NET.Http.WinHttpHandler和CacheCow.Clien NuGet软件包之前,需要手动从Web API项目中删除对.NET Framework System.NET.Http的引用。以下截取的代码演示了从CacheCow.Clien NuGet包中使用WinHttpHandler和CachingHandler:

static HttpClient client = new HttpClient(new CachingHandler { InnerHandler = new WinHttpHandler() })
{
    BaseAddress = new Uri("http://localhost:83/api/")
};
有关更多信息,请查看:

和CC Hameed的文章 阿利奥斯塔德的文章 MSDN页面
作为重新配置服务器的替代方案,您可以自己缓存结果,也可以根据需要将其存储在会话中


话虽如此,您已经将异步调用转变为阻塞调用—您应该真正使用回调或承诺。

作为重新配置服务器的替代方法,您可以自己缓存结果—可能会根据需要将其存储在会话中


话虽如此,您已经将异步调用转变为阻塞调用—您真的应该使用回调或承诺。

我尝试以控制台代码段工作的同一用户的身份运行应用程序池。没有区别。LoadUserProfile为true。我还添加了web.config。没有区别。还有其他建议吗?您是否检查了网站运行的计算机上的web.config或machine.config中是否没有disableAllCaching=true?此外,您可能希望使用web调试代理来检查您的网站是否实际执行了20个请求,以及它们的响应代码是否为200而不是404。例如,disableAllCaching不在machine.config或web.config请求确实返回200和缓存头i尝试以控制台代码段工作的同一用户的身份运行应用程序池。没有区别。LoadUserProfile为true。我还添加了web.config。没有区别。还有其他建议吗?您是否检查了网站运行的计算机上的web.config或machine.config中是否没有disableAllCaching=true?此外,您可能希望使用web调试代理来检查您的网站是否实际执行了20个请求,以及它们的响应代码是否为200而不是404。例如,disableAllCaching不在machine.config或web.configAnd请求确实返回200,而cache headerDoesn并没有真正回答这个问题,此控制器的目的是阻止测试缓存是否工作。使用async/Await时不需要回调并不能真正回答问题,此控制器的目的是阻塞以测试缓存是否工作。使用async/await时不需要回调