要使用Web 套接字实现支持客户端的服务器,服务器是否与每个客户端保持开放的 HTTP 连接?这个规模怎么来的?
实现这种类型的服务器时有哪些“编程模型”?即:大多数网络应用程序都有支持连接->请求->响应->关闭类型模型的 servlet 等。而对于网络套接字,连接会无限期地保持打开状态。
要使用Web 套接字实现支持客户端的服务器,服务器是否与每个客户端保持开放的 HTTP 连接?这个规模怎么来的?
实现这种类型的服务器时有哪些“编程模型”?即:大多数网络应用程序都有支持连接->请求->响应->关闭类型模型的 servlet 等。而对于网络套接字,连接会无限期地保持打开状态。
您通常需要在异步模型中工作,这些长期存在的连接才能正常工作。异步 I/O 有几种不同的技术。所有这些都有其优点和缺点。
任何使用过 JavaScript 和AJAX的人都应该熟悉的一种是回调模型。您在其中发送请求,并在完成时安装要调用的回调。这就是XMLHTTPRequest
工作原理,不会在等待一个页面的请求完成时阻止所有其他页面。这也是Twisted Python 网络框架的工作方式,尽管它可以根据您使用的接口调用对象上的方法或回调函数。
另一个强大的模型是Erlang风格的方法,称为 Actor 模型,有很多很多轻量级进程(像线程,但没有共享状态),每个进程通过异步消息相互通信。Erlang 运行时已被实现,以使生成数千个进程非常有效;然后您可以为每个连接设置一个进程,并让它们将消息发送到实现应用程序后端的其他进程。Erlang 进程也可以在多个操作系统线程上自动调度,以充分利用多核系统。ejabberd是一种流行的 Jabber 服务器(一种聊天协议,需要许多长期开放的连接),它是在 Erlang 中实现的,Facebook 聊天系统也是如此。
Google的新Go 语言使用了类似的方法,比 Erlang 的 Actor 模型更接近 Hoare 的 Communicating Sequential,但有很多相似之处。
在 Mac OS X 10.6 中,Apple 引入了Grand Central Dispatch以及 C、C++ 和 Objective-C 中的块(本质上是闭包)。这允许类似于 AJAX 或 Twisted 样式的事件驱动回调模型,但具有显式管理的队列,这些队列按顺序执行以管理对多线程、多核环境中共享资源的访问。Twisted 和 JavaScript 都运行单线程,因此只能利用单核,除非您使用多个操作系统进程,这可能会相当重并增加它们之间的通信成本。
然后是更传统的模型,如 Unixselect
函数,或者更现代和更强大的epoll
或kqueue()
. 在这些中,您的程序中通常有一个主循环,它设置了一堆要监视的事件(网络 I/O 返回更多数据,文件 I/O 返回更多数据,建立新的网络连接等) ,然后调用一个阻塞的系统调用,直到其中一个事件发生,此时您检查哪个事件发生了,然后适当地处理它。这些系统调用通常用于提供上述更高级别的框架。
有关可用选项的惊人排列(专注于更传统和更低级别的 Unix 方法)的非常好的概述,请参阅The C10K Problem,这是对帮助同时处理 10,000 个同时连接的不同技术的调查。这也有一个很好的 C 和 C++ 库列表,用于抽象各种可用的 API,例如libevent。
A final option, of course, is to use one process or one OS thread for each connection. The problem is, processes are very heavy weight, and even threads are fairly heavy weight compared to many of these options. In general, for the best performance, you would want to have one process or thread per CPU, each using an asynchronous I/O API to figure out when it needs to do work, and then dispatching that work to one of several objects or callbacks that have been registered to handle connections, or one of several Erlang style lightweight processes that is waiting for a message, or something of the sort.
As a side note, the connection in web sockets are not HTTP connections, but a new protocol, the websocket protocol, though you can use the same port as HTTP, and upgrade an HTTP connection to a web socket in order to be compatible with existing firewall rules.
一般来说,您应该期望将 WebSockets 与旨在以轻量级方式处理负载的自定义服务器实现一起使用。此类服务器已经存在用于长期 COMET 连接等。
它与 http 的不同之处在于,每个后续请求/响应都不需要包装在带有 http 标头的 http 消息中。因此实时应用程序不需要解析标头的开销。在最初的类似 http 的握手之后,它基本上表现得像一个普通的 ol' tcp 套接字。
这可以用 servlet 建模,但只需区分初始请求(带有所有标头)和随后的 2-way 对话,其格式在大多数情况下是任意的。
Take a look at HTML 5 WebSockets implemented in Tornado webserver: http://bret.appspot.com/entry/web-sockets-in-tornado
I have not played with this module yet, though.