是无阻塞,单线程的,异步Web服务器(如Node.js的)有可能在.NET? [英] Is a non-blocking, single-threaded, asynchronous web server (like Node.js) possible in .NET?

查看:115
本文介绍了是无阻塞,单线程的,异步Web服务器(如Node.js的)有可能在.NET?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在看这个问题,寻找一种方式来创建的单线程在.NET中,基于事件的异步非阻塞Web服务器。

I was looking at this question, looking for a way to create a single-threaded, event-based nonblocking asynchronous web server in .NET.

这个答案看着第一看好,声称在code的身体在一个线程中运行

This answer looked promising at first, by claiming that the body of the code runs in a single thread.

不过,我在C#中测试了这个:

However, I tested this in C#:

using System;
using System.IO;
using System.Threading;

class Program
{
    static void Main()
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

        var sc = new SynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(sc);
        {
            var path = Environment.ExpandEnvironmentVariables(
                @"%SystemRoot%\Notepad.exe");
            var fs = new FileStream(path, FileMode.Open,
                FileAccess.Read, FileShare.ReadWrite, 1024 * 4, true);
            var bytes = new byte[1024];
            fs.BeginRead(bytes, 0, bytes.Length, ar =>
            {
                sc.Post(dummy =>
                {
                    var res = fs.EndRead(ar);

                    // Are we in the same thread?
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                }, null);
            }, null);
        }
        Thread.Sleep(100);
    }
}

和结果是:

1结果
  5

1
5

所以它看起来像,这违背了答案,该线程启动读取和​​结束读取的线程是的的相同。

So it seems like, contrary to the answer, the thread initiating the read and the thread ending the read are not the same.

所以,现在我的问题是,你怎么实现的单线程的,在.NET基于事件的异步非阻塞Web服务器?

So now my question is, how do you to achieve a single-threaded, event-based nonblocking asynchronous web server in .NET?

推荐答案

整个 SetSynchronizationContext 是一个红色的鲱鱼,这仅仅是编组机制,工作仍然发生在IO线程池。

The whole SetSynchronizationContext is a red herring, this is just a mechanism for marshalling, the work still happens in the IO Thread Pool.

你所要求的是排队和收获异步过程调用所有的方法从主线程的IO工作。许多更高级别的框架包裹这种功能,其中最有名的一个是的libevent

What you are asking for is a way to queue and harvest Asynchronous Procedure Calls for all your IO work from the main thread. Many higher level frameworks wrap this kind functionality, the most famous one being libevent.

有是在这里的各种选项有很大回顾:<一href=\"http://stackoverflow.com/questions/4093185/whats-the-difference-between-epoll-poll-threadpool/5449827#5449827\">Whats epoll的,民意调查显示,线程池之间的区别?。

There is a great recap on the various options here: Whats the difference between epoll, poll, threadpool?.

.NET已经采取通过扩大对你照​​顾有特殊的IO线程池当你调用 BeginXYZ 方法处理IO访问。这个IO线程池必须有每个处理器至少有1个线程在包装盒上。请参见:<一href=\"http://msdn.microsoft.com/en-us/library/system.threading.threadpool.setmaxthreads.aspx\">ThreadPool.SetMaxThreads.

.NET already takes care of scaling for you by have a special "IO Thread Pool" that handles IO access when you call the BeginXYZ methods. This IO Thread Pool must have at least 1 thread per processor on the box. see: ThreadPool.SetMaxThreads.

如果单线程应用程序是一个关键的要求(对于一些疯狂的原因),你可以,当然,互操作的所有这些东西用<一个href=\"http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx\">DllImport (见这里一个例子)

If single threaded app is a critical requirement (for some crazy reason) you could, of course, interop all of this stuff in using DllImport (see an example here)

不过这将是一个非常<一个href=\"http://blogs.msdn.com/b/ericeil/archive/2008/06/20/windows-i-o-threads-vs-managed-i-o-threads.aspx\">complex和危险的任务

我们为什么不支持装甲运兵车为完成机制?装甲运兵车是真的不为用户code一个很好的通用完成机制。管理由装甲运兵车推出的重入几乎是不可能的;你的锁,阻止任何时间,例如,一些任意的I / O完成可能需要在你的线程。它可能会尝试,收购其拥有的锁,这可能会引入锁定顺序问题,从而死锁。 preventing这需要精心的设计,并确保别人的code永远的警惕的等待过程中运行的能力,反之亦然。这大大限制的APCs的效用

Why don't we support APCs as a completion mechanism? APCs are really not a good general-purpose completion mechanism for user code. Managing the reentrancy introduced by APCs is nearly impossible; any time you block on a lock, for example, some arbitrary I/O completion might take over your thread. It might try to acquire locks of its own, which may introduce lock ordering problems and thus deadlock. Preventing this requires meticulous design, and the ability to make sure that someone else's code will never run during your alertable wait, and vice-versa. This greatly limits the usefulness of APCs.

因此​​,要回顾一下。如果你想有一个单线程管理过程,它的全部使用APC和完成端口的工作,你将不得不出手code吧。建立这将是危险的,棘手的。

So, to recap. If you want a single threaded managed process that does all its work using APC and completion ports, you are going to have to hand code it. Building it would be risky and tricky.

如果你只是想高档次网络,您可以继续使用 BeginXYZ 和家人放心,这将表现良好,因为它使用APC。你付线和.NET特定的实现之间的微小价格编组的东西。

If you simply want high scale networking, you can keep using BeginXYZ and family and rest assured that it will perform well, since it uses APC. You pay a minor price marshalling stuff between threads and the .NET particular implementation.

从:<一href=\"http://msdn.microsoft.com/en-us/magazine/cc300760.aspx\">http://msdn.microsoft.com/en-us/magazine/cc300760.aspx

在扩大服务器中的下一个步骤是使用异步I / O。异步I / O可以不必创建和管理线程。这导致更简单的code和也是一种更有效的I / O模型。异步I / O利用回调处理传入的数据和连接,这意味着没有列表的设置和扫描,并没有必要创造新的工作线程来处理未决的I / O。

The next step in scaling up the server is to use asynchronous I/O. Asynchronous I/O alleviates the need to create and manage threads. This leads to much simpler code and also is a more efficient I/O model. Asynchronous I/O utilizes callbacks to handle incoming data and connections, which means there are no lists to set up and scan and there is no need to create new worker threads to deal with the pending I/O.

这是有趣的,一边其实是单线程是不使用完成端口看做在Windows异步套接字的最快方法:<一href=\"http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml\">http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml

An interesting, side fact, is that single threaded is not the fastest way to do async sockets on Windows using completion ports see: http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml

服务器的目标是产生尽可能少的上下文切换尽可能由具有其螺纹避免不必要的阻挡,而在同一时间,通过使用多个线程最大化并行性。理想情况是,那里是一个线程积极维护每一个处理器上的客户端请求,并为这些线程不阻塞,如果有等待,当他们完成一个请求额外的请求。为了使其正常工作,但是,必须有应用程序来激活另一个线程时,一个在I / O处理客户端请求块(比如当它从文件中读取作为处理的一部分)的方法。

The goal of a server is to incur as few context switches as possible by having its threads avoid unnecessary blocking, while at the same time maximizing parallelism by using multiple threads. The ideal is for there to be a thread actively servicing a client request on every processor and for those threads not to block if there are additional requests waiting when they complete a request. For this to work correctly however, there must be a way for the application to activate another thread when one processing a client request blocks on I/O (like when it reads from a file as part of the processing).

这篇关于是无阻塞,单线程的,异步Web服务器(如Node.js的)有可能在.NET?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