简单的异步I / O处理程序正在丢弃请求

时间:2014-06-17 10:19:39

标签: c# javascript asp.net node.js asynchronous

我在C#中编写了一个小的.ashx处理程序,具有直截了当的逻辑:

  • 生成54千字节的随机有效负载字符串。
  • 获取用于存储数据的唯一文件名。
  • 以异步方式将字符串写入文件。
  • 以异步方式从该文件回读。
  • 将该字符串发送回响应流。

我的想法是使用apache-bench向上述处理程序抛出多个并发请求,这样我就可以将ASP.NET 4.5与其他框架(如nodejs)进行比较,以便我开发一个大型应用程序这是严重的I / O限制。以下是处理程序的代码:

public class Handler : System.Web.IHttpHandler
{
    private StringBuilder payload = null;

    private async void processAsync()
    {
        var r = new Random ();

        //generate a random string of 108kb
        payload=new StringBuilder();
        for (var i = 0; i < 54000; i++)
            payload.Append( (char)(r.Next(65,90)));

        //create a unique file
        var fname = "";
        do{fname = "c:\\source\\csharp\\asyncdemo\\" + r.Next (1, 99999999).ToString () + ".txt";
        } while(File.Exists(fname));            

        //write the string to disk in async manner
        using(FileStream fs = File.Open(fname,FileMode.CreateNew,FileAccess.ReadWrite))
        {
            var bytes=(new System.Text.ASCIIEncoding ()).GetBytes (payload.ToString());
            await fs.WriteAsync (bytes,0,bytes.Length);
            fs.Close ();
        }

        //read the string back from disk in async manner
        payload = new StringBuilder ();
        StreamReader sr = new StreamReader (fname);
        payload.Append(await sr.ReadToEndAsync ());
        sr.Close ();
        //File.Delete (fname); //remove the file
    }

    public void ProcessRequest (HttpContext context)
    {
        Task task = new Task(processAsync);
        task.Start ();
        task.Wait ();

        //write the string back on the response stream
        context.Response.ContentType = "text/plain";
        context.Response.Write (payload.ToString());
    }


    public bool IsReusable 
    {
        get {
            return false;
        }
    }
}

麻烦的是,当我编译它并从浏览器运行一次时,Handler运行得很好。但是当我使用ab向它发送并发请求时,大约有一半的请求被丢弃。不仅如此,但与我在node.js中编写的类似脚本相比,它的速度太慢了 - 我已经在IIS-7 / Windows和Mono / Linux环境中对它进行了测试。你是否建议ASP.NET与node.js相比本身就更慢,以处理繁重的异步I / O负载?

1 个答案:

答案 0 :(得分:0)

我已按以下方式重新实现了我的代码,现在可以使用了:

private StringBuilder payload = null;

private async void processAsync()
{
    var r = new Random (DateTime.Now.Ticks.GetHashCode());

    //generate a random string of 108kb
    payload=new StringBuilder();
    for (var i = 0; i < 54000; i++)
        payload.Append( (char)(r.Next(65,90)));

    //create a unique file
    var fname = "";
    do
    {
        //fname = @"c:\source\csharp\asyncdemo\" + r.Next (1, 99999999).ToString () + ".txt";
        fname =  r.Next (1, 99999999).ToString () + ".txt";
    } while(File.Exists(fname));            

    //write the string to disk in async manner
    using(FileStream fs = new FileStream(fname,FileMode.CreateNew,FileAccess.Write, FileShare.None,
        bufferSize: 4096, useAsync: true))
    {
        var bytes=(new System.Text.ASCIIEncoding ()).GetBytes (payload.ToString());
        await fs.WriteAsync (bytes,0,bytes.Length);
        fs.Close ();
    }

    //read the string back from disk in async manner
    payload = new StringBuilder ();
    //FileStream ;
    //payload.Append(await fs.ReadToEndAsync ());
    using (var fs = new FileStream (fname, FileMode.Open, FileAccess.Read,
               FileShare.Read, bufferSize: 4096, useAsync: true)) {
        int numRead;
        byte[] buffer = new byte[0x1000];
        while ((numRead = await fs.ReadAsync (buffer, 0, buffer.Length)) != 0) {
            payload.Append (Encoding.Unicode.GetString (buffer, 0, numRead));
        }
    }


    //fs.Close ();
    //File.Delete (fname); //remove the file
}

public void ProcessRequest (HttpContext context)
{
    Task task = new Task(processAsync);
    task.Start ();
    task.Wait ();

    //write the string back on the response stream
    context.Response.ContentType = "text/plain";
    context.Response.Write (payload.ToString());
}