在我们实现的分布式服务器中,每个节点存储时空数据,这些节点上的时空数据通过RTree进行索引。每个节点还保存路由(相邻节点)信息。客户端可以向服务器发送数据查询请求。服务器负责接收请求并根据请求的类型进行处理,包括查询本地数据和转发请求给相邻节点。时空数据以数据流的形式不断插入服务器。当一个节点的数据达到系统预定义的阈值时,该节点将分裂为两个节点。我们根据计算数据的最优划分策略对数据进行划分,并将划分后的数据迁移到新的节点上。同时更新当前节点和新建节点的路由信息??。 根据以上需求,我们的服务器需要满足以下两个目标:满足高并发的数据查询请求和数据传输请求,同时处理长短连接 服务器中有两种连接模式同时:长连接和短连接。持久连接是指客户端和服务器端先建立通信连接,连接建立后不断开连接,再进行消息的发送和接收。长连接常用于点对点通信。在服务器中,数据传输使用长连接。短连接是指只有在发送和接收消息时,客户端和服务器才连接起来进行通信,操作完成后立即关闭连接。短连接一般用于点对多点的通信,比如多个Client连接一个Server。在服务端,数据查询请求使用短连接。 常见的网络服务器有以下几种方式:一个线程服务一个客户端,使用阻塞I/O一个线程服务多个客户端,使用非阻塞I/O一个线程服务多个客户端,使用异步I/O/O 第一种方法的缺点是当并发连接数过高时,操作系统在同时处理上百个线程时会出现性能问题。而且,如果服务器硬件配置不变,随着连接数的增加,性能会急剧下降。第三种方式目前在Unix上使用并不广泛,所以在我们的系统中没有使用。第二种方式是将网络句柄设置为非阻塞模式,然后使用select或pollIO多路复用技术通知该句柄已经有数据等待处理。在这种模型下,系统内核通知应用程序某个网络句柄的状态。这种模型也是传统的IO多路复用模型,是目前大多数网络服务器的解决方案。 我们的服务器是基于Linux开发的。在Linux上,实现IO多路复用主要有几种技术,分别是select模型、poll模型和epoll模型。 select模型最大的缺点就是最大并发限制,因为一个进程打开的socketFD(文件描述符)是有限制的,默认是1024,所以select模型的最大并发是有限制的。当然我们可以通过修改系统参数来增加最大并发数,但是因为select的每次调用都会线性扫描所有的socketfd集合。当socketFD增加时,服务器效率会线性下降。 poll模型在效率上和select基本一致,poll模型没有解决select的问题。 epoll模型是目前比较优秀的IO多路复用模型。首先,epoll没有最大并发连接限制。上限是整个系统最多可以打开socketfd的个数。这个数字远大于2048。一般来说,这个数字与系统内存有很大关系。1G内存的机器的***sockeffd数量可达10万左右。其次,epoll***的优点是只关心活跃连接数,不关心连接总数。所以在实际的网络环境中,epoll的效率会比select和poll高很多。 鉴于epoll的优势,我们的服务器采用epoll作为IO多路复用的基础技术。 常见的基于epoll的设计模式主要是单线程的事件循环,对于一些非阻塞的业务逻辑开发效率很高。但是,在我们的服务器开发中,涉及到数据传输。需要转发请求需要很长时间。所以单线程的epoll不能满足我们的需求。下面用一个简单的例子来说明epoll在单线程模式下的缺点。 因为是单线程模型,当一个客户端的请求处理时间较长时,会影响服务器接收其他客户端的连接请求,进而影响整个服务器的并发性能。 因此,单线程epoll模型在我们的分布式服务器中是不适用的。以下是我们服务器的设计方案: 图2 图3 以上设计模式一般称为Reactor模式,Reactor模式是一种常见的处理并发I/O的模式。中心思想是首先将所有需要处理的I/O事件添加到一个中央多路复用器(epoll)中,而主线程阻塞在多路复用器上;一旦连接到达或准备就绪,多个多路复用器将返回并将相应的I/O事件分派给相应的处理线程。 我们的服务器使用了多个Reactor,也就是多线程epoll。反应器分为主反应器和副反应器,分别对应图2和图3。每个reactor都有一个独立的epoll作为multiplexer。其中,主反应器中的epoll负责监听连接请求。一旦有连接到达,连接套接字就会通过一定的分配策略加入到子反应器的epoll中。对于各个子reactor的epoll,主要的工作就是监听连接socket。一旦连接套接字的I/O就绪,通知相应的处理程序接收数据并处理请求。 通过使用非阻塞I/O多路复用技术epoll,连接建立后连接请求与逻辑分离,我们设计了基于Reactor设计模式的服务器,满足高并发处理数据查询请求数据传输请求。它可以同时处理长连接和短连接。同时,还有一些细节我们可以改进:从主反应器到子反应器的分配策略 目前我们采用的是Round-robin方式,可能会造成负载不均衡。后面我们可以通过一定的策略,将主reactor收到的连接请求分发给相对空闲的sub reactor。保证整个系统的负载均衡。子反应器的多线程 对于每个子反应器,这是单线程的。我们还可以进一步划分子reactor,将数据接收和请求处理分开,请求处理采用线程池的方式。这样会进一步提高服务器的并发性。原文链接:http://www.cnblogs.com/meibenjin/p/3604389.html
