2010-01-04 30 views
11

要使用web sockets实现支持客户端的服务器,服务器是否与每个客户端保持开放的HTTP连接?这如何扩展?Web套接字服务器端处理模型

什么是实施此类服务器时的“编程模型”?也就是说:大多数Web应用程序都有支持connect-> request-> response-> close类型的servlet等。而使用网络套接字时,连接保持无限期打开状态。

回答

17

您通常需要在asynchronous模型中工作这些长期连接才能工作。有几种不同的技术来完成异步I/O;所有这些都有其优点和缺点。

一个应该已经熟悉任何使用JavaScript和AJAX的人都是回调模型;在其中发送一个请求,并安装一个回调,当它完成时被调用。这是XMLHTTPRequest的工作方式,在等待一页请求完成时不阻止所有其他页面。这也是Python网络框架的工作原理,尽管它可以根据您使用的接口调用对象上的方法或回调函数。

另一个强大的模型是Erlang风格的方法,称为Actor模型,有许多很多轻量级进程(像线程但没有共享状态),每个进程都通过异步消息相互通信。 Erlang运行时已经实现,可以产生数千个非常高效的进程;那么您可以为每个连接创建一个进程,并让他们将消息发送到实现应用程序后端的其他进程。 Erlang进程也可以在多个OS线程上自动调度,以充分利用多核系统。 ejabberd是一种流行的Jabber服务器(一种聊天协议,它需要许多长期的开放式连接),在Erlang中也是如此,其中Facebook Chat system也是如此。

来自Google的新的Go language采用了类似的方法,比Erlang的Actor模型更接近于Hoare的通信顺序,但它有很多相似之处。

在Mac OS X 10.6中,Apple引入了Grand Central Dispatch以及C,C++和Objective-C中的块(基本上是闭包)。这允许类似于AJAX或Twisted风格的事件驱动回调模型,但具有按顺序执行的显式管理队列,以管理对多线程多核环境中共享资源的访问。 Twisted和JavaScript都运行单线程,因此只能利用单个内核,除非使用多个操作系统进程,这些进程可能相当重,并增加了它们之间的通信成本。

然后有更传统的模型,如Unix select函数,或更现代和有能力的epollkqueue()。在这些应用程序中,通常在程序中有一个主循环,它建立了一系列需要监视的事件(网络I/O返回更多数据,文件I/O返回更多数据,创建新的网络连接等) ,然后调用阻塞的系统调用,直到其中一个事件发生,此时您检查发生了哪一个事件,然后进行适当的处​​理。这些系统调用通常用于提供上述更高级别的框架。

有关可用选项(关注更传统的和更低级别的Unix方法)的非常好的概述,请参阅The C10K Problem,这是一项帮助同时处理10,000个同时连接的不同技术调查。这也有一个很好的C和C++库列表,用于抽象各种可用的API,如libevent

当然,最后一个选项是为每个连接使用一个进程或一个OS线程。问题是,过程的重量非常重,甚至与许多这些选项相比,线程的重量也相当重。通常,为了获得最佳性能,您希望每个CPU都有一个进程或线程,每个都使用异步I/O API来确定何时需要执行工作,然后将该工作分派到多个对象或回调中的一个已经被注册来处理连接,或者正在等待消息的几个Erlang样式的轻量级进程之一,或者类似的东西。

请注意,web套接字中的连接不是HTTP连接,而是一个新协议,即websocket protocol,尽管您可以使用与HTTP相同的端口,并且将HTTP连接升级到web套接字以便与现有防火墙规则兼容。

0

一般来说,您应该期望使用WebSockets和用于轻量级处理负载的自定义服务器实现。这种服务器已经存在用于长期COMET连接等等。

0

它与http的不同之处在于每个后续的请求/响应不需要被包装在具有http头的http消息中。所以实时应用程序不需要解析标题的开销。在最初的类似于http的握手之后,它基本上像普通的ol'tcp套接字一样。

这可以使用servlet建模,但只需要区分初始请求(包含所有头文件)和随后的双向对话框,其格式在大多数情况下是任意的。