这个系列把毕业论文的部分贴了出来,以作保存留念。整个系列分为三大部分,其中第一章到第三章是介绍服务器的系统层设计,设计思路参考了libevent和muduo等开源代码的实现;第四章到第六章是介绍服务器的服务层设计,设计思路参考了自己的Khala实现;第七章介绍了如何利用该服务器框架实现一款类似于QQ的聊天系统。全文主要参考了陈硕的《Linux多线程服务端编程》、《Unix网络编程卷1》。

系统简介

  本系统是用C++设计实现的TCP网络服务器框架。该系统底层I/O部分采用基于Reactor模式的非阻塞模型,线程部分采用event loop+ 线程池模型。系统的服务层具有超时检测管理、多类型设备和多事件消息管理,以及连接生命周期管理的功能。同时整个系统通过封装实现了网络实现与业务逻辑相分离的多线程网络框架。

  该框架面向网络业务开发者,对整个网络服务端的开发过程提供了更高层的封装,能够大大降低业务开发难度。通过该框架,开发者无需关心底层网络I/O及多线程下并发连接的实现,只需根据具体业务所属设备类型编写业务逻辑作为消息响应事件,并可以选择使用服务层提供的相关服务作为业务支持。

  该框架适用于局域网内基于TCP长连接的业务场景。比如智能家居下的多设备管理,局域网内的多用户聊天工具等。在这些场景中,通过使用本系统框架,开发者只需编写少数业务相关的代码即可完成服务端功能的实现。

系统需求分析

  本服务器系统主要从高效和易用两个方面作为设计的核心。

  高效是指合理设计系统底层的I/O和线程模型,充分利用CPU和内存资源,达到尽可能的高连接和高并发的要求。此处只考虑服务器硬件性能的利用,并不考虑以太网带宽的限制。

  易用是从两个方面出发进行考虑。第一是将网络细节与业务逻辑相分离,使该框架的开发者从底层琐碎细节中解脱出来,只需专注于业务逻辑的编写;第二是提供一层服务层,能为对于连接超时、多设备及生命周期支持等特定场合下有特殊需求的开发者提供服务支持。

  本服务器系统的基本需求分析如下:

  • l  环境需求:本系统只考虑在安全可控的局域网内部使用,网络数据采用明文传输,局域网内客户机可能会因为网络故障或死机等异常导致与服务器断开。但是并不考虑服务器可能被某些用户恶意攻击的场景。因此本系统并不为安全性做特别的增强。在公网环境上使用本服务器系统是不安全的。
  • l  操作系统需求:由于服务器系统涉及大量与底层操作系统交互的过程,如I/O及网络的处理,而不同操作系统的系统调用并不完全相同。比如在I/O复用上,虽然大多数系统均提供了select作为系统调用,但是该调用有着O(n)的时间复杂度,效率低下。因此不同系统各自实现了不同的类似系统调用作为优化,比如Linux系统下提供了epoll,BSD系统下提供了kqueue,Windows下提供了IOCP。虽然可以通过适配器模式对这些系统特性进行封装,抽象出一层跨平台的统一接口,但这将大大增加整个设计实现的工作量,同时这也不是本系统设计的重点。因此本服务器系统只支持X86-64下的Linux,不考虑可移植性,不支持Windows等其他平台。
  • l  网络需求:由于服务器系统涉及基于TCP/IP协议的网络编程过程,而在TCP/IP中又存在多种选择。在传输层中,存在TCP和UDP两种协议,其中TCP是可靠的字节流协议,而UDP是不可靠的数据报协议。由于本服务器系统大多运用于局域网内,且原生业务中并无类似音频和多媒体应用等大数据量的传输要求,同时由于对于连接的生命周期的设计将是系统设计的重点。因此我们优先采用基于可靠性和有序性、面向连接的TCP协议,并不支持UDP协议。同时由于开发时间及成本的关系,本系统只目前支持IPv4,不考虑兼容IPv6。
  • l  性能需求:作为服务器系统应该能够充分利用CPU和内存资源。同时能够发挥多核处理器的效能,原生支持多核多线程,并保证线程安全,而不像libevent本身只支持单线程,需要后期进行多线程修改。
  • l  数据传输需求:TCP协议是一个无边界的字节流协议,但读写数据处理是以一条完整消息为单位的。因此服务器需要能够区分消息边界,能够解决“目前收到的数据暂时不能构成一条完整消息”和“一次收到多条消息的数据”等情况。同时在多线程的环境下需要保证消息的正确和有序,即不能出现一条消息内混入另一条消息的数据,并且每条消息按照接收顺序等待被处理。同时以上细节不能暴露给用户,用户应该只需关注收到一条完整消息的处理,及每次发送出去一条完整的消息。

  同时服务器框架提供了一些特定服务,可以为某些特殊业务的开发提供便利。开发者可以选择使用其中某些框架服务支持,也可以选择自己另行实现。这些服务相关的需求分析如下:

  • l  超时检测:服务器应该能够检测长期未发送有效数据的空闲连接。这些连接很有可能是由于机器断电、网线故障或防火墙导致的的僵死连接。大量的僵死连接将占用服务器资源,影响服务器性能。因此当服务器检测到这些可能的僵死连接后,应该尝试通知这些连接,并最终断开这些僵死连接,释放它们占用的系统资源。
  • l  多设备管理:不同于传统服务器仅对消息进行解析回复,而不对消息事件进行归类管理。本服务器系统应该能够管理不同连接客户的设备类型,并能够对来自不同类型设备的不同消息消息进行权限管理。即某个设备类型的连接无权限请求属于另一个设备类型的消息事件。而如果某个消息事件同时属于多个设备类型,每种设备类型的连接请求该消息事件的消息处理机制也不尽相同。用户可以为系统创建新的设备类型,为该设备类型注册不同的消息事件,并针对每种消息事件编写具体的业务处理代码。
  • l  连接生命周期管理:每个连接的过程存在多个阶段,比如连接的建立,登录的验证,退出前的处理等。服务器为每个连接的不同阶段中预留了不同的接口,并保证这些接口内代码的线程安全。这些接口由不同设备类型进行管理,用户可以根据不同的设备类型重写这些接口,完成对不同设备类型的每个连接在不同阶段的下的操作管理。

