同一个功能的软件,不同的团队,不同工程师去实现,肯定是千差万别,甚至从根本上完全不同。所以软件开发在未来很长时间内仍然是一项工匠的手工劳动,尤其像多任务,高并发,偏底层这种对实现技巧比较高的系统,这种系统对开发者来说仍然充满挑战,考验工程师对产品的理解,经验的积累,技术方案的取舍,以及各种因素的权衡。总之,平庸的软件系统,很多人都可以做,但在这个领域内的标杆产品,只有功力深厚的工程师才能驾驭。

对应用服务器业务类型的深入理解
开发一个产品,肯定要先对产品的业务和功能必须有深入的理解,脱离业务去谈产品的技术实现,那无异于空中楼阁,没有根基,产品是为解决业务需求,业务痛点而存在的。首先架构师将一个大的解决方案进行模块切分,然后对每个软件业务模块进行需求定义,接下来技术专家对实现方案进行技术论证决策和开发任务提炼,最后开发工程师负责开发任务的实现。作为各个环节的参与者,我们首先要深入理解需求定义,探明软件日常的工作场景,然后才能有针对性的进行相关的构建和设计。
我们一般大体上将服务器软件类型分为“IO密集型”和“计算密集型”。IO密集型,顾名思义,就是说软件要处理高并发,大数据量的网络或者文件IO请求,这时我们要将CPU计算资源向IO倾斜,并审慎的选择高效的IO模型,IO模型的选择也包含了很多技术内容,同时也有很多的框架支撑,具体不在此赘述。计算密集型,就是说软件的主要业务是进行同步计算,这时我们的侧重点要考虑如何在多核CPU之间分配、同步这些计算任务,使之充分利用计算资源;IO层面如何做到精简,稳定,可靠。当然也存在着“IO和计算混合型”,那我们就要结合具体业务综合考虑技术方案。总之,兵无常势 水无常形,具体问题,具体分析,决策的依据都来源于我们日常的总结与积累。

计算任务的合理分配(多任务CPU资源的分配)
我们早已迈入多核CPU的时代,在服务器领域,尤其如此。服务端的软件系统要充分利用计算资源,那就必须适应多核CPU的并发特性。提到这里,很多人会想“不就是多搞几个线程就行了,有什么难的”,是啊,那搞几个线程?为什么要把这个任务放在这个线程里?深究起来,都不是简单的问题,我们在开发一个系统前,必须要有“并发性规划”,根据业务特点,进行进程,线程,线程池,同步/异步,阻塞/非阻塞的规划选择,任何选择都不是随意的,都是有考量和统筹的,甚至有模拟演算,这样的决策才是科学、有效的。

IO复用模型的合理选择
服务端系统要么要接收外界的数据流,要么要监听外界的指令。数据流和指令的接收处理方式,都要涉及到IO模型的选择,尤其对IO密集型的应用,IO模型的选择和开发实现,是产品成功与否的关键,这也是CamelProxy的核心技术。除了标准的socket标准,不同的操作系统平台也对IO复用模型有不同的技术支持,比如Linux平台的poll, epoll,Windows的重叠IO,完成端口等。同时也产生了很多第三方的跨平台的C++网络开发框架和库,同时支持同步的,异步的,反应式,前摄式的等操作方式,并且也提供了很多网络开发过程必不可少的组件,比如主动对象,线程池,消息队列,同步控制等。这方面的框架包括ACE, Libevent, Boost等,都是非常好的网络开发知识总结和实现。总之,没有差的技术,只有合不合适你当前场景的技术,合理的选择,将会事半功倍。

内存资源的高效使用
作为一个服务器后台系统的开发者,我们都希望自己的系统高效,能够长时间稳定运行的,最好能连续几个月,不需要重启的。从我们的经验来看,要达到这个目标,必须对内存的调配使用要着重考量。内存的使用也是反应一个开发者在C, C++编程能力的重要指标,如果代码中临时对象,内存复制满天飞,起码就反映了开发者对语言的机制没有深入洞悉。在内存使用技巧上,要注意两个方面。首先,不要频繁的进行内存的动态分配,释放,避免内存碎片的累积。很多系统也没有内存泄漏,但随着运行时间的退役,内存占用量不断上升,最终到了一个临界点,然后系统就必须重启。内存最好在系统开始运行就分配好,再根据系统的负载的变化动态的调整预分配的内存,或者用内存池等技巧来优化;再者,编程实现时,注重指针,引用的使用,避免不必要的临时对象的产生,用不好指针的程序员,不是合格的C++开发者。总之,开发高效,稳定的系统,内存的编程实现技巧必不可少,考验的也是开发者的功力于思考。

多线程并发的有效控制
充分挖掘多核CPU的计算能力,就必须应用多线程,多执行路径的程序设计方式。多线程开发除了带来线程路径设计和执行任务分配的问题外,还有一个重要的问题就是线程间的协作和通信。这不仅包括了多线程对竞争资源的访问控制,也包含了线程的通知激活,优雅退出,以及衍生出来消息队列,流水线操作,都需要适当的场景选择合适的方案。

语言工具的选择
干什么活用什么样的工具,工具的选择会使过程和结果事半功倍。做高性能,大容量,高并发服务端后台服务软件系统,开发语言一定是C,C++, 因为该语言提供了足够的空间,让你充分运用各种技巧来优化程序的性能,这是其他高层语言所不能具备的,其他语言为了降低开发者所需掌握的难度与复杂性,做了太多的封装与抽象化,不适合做一些高性能的应用。
选择了对的工具,剩下的就是考验实现者对工具的运用的水平,也是系统实现的关键和核心,也体现了一个高水平开发者对软件的认识与思考,懂得如何有的放矢,充分解决问题,又不臃肿。正可谓“增一分则太长,减一分则太短”,取舍之间,大有乾坤。

这是在开发网络代理服务器CamelProxy系统-CamelProxy代理服务器过程中一点经验总结,如果您有更好的建议,欢迎批评指正。