【问题标题】:Need suggestion for ASP.Net in-memory queue需要对 ASP.Net 内存队列的建议
【发布时间】:2008-12-29 03:19:16
【问题描述】:

我需要创建一个 HttpHandler,它将为图像文件(简单的静态文件)提供服务,并且它还将在 SQL Server 表中插入一条记录。 (例如http://site/some.img,其中 some.img 是一个 HttpHandler)我需要一个内存对象(如通用列表对象),我可以在每个请求中添加项目(我还必须考虑每秒数百或数千个请求) 并且我应该能够使用 SqlBulkCopy 将此内存中的对象卸载到 sql 表中。

列表 --> 数据表 --> SqlBulkCopy

我想到了使用 Cache 对象。创建一个通用列表对象并将其保存在 HttpContext.Cache 中,并在每次向其中插入一个新项目。这将不起作用,因为 CacheItemRemovedCallback 会在 HttpHandler 尝试添加新项目时立即触发。我不能使用 Cache 对象作为内存队列。

任何人都可以提出任何建议吗?如果负载更多,我将来可以扩展吗?

【问题讨论】:

    标签: asp.net httphandler


    【解决方案1】:

    当您向队列中添加内容时,为什么 CacheItemRemovedCalledback 会触发?这对我来说没有意义......即使它确实触发了,也没有必要在这里任何事情。也许我误解了您的要求?

    我以这种方式非常成功地使用了 Cache 对象。这就是它的设计目的,并且可以很好地扩展。我存储了一个 Hashtable,每个应用页面请求都会访问该 Hashtable,并根据需要进行更新/清除。

    选项二...你真的需要队列吗?如果您只想直接写入数据库,SQL Server 也可以很好地扩展。使用共享连接对象和/或连接池。

    【讨论】:

      【解决方案2】:

      仅使用通用列表存储请求并使用不同的线程执行 SqlBulkCopy 怎么样?

      这种方式将请求存储在列表中不会阻塞响应太久,后台线程将能够按照自己的时间更新Sql,每5分钟一次。

      您甚至可以通过在 CacheItemRemovedCallback 上执行工作来将后台线程建立在 Cache 机制上。

      只需插入一些删除时间为 5 分钟的对象,然后在处理工作结束时重新插入。

      【讨论】:

        【解决方案3】:

        感谢 Alex 和 Bryan 的建议。

        Bryan:当我尝试为第二个请求替换缓存中的 List 对象时(现在,计数应该是 2),当我用新的缓存对象替换当前缓存对象时,CacheItemRemovedCalledback 会触发。最初,我也认为这是一种奇怪的行为,所以我必须更深入地研究它。 另外,对于第二个建议,我将尝试插入记录(使用 Cached SqlConnection 对象)并查看在进行压力测试时获得的性能。我怀疑我会在 I/O 操作中获得惊人的数字。

        根据您的建议,我会继续挖掘最佳解决方案。

        【讨论】:

        • 如果您尝试逐条插入记录,我怀疑您将获得可接受的性能。我试图建议的是批量更新数据库,其中包含许多记录。看看 msdn 上的 SqlBulkCopy。
        • 啊...好的。我想我现在看到了你的问题。您无需在每次请求时将列表对象替换回缓存!它一直存在,直到它过期或被明确删除。只需一遍又一遍地使用同一个列表。
        【解决方案4】:

        您可以在回调中创建条件要求,以确保您正在处理因过期而不是删除/替换而被命中的缓存条目(在 VB 中,因为我很方便):

        Private Shared Sub CacheRemovalCallbackFunction(ByVal cacheKey As String, ByVal cacheObject As Object, ByVal removalReason As Web.Caching.CacheItemRemovedReason)
            Select Case removalReason
                Case Web.Caching.CacheItemRemovedReason.Expired, Web.Caching.CacheItemRemovedReason.DependencyChanged, Web.Caching.CacheItemRemovedReason.Underused
                ' By leaving off Web.Caching.CacheItemRemovedReason.Removed, this will exclude items that are replaced or removed explicitly (Cache.Remove) '
            End Select
        End Sub
        

        编辑如果需要,这里是 C#:

        private static void CacheRemovalCallbackFunction(string cacheKey, object cacheObject, System.Web.Caching.CacheItemRemovedReason removalReason)
        {
            switch(removalReason)
            {
                case System.Web.Caching.CacheItemRemovedReason.DependencyChanged:
                case System.Web.Caching.CacheItemRemovedReason.Expired:
                case System.Web.Caching.CacheItemRemovedReason.Underused:
                    // This excludes the option System.Web.Caching.CacheItemRemovedReason.Removed, which is triggered when you overwrite a cache item or remove it explicitly (e.g., HttpRuntime.Cache.Remove(key))
                    break;
            }
        }
        

        【讨论】:

          【解决方案5】:

          扩展我之前的评论...我得到了您错误地考虑缓存的图片。如果您有一个对象存储在缓存中,比如一个哈希表,那么该哈希表中的任何更新/存储都将被持久化,而无需您显式修改缓存的内容。您只需将 Hashtable 添加到 Cache 一次,无论是在应用程序启动时还是在第一次请求时。

          如果您担心批量复制和页面请求更新同时发生,那么我建议您简单地拥有两个缓存列表。有一个是随着页面请求进入而更新的列表,还有一个用于批量复制操作的列表。当一个大容量复制完成后,交换列表并重复。这类似于视频游戏或视频应用的双缓冲视频 RAM。

          【讨论】:

            猜你喜欢
            • 2021-11-15
            • 1970-01-01
            • 2013-07-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多