从控制台程序插入 asp.net mvc outputcache
Insert to asp.net mvc outputcache from console program
我将 Redis 用于 asp.net MVC 输出缓存。我的一些视图需要进行相当多的处理,目前我有一个通宵流程,可以为视图生成所需的数据并将其放入 Redis 缓存中,以便视图可以更快地呈现,但是数据仅用于缓存中视图的初始渲染,然后视图由输出缓存配置缓存。
如果我可以只渲染视图并将其直接从隔夜控制台程序放入缓存中,那就更好了。我该怎么做?我想我需要使用 ASP.NET MVC 提供的相同密钥插入 Redis 并调用 asp.net MVC 使用的任何内部渲染方法?
我不需要插入到 Redis 的说明,而是我需要调用什么渲染方法以及如何为 asp.net MVC OutputCache 构造键名。
我正在使用 asp.net MVC 5,但是,如果您也可以回答 Core 以确保未来的答案,那就加分了!
请不要建议生成静态文件,那不是我想要的,谢谢。
How are the key names constructed for asp.net mvc outputcache?
这部分只要查阅source code for OutputCacheAttribute. The keys depend on the settings (e.g. the keys will have more data in them if you have set VaryByParam)就很容易回答。您可以通过检查属性如何为您的用例填充 uniqueID
来确定键。请注意,键被连接起来,然后进行哈希处理(因为它们可能会变得很长),然后进行 base64 编码。这是相关代码:
internal string GetChildActionUniqueId(ActionExecutingContext filterContext)
{
StringBuilder uniqueIdBuilder = new StringBuilder();
// Start with a prefix, presuming that we share the cache with other users
uniqueIdBuilder.Append(CacheKeyPrefix);
// Unique ID of the action description
uniqueIdBuilder.Append(filterContext.ActionDescriptor.UniqueId);
// Unique ID from the VaryByCustom settings, if any
uniqueIdBuilder.Append(DescriptorUtil.CreateUniqueId(VaryByCustom));
if (!String.IsNullOrEmpty(VaryByCustom))
{
string varyByCustomResult = filterContext.HttpContext.ApplicationInstance.GetVaryByCustomString(HttpContext.Current, VaryByCustom);
uniqueIdBuilder.Append(varyByCustomResult);
}
// Unique ID from the VaryByParam settings, if any
uniqueIdBuilder.Append(GetUniqueIdFromActionParameters(filterContext, SplitVaryByParam(VaryByParam)));
// The key is typically too long to be useful, so we use a cryptographic hash
// as the actual key (better randomization and key distribution, so small vary
// values will generate dramtically different keys).
using (SHA256Cng sha = new SHA256Cng())
{
return Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(uniqueIdBuilder.ToString())));
}
}
您稍后会注意到 uniqueID 用作进入内部缓存的键:
ChildActionCacheInternal.Add(uniqueId, capturedText, DateTimeOffset.UtcNow.AddSeconds(Duration));
What is the render method I need to call?
简答:ExecuteResult.
长答案:天哪,你在这里问了很多。本质上,您希望在控制台进程中实例化一些 objects 并调用方法,如果您从网站通常 运行s 的 AppDomain 中调用它,这些方法将忠实地重新创建输出。
Web 应用程序通常依赖于应用程序启动时创建的初始化和状态(例如设置组合 root/IoC,或设置 Automapper,诸如此类),因此您必须运行 初始化您的网站。特定视图可能依赖于上下文信息,例如 URL、cookie 和查询字符串参数;它可能依赖于配置;它可能会调用内部服务,这也依赖于配置,以及以某种方式设置的 AppDomain 帐户;它可能需要使用可能在服务帐户的个人存储中设置的客户端证书等内容。
以下是控制台应用程序必须执行的一般过程:
- 实例化站点的全局 object,调用其构造函数,这可能会尝试将事件连接到管道。
- 您将需要模拟管道并处理站点引发的任何事件。您还需要以模拟 ASP.NET 管道工作方式的方式引发事件。
- 您需要在 ASP.NET 管道中实施任何怪癖,例如除了引发事件之外,您还需要调用未订阅事件的处理程序,如果它们具有某些预定义的名称,例如
Application_Start
.
- 您需要通过构造或模拟管道 object 来模拟 HTTP 请求,例如
HttpContext
。
- 您需要以正确的顺序在您的代码中触发 request-specific 事件以模拟 HTTP 流量。
- 您将需要 运行 您的路由逻辑来确定要实例化的适当控制器,然后实例化它。
- 您需要从操作方法中读取元数据以确定要应用的过滤器,然后实例化它们,并允许它们订阅更多您必须发布的事件。
- 最后,您需要获取操作方法产生的
ActionResult
object 并调用其 ExecuteResult 方法。
我认为这不是一个可行的方法,但如果您成功了,我希望收到您的回复。
你真正应该做的事
您的控制台应用程序应该简单地在您的应用程序中触发 HTTP 请求,以符合最终用户实际使用情况的方式填充缓存。其他人都是这样做的。
如果您希望在缓存页面过期之前替换它,您可以通过重新启动应用程序池或使用 dependency.
使缓存失效
如果您担心您的响应时间统计数据,请更改您测量它们的方式,以便排除发生此刷新的任何时间 window。
如果您担心 Google 抓取的影响,您可以 modify the host load schedule 并在重置期间将其设置为 0 window。
如果您实在不想做网站
如果您坚持不想使用站点来创建缓存,我建议您让视图更轻量,并在您的应用程序中查看较低层的缓存。
例如,如果您的视图需要很长时间才能呈现的原因是它们必须 运行 具有大量连接的复杂查询,请考虑以非规范化 table.您可以 运行 SQL 代理作业每晚填充非规范化 table,从而刷新您的缓存。这样视图可以是轻量级的,您不必将它缓存在 Web 服务器上。
再比如,如果你的web应用调用了RESTful需要很长时间的服务到运行,考虑在你的服务中实现cache-controlheaders,修改您的 REST 客户端尊重它们,因此对相同表示的重复请求实际上不需要服务调用。参见 Caching your REST API。
我将 Redis 用于 asp.net MVC 输出缓存。我的一些视图需要进行相当多的处理,目前我有一个通宵流程,可以为视图生成所需的数据并将其放入 Redis 缓存中,以便视图可以更快地呈现,但是数据仅用于缓存中视图的初始渲染,然后视图由输出缓存配置缓存。
如果我可以只渲染视图并将其直接从隔夜控制台程序放入缓存中,那就更好了。我该怎么做?我想我需要使用 ASP.NET MVC 提供的相同密钥插入 Redis 并调用 asp.net MVC 使用的任何内部渲染方法?
我不需要插入到 Redis 的说明,而是我需要调用什么渲染方法以及如何为 asp.net MVC OutputCache 构造键名。
我正在使用 asp.net MVC 5,但是,如果您也可以回答 Core 以确保未来的答案,那就加分了!
请不要建议生成静态文件,那不是我想要的,谢谢。
How are the key names constructed for asp.net mvc outputcache?
这部分只要查阅source code for OutputCacheAttribute. The keys depend on the settings (e.g. the keys will have more data in them if you have set VaryByParam)就很容易回答。您可以通过检查属性如何为您的用例填充 uniqueID
来确定键。请注意,键被连接起来,然后进行哈希处理(因为它们可能会变得很长),然后进行 base64 编码。这是相关代码:
internal string GetChildActionUniqueId(ActionExecutingContext filterContext)
{
StringBuilder uniqueIdBuilder = new StringBuilder();
// Start with a prefix, presuming that we share the cache with other users
uniqueIdBuilder.Append(CacheKeyPrefix);
// Unique ID of the action description
uniqueIdBuilder.Append(filterContext.ActionDescriptor.UniqueId);
// Unique ID from the VaryByCustom settings, if any
uniqueIdBuilder.Append(DescriptorUtil.CreateUniqueId(VaryByCustom));
if (!String.IsNullOrEmpty(VaryByCustom))
{
string varyByCustomResult = filterContext.HttpContext.ApplicationInstance.GetVaryByCustomString(HttpContext.Current, VaryByCustom);
uniqueIdBuilder.Append(varyByCustomResult);
}
// Unique ID from the VaryByParam settings, if any
uniqueIdBuilder.Append(GetUniqueIdFromActionParameters(filterContext, SplitVaryByParam(VaryByParam)));
// The key is typically too long to be useful, so we use a cryptographic hash
// as the actual key (better randomization and key distribution, so small vary
// values will generate dramtically different keys).
using (SHA256Cng sha = new SHA256Cng())
{
return Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(uniqueIdBuilder.ToString())));
}
}
您稍后会注意到 uniqueID 用作进入内部缓存的键:
ChildActionCacheInternal.Add(uniqueId, capturedText, DateTimeOffset.UtcNow.AddSeconds(Duration));
What is the render method I need to call?
简答:ExecuteResult.
长答案:天哪,你在这里问了很多。本质上,您希望在控制台进程中实例化一些 objects 并调用方法,如果您从网站通常 运行s 的 AppDomain 中调用它,这些方法将忠实地重新创建输出。
Web 应用程序通常依赖于应用程序启动时创建的初始化和状态(例如设置组合 root/IoC,或设置 Automapper,诸如此类),因此您必须运行 初始化您的网站。特定视图可能依赖于上下文信息,例如 URL、cookie 和查询字符串参数;它可能依赖于配置;它可能会调用内部服务,这也依赖于配置,以及以某种方式设置的 AppDomain 帐户;它可能需要使用可能在服务帐户的个人存储中设置的客户端证书等内容。
以下是控制台应用程序必须执行的一般过程:
- 实例化站点的全局 object,调用其构造函数,这可能会尝试将事件连接到管道。
- 您将需要模拟管道并处理站点引发的任何事件。您还需要以模拟 ASP.NET 管道工作方式的方式引发事件。
- 您需要在 ASP.NET 管道中实施任何怪癖,例如除了引发事件之外,您还需要调用未订阅事件的处理程序,如果它们具有某些预定义的名称,例如
Application_Start
. - 您需要通过构造或模拟管道 object 来模拟 HTTP 请求,例如
HttpContext
。 - 您需要以正确的顺序在您的代码中触发 request-specific 事件以模拟 HTTP 流量。
- 您将需要 运行 您的路由逻辑来确定要实例化的适当控制器,然后实例化它。
- 您需要从操作方法中读取元数据以确定要应用的过滤器,然后实例化它们,并允许它们订阅更多您必须发布的事件。
- 最后,您需要获取操作方法产生的
ActionResult
object 并调用其 ExecuteResult 方法。
我认为这不是一个可行的方法,但如果您成功了,我希望收到您的回复。
你真正应该做的事
您的控制台应用程序应该简单地在您的应用程序中触发 HTTP 请求,以符合最终用户实际使用情况的方式填充缓存。其他人都是这样做的。
如果您希望在缓存页面过期之前替换它,您可以通过重新启动应用程序池或使用 dependency.
使缓存失效如果您担心您的响应时间统计数据,请更改您测量它们的方式,以便排除发生此刷新的任何时间 window。
如果您担心 Google 抓取的影响,您可以 modify the host load schedule 并在重置期间将其设置为 0 window。
如果您实在不想做网站
如果您坚持不想使用站点来创建缓存,我建议您让视图更轻量,并在您的应用程序中查看较低层的缓存。
例如,如果您的视图需要很长时间才能呈现的原因是它们必须 运行 具有大量连接的复杂查询,请考虑以非规范化 table.您可以 运行 SQL 代理作业每晚填充非规范化 table,从而刷新您的缓存。这样视图可以是轻量级的,您不必将它缓存在 Web 服务器上。
再比如,如果你的web应用调用了RESTful需要很长时间的服务到运行,考虑在你的服务中实现cache-controlheaders,修改您的 REST 客户端尊重它们,因此对相同表示的重复请求实际上不需要服务调用。参见 Caching your REST API。