系统总体架构

  如图2-1所示,整个服务器框架由系统层、服务层和用户层组成,运行于Linux操作系统之上。其中系统层和服务层构成框架主体,并通过相关接口提供给用户层使用。用户层由框架的使用者依据具体业务进行实现。每层的具体介绍如下。

图2-1 服务框架软件架构图

  系统层是整个服务器系统框架的核心。它与操作系统交互,通过I/O和线程等机制,保证了整个系统的正常高效运行,并提供了对底层系统及网络等细节的封装,保证了与上层具体业务逻辑的分离。

  系统层由Reactor模式、多线程模型、连接对象和应用层I/O缓冲四个部分组成。在Reactor模式中,通过Linux下的epoll系统调用实现的非阻塞I/O机制,实现了对不同连接的I/O事件的管理,构成了系统层的主体。同时在多线程模型中,采用了event loop + 线程池机制[39],同时线程间通过任务队列的形式进行通信,并且保证对于每个连接的整个连接周期中都在一个线程中进行管理。在连接对象部分,对每个连接的描述符等信息和连接相关操作进行了封装处理。在应用层I/O缓冲中,通过缓冲机制,封装了非阻塞I/O下的数据收发处理,保证了数据收发下的完整性。

  服务层是在系统层的基础上进行了进一步封装,并提供了更多的服务功能。理论上整个框架可以剥离服务层而单独在系统层上运行,但框架的易用性将大打折扣,同时业务逻辑也将很容易侵入到系统层的代码中。使用者可以根据具体业务需求选择使用服务层的某些功能,对不需要的服务进行关闭。因此在实际使用中应该基于服务层提供的接口进行开发工作。

  服务层主要由连接超时管理、多设备类型管理和连接生命周期管理三个部分组成。

  在连接超时管理中,服务层通过心跳机制对每个连接进行计时,客户端需要每隔一段时间向服务器发送有效数据,通知服务器连接仍然在线。当服务器检测到某个连接超时时,将会执行超时接口中实现的处理机制,并强制将该连接断开连接并移除系统。用户可以设置超时时间,并通过超时接口为不同设备制定不同的超时处理机制。

  在多设备类型管理中,服务层提供了以设备类型为单位制定不同的消息事件,并为不同消息事件实现具体处理的机制。服务层默认实现了临时设备类型和登录设备类型这两种设备类型,并为其制定了和登录相关的消息事件及处理。

  连接的生命周期管理主要是提供一组和连接的生命周期状态变化和错误处理相关的接口,并以设备类型为单位进行管理。这些生命周期状态包括连接的建立、登录、超时及退出等。用户可以为不同的设备类型的连接制定不同的生命周期接口实现,比如统计每一个新建连接信息,或对不同类型的登录连接进行验证等。

图2-2 用户创建新的设备类型

  用户层位于整个服务器系统框架之上,由该框架的使用者根据具体的业务需求进行实现。使用者主要工作为根据连接类型创建新的设备类型对象,如图2-2所示,并为新的设备类型注册业务相关的消息事件和处理机制,并根据需求实现该设备类型对应连接的生命周期接口。

  整个服务器框架设计中并不涉及磁盘文件I/O和数据库操作,而在具体服务端业务编程中通常会涉及数据库操作。如果需要连接使用数据库,服务端开发者应该在系统用户层自行实现或导入第三方的数据库操作类库,比如Mysql++库等,并通过该库的API实现与后台数据库的交互操作。

