开发者

How to limit number of concurrent file downloads for the number of requests?

开发者 https://www.devze.com 2023-04-12 22:16 出处:网络
I ha开发者_如何学Pythonve created an MVC.Net application and there is a download page from where users can download the setup file of approx 5MB in size. This setup file is generated dynamically when

I ha开发者_如何学Pythonve created an MVC.Net application and there is a download page from where users can download the setup file of approx 5MB in size. This setup file is generated dynamically when we hit the download button. Each dynamic generation of this setup file increase 7% of server CPU usage. Suppose the number of users increase at least 100 and all of them will try to download the file then the CPU usage will increase to 100% which will make the server down or it will un-responsive.

To overcome to this situation, we are trying to limit the total 5 downloads at a time logically by code. It means 5 users can download the files at a time and sixth onward users will be in queue until any first 5 downloads are not complete. Also we have to show the wait time to the queued users that "your download will begin in 28 seconds" or so.

Any suggestion how to achieve this will be highly appreciated.

Regards, Haidar


You can use a Semaphore and limit it to 5. You can mantain the Semaphore in a static class and access it by your controller.

Here an example:

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();
  }

}


The behaviour you describe requires you to return from your action, and later track the request status with AJAX.

In the simple naive approach this means when the request comes in, instead of returning a file result, you will issue a ticket and return a page which tells the user to wait.

The ticket returned to user can be in a cookie, or in the page itself. As far as value goes you can use a GUID.

Then the page will poll your server with AJAX every n seconds. Ideally this poll should update the ticket on the server side (e.g a last checked timestamp) so that you know there is still a user waiting for the ticket to be served. Once you have the capacity you will return for the AJAX GET a result which tells to the page JS code to start downloading.

If your ticket is not in a cookie you can here add the ticket to the request URL.

In the server side you will check the ticket, making sure it is valid and ordered right, and serve the file and remove the ticket.

Now saying this, implementation details will depend on how many servers you are planning to have. If you want to have a scalable system, then I would suggest using something like Web Role/Worker Role/Queue of azure. This way you will decouple the ticket issuing, ticket tracking, and ticket processing.

Else for a proof of concept system you can keep your tickets in memory or for a small multi-machine system you can have a shared database.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号