首先感激陈硕大大,附链接 陈硕的CSDN。《UNP》这本书肯定也是必须的,豆瓣的评价

       最近项目需要有一个嵌入式网络服务器,在系统中,该模块需要与每个客户端保持多个socket连接,然后将收到的数据分别转发给对应的上层处理模块。有点像云风的blog中提到的游戏服务端的接入服务器。但为了满足实时性,转发机制不经过socket,直接保存到优先级队列中。这里面的优化的地方颇多,暂时有零拷贝机制优化,相对于linux中用户态和内核态的各种缓冲拷贝,VxWorks直接在内核态操作无疑给这方面的优化工作大大的便利,也不准备使用RTP用户态机制给自己添堵了。这篇博客不准备在这方面写更多,其实重点是网络编程模型的一些东西。

       之前一直对linux网络编程有些感觉,在VxWorks上面,同样的需求让我很是惊喜。该模块大体情况为:使用VxWorks SMP中的CPU亲和机制,给该模块分配一个CPU核单独使用。每个客户端会和服务器保持多个连接,各个连接发送不同功能的信息,这些信息将会分配到不同的消息队列供上层处理。首先想到的是以下三个架构方法:

单任务设计肯定很简单,连任务切换都省了。在任务中使用select()监听多个socket,这是《UNP》一书中详细讲解的方法,但对后续优化肯定不方便,而且select那令人dt的轮询机制和socket连接数限制也会让人无比羡慕epoll这种大杀器。

要与零拷贝机制结合,最初的设想是多个任务分别监听,只要注意好惊群效应和任务均衡就ok。这也是《UNP》的设想,比单一任务accept再分发连接效率高。但这么做对后续数据的分发及其不方便,每一个任务都要去判别分发到哪个消息队列。

那么,单一任务accept。判断是何种消息socket,再分别发送到各个单一功能任务中。无疑是很好的办法了。这么做的好处还有一点就是,每个任务都只操作一个消息队列(只收发一种消息),在零拷贝机制上,可以最大限度地减少拷贝甚至不拷贝。

     第一个方法肯定不用,第二个方法也有改进的地方,多任务accept的时候,可以监听不同的端口,达到分发效果。这么做有另外的消耗,最重要的是,降低了客户端的可复用性。可能后续有一些折中,具体选用还得考虑。这些所有的模型,都使用了事件循环机制,每个事件循环可以处理一定量的accept事件和数据I/O事件。

     前几天参加风河开发者大会,提到物联网与大数据。无疑,大数据处理在现今是一个很时髦的话题。额,暂时我也没那范去搞这方面的内容,只是在看面试集锦中,总结起来,大量数据的处理,bit-map、分治法、哈希大致应该为大杀器,理解了就可以秒杀这方面的面试了。

     网络编程中,处理大量并发连接,何尝不是一种大数据呢。bit-map和哈希就不去想它了。这里主要想说的是分治法:

把一个复杂的问题分成多个的相同或相似的子问题求解,原问题的解即子问题的解的合并。

     服务器要处理的事情,归结起来,有三部分:accept、数据IO、数据处理。

     首先感谢epoll机制的高效性。以前的poll机制,有两个性能瓶颈,一是每次poll都要把需要等待的fd拷贝到内核;二是轮询。epoll则让内核保存fd来避免拷贝,以异步回调来处理事件发生。在使用时,可以把epoll看做一个数据处理工具,这个工具有自己的性能瓶颈,处理的数据量是有限制的。那么,怎么去处理超过其瓶颈的数据呢。无疑是分治法:

     将需要处理的“数据”(也可以成为事件)划分给多个epoll事件循环,这些循环交给多线程/多进程去承载。

     首先,Accept和数据IO具有连续性,你可以简单地使用多个事件循环去accept,每个事件循环处理自己连接上的数据IO。至于数据处理部分,若处理量大,一般使用线程池或者进程池处理。这个方法与UNP一书中多进程/线程Accept有异曲同工之妙,只是将每个进程/线程上的阻塞模型改为事件循环+异步非阻塞模型而已。当然,同时需要处理的还有惊群效应和负载均衡。Nginx是使用该模型的很好的例子。需要注意到的是,每个线程/进程最好只承载一个事件循环。进程/线程数量的安排也与CPU核的个数有关。SMP机制虽然可以让我们很容易使用多核CPU,但进程/线程在CPU间的转移有很大的效率上的损失,不论是VxWorks还是linux,都提供进程与CPU核的亲缘性与绑定机制,对效率上的增加有一定好处。

    其次,当Acccpt事件和IO事件不对等的时候。例如,一些应用场合Accept事件很少,甚至只是简单的接受固定的长连接事件(比如上面讲的那个嵌入式服务器),但数据IO却非常多。那么,可以再一个事件循环中专门处理Accept事件,然后将连接分发到专用IO处理事件循环中。数据处理同上一种情况,以计算量大小决定是否选择pool解决。

   但写起来,总感觉实际应用情况要复杂得多。不同的数据类型,不同的应用场合,可能在模型设计与性能优化之间有很大折中,可能在网络服务器这块选用不是效率最高的那种,但整体考虑,它可能是最适合系统整体优化的。

   项目中要用到SCTP,看来得重回UNP阅读SCTP部分了。这本书乍一看有些老了。各种编程模型在工业场合也基本不会用,但总感觉那些东西像形状不同的积木,不论是什么高级的模型,都可以再这里找到原型。OK。继续看书吧。

posted on 2018-03-09 08:43  xmj  阅读(151)  评论(0编辑  收藏  举报