我创建了一个 MVC.Net 应用程序,并且有一个下载页面,用户可以从该页面下载大小约为5MB的安装文件。当我们点击下载按钮时,动态生成此设置文件。每个动态生成此安装程序文件会增加7%的服务器CPU使用率。 假设用户数量增加至少100并且所有用户都会尝试下载文件,那么CPU使用率将增加到100%,这将使服务器关闭或无响应。
为了克服这种情况,我们试图通过代码在逻辑上限制总共5次下载。这意味着5个用户可以一次下载文件,第六个用户将在队列中,直到前5个下载未完成。此外,我们必须向排队用户显示“您的下载将在28秒内开始”的等待时间。
任何有关如何实现这一目标的建议都将受到高度赞赏。
此致 海德尔
答案 0 :(得分:1)
您可以使用Semaphore
并将其限制为5.您可以在静态类中维护Semaphore
并由您的控制器访问它。
这是一个例子:
public static class MySemaphore {
private static Semaphore pool = new Semaphore(0,5);
public Semaphore GetSemaphore() { return pool; }
}
public class MyController : Controller {
public ActionResult MyDownloadAction() {
MySemaphore.GetSemaphore().WaitOne(); // wait for semaphore
// do your job : create file
// ...
MySemaphore.GetSemaphore().Release(); // release the semaphore
// prepare download resource and send response
// ...
return View();
}
}
答案 1 :(得分:0)
您描述的行为要求您从操作中返回,然后使用AJAX跟踪请求状态。
在简单的天真方法中,这意味着当请求进入时,您将发出票证并返回一个告诉用户等待的页面,而不是返回文件结果。
返回给用户的故障单可以在cookie中,也可以在页面本身中。就价值而言,您可以使用GUID。
然后页面将每隔n秒用AJAX轮询您的服务器。理想情况下,此轮询应更新服务器端的票证(例如,上次检查的时间戳),以便您知道仍有用户等待提供票证。一旦你有了容量,你将返回AJAX GET结果,告诉页面JS代码开始下载。
如果您的故障单不在cookie中,您可以在此处将故障单添加到请求URL。
在服务器端,您将检查故障单,确保其有效并正确订购,并提供该文件并删除故障单。
现在说这个,实施细节将取决于您计划拥有多少台服务器。如果你想拥有一个可扩展的系统,那么我建议使用像Azure角色/工作者角色/队列这样的东西。这样,您将解除票证发放,票证跟踪和票证处理。
另外,对于概念验证系统,您可以将票据保存在内存中,或者对于可以拥有共享数据库的小型多机系统。