C++服务器设计(零):总体设计的更多相关文章

  1. 基于内存,redis,mysql的高速游戏数据服务器设计架构

    转载请注明出处,欢迎大家批评指正 1.数据服务器详细设计 数据服务器在设计上采用三个层次的数据同步,实现玩家数据的高速获取和修改. 数据层次上分为:内存数据,redis数据,mysql数据 设计目的: ...

  2. H2Engine游戏服务器设计之属性管理器

    游戏服务器设计之属性管理器 游戏中角色拥有的属性值很多,运营多年的游戏,往往会有很多个成长线,每个属性都有可能被N个成长线模块增减数值.举例当角色戴上武器时候hp+100点,卸下武器时HP-100点, ...

  3. 游戏服务器设计之NPC系统

    游戏服务器设计之NPC系统 简介 NPC系统是游戏中非常重要的系统,设计的好坏很大程度上影响游戏的体验.NPC在游戏中有如下作用: 引导玩家体验游戏内容,一般游戏内有很多主线.支线任务,而任务的介绍. ...

  4. h2engine游戏服务器设计之聊天室示例

    游戏服务器设计之聊天室示例 简介 h2engine引擎建群以后,有热心网友向我反馈,想尝试h2engine但是没有服务器开发经验觉得无从入手,希望我能提供一个简单明了的示例.由于前一段时间工作实在忙碌 ...

  5. 基于内存,redis,mysql的高速游戏数据服务器设计架构 ZT

    zt  http://www.cnblogs.com/captainl1993/p/4788236.html 1.数据服务器详细设计 数据服务器在设计上采用三个层次的数据同步,实现玩家数据的高速获取和 ...

  6. FPS游戏服务器设计的问题 【转】

    一.追溯 去gameloft笔试,有一个题目是说: 叫你去设计一个FPS(第一人称射击游戏),你是要用TCP呢还是要用UDP,说明理由 . 二.学习 这是两篇网上找到的文章,写非常不错. 当时笔试的时 ...

  7. 机动车驾驶员计时培训系统符合性检测平台TCP服务器设计和开发

    驾校计时平台的TCP服务器,主要用于接入计时终端,计时终端与计时平台.计时平台与省级监管服务平台.省级监管服务平台与全国驾培平台的卫星定位过程明细数据和学时过程明细数据接口应使用基于JT/T 808标 ...

  8. 高性能服务器设计(Jeff Darcy's notes on high-performance server design

    高性能服务器设计(Jeff Darcy's notes on high-performance server design 我想通过这篇文章跟大家共享一下我多年来怎样开发“服务器”这类应用的一些想法和 ...

  9. unity3d + photon + grpc + nodejs + postgis/postgresql 游戏服务器设计

    unity3d + photon + grpc + nodejs + postgis/postgresql 游戏服务器设计 最近做玩票性质的游戏项目,客户端技术是 unity3d 和 android. ...

  10. (转)FPS游戏服务器设计的问题

    FPS游戏服务器设计的问题出处:http://www.byteedu.com/thread-20-1-1.html一.追溯 去gameloft笔试,有一个题目是说: 叫你去设计一个FPS(第一人称射击 ...

随机推荐

  1. 大家来找茬-SpringMVC中Tomcat正常启动,始终访问不了Controller,出404错

    创建了一个空的SpringMVC项目,Tomcat可以正常启动,但是运行的时候,始终进不了Controller,并且报404错误. 百度各种查,结果也是查不到原因.各个群里面各种求,各种贴源码,也没有 ...

  2. Hbase写数据,存数据,读数据的详细过程

    Client写入 -> 存入MemStore,一直到MemStore满 -> Flush成一个StoreFile,直至增长到一定阈值 -> 出发Compact合并操作 -> 多 ...

  3. Lua 字符串函数小结

    1.求字符串长度 string.len(str) 2.大小写转换 string.upper(str) string.lower(str) 3.字符串查找(非全局) --func_string.lua ...

  4. Tornado web 框架

    Tornado web 框架 其实很简单.深度应用 一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像we ...

  5. 使用ARM模板在Azure中国大规模部署DCOS集群

    容器技术是目前非常流行的技术,尤其是在以Docker作为容器引擎的推动下,让容器的轻量级,可移植,自包含,隔离性等的上了一个新的台阶,目前谈及Dev/Ops,CI/CD很少能够绕过Docker的. A ...

  6. 可以让javascript加快的脚本(收藏了)

    <?php        ob_start('ob_gzhandler');        header("Cache-Control: public");        h ...

  7. Effective Java实作hashCode() - 就是爱Java

    hashCode()这个方法,也是定义在Object class中,这个是所有class的base class,因此所有的class也都继承这个方法,预设是传回这个对象储存的内存地址编号,因为Mix覆 ...

  8. 一颗 45nm CPU的制造过程

    沙子 :硅是地壳内第二丰富的元素,而脱氧后的沙子(尤其是石英)最多包含25%的硅元素,以二氧化硅(SiO2)的形式存在,这也是半导体制造产业的基础. 硅熔炼: 12英寸/300毫米晶圆级,下同.通过多 ...

  9. 统计维护<第四篇>

    SQL Server允许用户手工地控制单独数据库中的统计维护.SQL Server的4个主要的控制紫铜统计的维护的配置如下: 在无索引的列上新建统计(自动创建统计): 更新现有统计(自动更新统计): ...

  10. 《数据通信与网络》笔记--SSL/TLS

    上次简单地介绍了IP层的安全,今天来介绍下在传输层提供安全性最主要的2个协议:安全套接字层(SSL)协议和传输 层安全(TLS)协议.TLS实际上就是SSL的IETF版本. 1.SSL服务 设计安全套 ...