1、服务器通信技术方案前言 .31. 服务器通讯需要解决的问题 .31.1 单台 RCU 设备通讯情况 .31.2 上万个 RCU 甚至达到将近百万终端与服务器同时通讯 .41.2.1 单台服务器 .41.2.2 集群服务器 .42. 目前服务器通讯主流技术方案 .52.1 网上常用主流方案简介与比较 .52.1.1 传统的 socket 通讯模型 .52.1.2 Windows 下 IOCP 模型 .52.1.3 linux 下 epoll 模型 .62.1.4 其它的网络通讯第三方开源库简介及比较 .72.2 服务器集群方案 .103. 根据项目情况选择最合适方案 .123.1 推荐选择 li
2、nux 系统下的 epoll 及开源库 Boost:asio .123.2 可能问题 .12修订记录序号 版本号 修订内容 修订人 修订日期A 1.00.000 第一个版本 颜冬 2013.09.07BCDEFGHIJKLMNOPQ前言RCU-U 设备采集数据如:车辆诊断,通过 GSM 基站定位,内置 GPS,GPRS 系统提供远程数据,对车辆各个系统的运行状况(如 ENG、ABS 、ETC 等)实时监测状态数据等。这些数据的网络通讯平台,则由服务器提供的通讯技术来实现,因此如何实现这种多设备数据同时接收的技术方案很重要。本文将详细介绍相关技术及提出方案。1.服务器通讯需要解决的问题1.1 单
3、台 RCU 设备通讯情况主要通讯数据:设备端,刚连接时登陆验证(设备端信息验证);设备端,诊断数据及其它采集数据上传到服务器(估计频率 每秒发一次);服务器端,发送指令,实现对设备端的远程配置;RCU 设备工程师估计的数据:1 每个 RCU 设备每秒钟产生一条数据,每条数据大概 100 个字节左右(0.1K 左右) ;2 可以假设每台车每天平均开动 1 小时或 2 小时(实际产生数据时间) ;RCU 数量(个) 1 秒 1 小时 2 小时1 0.1kb 360kb 720kb1 万 1000kb0.97M3515M3.43G7030M6.86G100 万 100,000kb97M343G 68
4、6G1000 万 1000,000kb970M3430G3.35TB6860G6.70TB从上数据显示如果达到:100 万级别的 RCU 用户量,需要服务器有近百兆的网络带宽吞吐量。1000 万级别的 RCU 用户量,需要服务器有近千兆的网络带宽吞吐量。1.2 上万个 RCU 甚至达到将近百万终端与服务器同时通讯1.2.1 单台服务器如果按照经典的 server/client 通讯模型,当有一个设备通过(TCP/UDP )连接服务器时,服务端单独开一个线程为这个设备数据服务,显然,当路数越多,我们的设备又是长连接方式,很快服务器将在设备近千路时服务器资源将达到上限,并且存在大量线程切换与管理问
5、题。这时如果我们能合理利用单台服务器资源(如:windows 下 iocp 模式,linux 下的 epoll 网络通信模式等) ,在更优的管理模式下,将能接更多设备的服务(网上资料预估几千路的长连接甚至硬件较好配置下达到万路以上) 。上面我们能在单台服务器在较好硬件配置和软件优化的模型管理下,能解决几千路上万路设备的长连接。1.2.2 集群服务器 但是,如果几十万台甚至接近百万级别的设备数量同时访问服务端时,这个时候需要涉及到一种合理的集群服务器架构模式。理论上,为了达到 1:10000 的连接,可以采用Server-Client 的连接方式,而为了达到 1:10000*100 的连接,我们
6、怎么办呢?一般会采用Client- ConnServer - LogicServer。相当于有一批服务器来合理布局解决设备的大并发通讯问题。ConnServer 在接受完 Client 的连接后,将 Logic Server 暴露给 Client,并立刻断开连接,称之为短连接。以后的数据交互就和 Conn Server 没有关系了,让 Logic Server 直接跟client 再长连接通讯,这种架构有很多的优势。图一:标准集群 Server 架构方案2.目前服务器通讯主流技术方案2.1 网上常用主流方案简介与比较2.1.1 传统的 socket 通讯模型socket 有两种:流式 Sock
7、et( SOCK_STREAM)和数据报式 Socket(SOCK_DGRAM) 。流式是一种面向连接的 Socket,针对于面向连接的 TCP 服务应用;数据报式 Socket 是一种无连接的 Socket,对应于无连接的 UDP 服务应用。一般小型的 c/s 通讯系统利用 socket API 和结合一个线程对应一个客户的开发模式。如果路数增多,容易耗尽服务端资源。该通讯模型利用硬件资源效率不高。2.1.2 Windows 下 IOCP 模型IOCP 完成端口模型又是怎样实现的呢?首先我们创建一个完成端口 CreateIOCompletionPort。绑定端口之后,建立一个监听线程,用来监
8、听客户端的连接,当有连接进来时,将该连接的套接字加入到 IOCP 对队列中,同时再创建几个工作线程(CPU 数*2+2) ,工作线程调用 getQueuedCompletionStatus 方法在关联到这个完成端口上的所有套接字上等待 I/O 的完成,再判断完成了什么类型的 I/O,然后接着发出 WSASend 和 WSARecv,这样在该连接发生请求时,IOCP 模型就会在工作线程通知,这样我们就可以在工作线程中,完成对客户端的请求做出一系列响应。完成端口提供了一个高效复杂的内核对象,使得非 IO 处理和 IO 处理能重叠并行地操作。该对象通过指定工作线程的数量,对重叠的 I O 操作进行处
9、理。当一个事件发生,此完成端口就被操作系统加入一个队列中,然后应用程序可以对核心层进行查询以得到此完成端口。IOCP 的核心思想简单说就是:将所有用户的请求都投递到一个消息队列中,利用事先创建好的若干个工作线程逐一从消息队列中取出消息并加以处理。这样不仅减少了线程资源,也大大提高了线程的利用率。要注意的是,所谓完成端口,实际上是Windows 采用的一种 IO 构造机制,并非通常所说的端口( 如 Port:80)。2.1.3 linux 下 epoll 模型epoll 是 Linux 下多路复用 IO 接口 select/poll 的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况
10、下的系统 CPU 利用率。因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO 事件异步唤醒而加入 Ready 队列的描述符集合就行了。 epoll 除了提供 select/poll 那种 IO事件的电平触发(Level Triggered)外,还提供了边沿触发(Edge Triggered) ,这就使得用户空间程序有可能缓存 IO 状态,减少 epoll_wait/epoll_pwait 的调用,提高应用程序效率。传统的 select/poll 另一个致
11、命弱点就是当你拥有一个很大的 socket 集合,不过由于网络延时,任一时间只有部分的 socket 是“ 活跃”的,但是 select/poll 每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是 epoll 不存在这个问题,它只会对“活跃”的 socket进行操作- 这是因为在内核实现中 epoll 是根据每个 fd 上面的 callback 函数实现的。那么,只有“活跃”的 socket 才会主动的去调用 callback 函数,其他 idle 状态 socket 则不会。通讯模型 主要优点 主要缺点传统 socket 适合于连接量较小的通讯情况,通过socet API 建立 C
12、/S 通讯。服务连接路数小,IO 没有复用,一般是一个线程对应终端的服务模式。通讯情况下,每个 socket 句柄,包含不活跃的连接也会需要遍历。Windows 下 IOCP 适合于大量连接数(上万路) ,IO 复用,消息队列,可指定相应工作线程数,轮询端口的事件,充分利用多核,高效率地服务于多并发。只跑在 windows 服务器下,如果数据库平台为 linux 服务器,影响系统功能模块整合。linux 下 epoll 适合于大量连接数(上万路) ,多路复用 IO 接口,只遍历那些被内核 IO 事件异步唤醒而加入 Ready 队列的描述符集合。通讯情况下,只对活跃的连接遍历,提高了效率。当前主
13、流服务器为 linux,也有系统优势。ET 和 LT 模式下,其中 LT模式比较复杂,较难处理数据收发。基于以上比较,我们服务器的操作系统平台是 linux 下(大数据库的平台也是) ,显然大并发访问通讯模型 linux 下 epoll 更合适我们项目实际需求。2.1.4 其它的网络通讯第三方开源库简介及比较Libeventlibevent 是一个事件触发的网络库,适用于 windows、linux、bsd 等多种平台,内部使用 select、epoll、kqueue 等系统调用管理事件机制。著名分布式缓存软件 memcached 也是libevent based,而且 libevent 在使
14、用上可以做到跨平台,而且根据 libevent 官方网站上公布的数据统计,似乎也有着非凡的性能。libevent 包括事件管理、缓存管理、DNS、HTTP、缓存事件几大部分。事件管理包括各种 IO(socket) 、定时器、信号等事件;缓存管理是指 evbuffer 功能;DNS 是 libevent 提供的一个异步 DNS 查询功能;HTTP 是 libevent 的一个轻量级 http 实现,包括服务器和客户端。libevent 也支持 ssl,这对于有安全需求的网络程序非常的重要,但是其支持不是很完善,比如 http server 的实现就不支持 ssl。Libevlibev 是 lib
15、event 之后的一个事件驱动的编程框架,其接口和 libevent 基本类似。据官方介绍,其性能比 libevent 还要高,bug 比 libevent 还少。ACE有人评价其框架模式很值得学习,但是其网络应用效率和开发应用相比其他开源库较差,这也是其主要用于研究很少用于商业应用的原因,这方面不像 boost 应用广泛。应用中需要充分理解其复杂的架构模式。这不是短时间可掌握和灵活运用的,相对来说其他第三方网络开源库相对模式精简很多。ICEZeroC ICE 是指 ZeroC 公司的 ICE(Internet Communications Engine)中间件平台。对于客户端和服务端程序的开
16、发提供了很大的便利。目前 ICE 平台中包括 Ice,Ice-E,Ice Touch。Ice 为主流平台设计,包括 Windows 和 Linux,支持广泛的语言,包括C+,Java ,C#(和其他.Net 的语言,例如 Visual Basic) ,Python,Ruby,PHP 和ActionScript。也包括所有的 ICE 服务,例如 Ice Grid,IceStorm 等。Ice-E 是 Ice 在资源受限的平台上的一个实现,支持 C+和嵌入式操作系统,例如Windows CE,Linux。Ice-E 本身不包含任何服务,但是可以利用在 Ice 上提供的各种服务。因此,通过 Ice-
17、E,移动设备也能无缝的集成到分布式系统中。Ice Touch 是为 iphone 和 ipod touch 开发的版本,包括 Object-C 映射,支持 Iphone OS,并为 MAC OS X 开发图形界面应用程序提供完整的 Cocoa 框架的访问。Boost:asioBoost.Asio 是利用当代 C+的先进方法,跨平台,异步 I/O 模型的 C+网络库,ASIO 在Linux 平台下的实现基于 epoll,在 windows 下基于 iocp。其商业应用非常广泛。Boost 库本身还支持很多常有用的开源库,如 regex 正则表达式算法,它本身是基于 STL 的二次开发。Muduo
18、muduo 是一个基于 Reactor 模式的现代 C+ 网络库,它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。这是一个国内个人写的开源库,有专门介绍的书,网上热评较多,据其书上测试数据所描述,其性能要稍好于 libevent 与 boost。Node.js Node.js 是一套用来编写高性能网络服务器的 JavaScript 工具包。Node.js 可以在不新增额外线程的情况下,依然可以对任务进行并行处理, Node.js 是单线程的。它通过事件轮询(event loop)来实现并行操作。但它是一个新兴的后台语言, 网络资
19、源相对较小,需要对 javascript 的事件驱动非常熟悉。调试方面比较困难。后期维护较难。开源库 主要优点 主要缺点Libevent 跨平台/支持安全机制 ssl/有事件机制/DNS 支持基于其上开发网络库,还需要实现很多网络模块。Libev类似 libevent,包含它的所有功能,官方描述其性能比它好。网上评价相对来说libevent 应用较广泛。ACE封装程度高,模式框架强,支持事件驱动,跨平台。学生用于论文研究开发的网络通讯库,学术性强,应用及性能较差,模式复杂。ICE 支持分布式系统,支持多语言,多操作系统,是一个 zeroc 公司开发的库,应用不是很广泛,被称为 ACE 的轻量级
20、别。应用不太广泛,是一个公司的网络开源通讯库。二次开发待验证。Boost:asio跨平台,本身利用 epoll 与 iocp 模型就为了支持多路连接并发考虑的库。商业应用非常广泛,其库有可能纳入 C+规范里面做教材用充分了解 boost 开源库需要一定时间,其主要利用泛型编程模式。Muduo 非阻塞,多线程,支持 linux 平台,其利用通讯模型 epoll 实现应用。书中的测试个人网络库,知名度应用方面不如 libevent 与数据显示,单台服务器(硬件配置 8 核CPU,16G 内存)已经实现 10000 台终端连接数,并有与其他开源库测试性能比较。boost,但是其书热评很多。Node.
21、js 官方描述,高性能网络服务器的JavaScript 工具包。Node.js 可以在不新增额外线程的情况下,依然可以对任务进行并行处理, Node.js 是单线程的。它通过事件轮询(event loop)来实现并行操作基于 javascript 的新型网络库,应用时间较短,调试麻烦,后期维护困难。它的单线程模式,对现在的硬件多核处理器来说,利用不了多核的优势。基于以上比较,主要选商业应用较广泛,开源时间较长,库功能丰富的 Boost:asio 第三方开源库, 另外两个个人与公司的开源库 Muduo 和 ICE 待验证作为备选。2.2 服务器集群方案图一:标准集群 Server 架构方案DNS 均衡服务器原理:就是 1 个主机纪录对应多个 IP Address(不同的多台服务器或多张网卡),实现不同 DNS 客户的均衡轮询。