ASP.NET 3.5企业级项目开发 第一章(续):企业级项目框架解决方案的提出
一个缺货提示系统,但 无论如何,您都要面对感到失望的客户。
或许问题根源在于您的过期设定方案:时间设定的不够好。您可以缓存库存数,当有人购买了某个小 组件后,缓存对象即过期。这样一来就比较合乎逻辑了,但如果有多个 ASP.NET 服务器会怎样?这时您 会得到该小组件的不同库存数,具体取决于您请求的是哪个服务器。请想一想,接收新库存(添加到计数 中)甚至不会经过您的 Web 应用程序,这样就可能会引入新的错误。 可以在各 ASP.NET 服务器之间同步过期时间,但必须要小心。各 Web 服务器之间产生的对话量将随 着缓存对象和 Web 服务器数量的增加而呈几何性上升。 有关缓存过期对性能的影响还需要做进一步的研究。在高负载情况下,某个缓存对象过期可能会带来 很多麻烦。例如,假定您执行了一次非常耗时的查询,它需要 30 秒才能从数据库中返回结果。由于在有 负载情况下,该页面每秒都会被请求一次,因此您缓存该查询以节省开销。 处理缓存对象的代码非常简单。应用程序首先会检查是否填充了缓存对象,而不是在需要时才从数据 库中检索数据。如果检查到缓存对象,则它将使用缓存对象中的数据。如果未检查到,它将执行代码从数 据库中检索数据,然后使用该数据填充缓存对象;代码随后继续正常执行。 问题在于如果您的查询需要花费 30 秒的时间,而您每秒都要执行该页面,那么在填充缓存项目的这 段时间内,将有 29 个其他请求传入,而且它们都试图用自己的数据库查询结果来填充缓存项目。要解决 此问题,您可以添加一个线程锁,以阻止其他页面从数据库请求数据。 但要重新运行整个方案:第一个请求传入,发现缓存项目尚未填充,对代码应用一次锁定,然后运行 查询以填充缓存对象。一秒钟后第二个请求到达(此时第一个请求仍在运行),发现缓存对象尚未填充, 但已置入锁定,因此第二个请求被封锁。接下来的 28 个请求都会有同样的经历。接下来,第一个请求完 成其处理并删除锁定,然后继续执行。其他 29 个请求会怎样?它们不再被封锁,因此也继续执行。但是 它们已经检查过缓存对象是否已被填充(当时尚未填充)。因此它们将尝试夺取锁定,有一个请求将会胜 出并重新运行查询。 发现问题了吗?在第一个请求完成了缓存对象的填充之后到达的那些请求将正常运行,但在查询运行 期间传入的那些请求却处于困境。您必须编写代码来处理这种情况。如果某个请求夺取了锁定,当锁定被 提升后,它会重新检查缓存对象是否已填充,如图 5 所示。很可能缓存对象马上就被填充;这就是首先 夺取锁定的原因。尽管可能并非如此,但由于其他一些代码块已过期,因此会再次缓存对象。 Figure 5 检查、锁定和重新检查缓存对象 // check for cached results object cachedResults = ctx.Cache["PersonList"]; ArrayList results = new ArrayList(); if (cachedResults == null) { // lock this section of the code // while we populate the list lock(lockObject) { // only populate if list was not populated by // another thread while this thread was waiting if (cachedResults == null) { ... } } } 虽然编写行之有效的缓存代码是一项非常艰巨的工作,但回报也是相当可观的。不过,缓存确实增加 了复杂性,因此要明智地使用它。要确保您确实会从复杂的状况中得到益处。请务必针对以下复杂情况对 缓存代码进行测试。同时出现多个请求时该怎么办?很快就会过期时该怎么办?您必须要知道这些问题的 答案。您肯定不希望您的缓存代码把扩展问题搞的更糟。 扩展数据库 扩展 Web 站点的一般方法是全面扩展,而不是向上扩展。这主要是考虑到 ASP.NET 线程和内存限制 以及 Web 请求的短 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |