加入收藏 | 设为首页 | 会员中心 | 我要投稿 河北网 (https://www.hebeiwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 业界 > 正文

实例:一个处事器措施的架构先容

发布时间:2019-01-20 21:13:04 所属栏目:业界 来源:高性能服务器开发
导读:本文将先容我曾经做过的一个项目标处事器架构和处事器编程的一些重要细节。 一、措施运行情形 操纵体系:Centos 7.0 编译器:gcc/g++ 4.8.3、cmake 2.8.11 mysql数据库:5.5.47 项目代码打点器材:Visual Studio 2013 一、措施布局 该措施总共有 17 个线程
副问题[/!--empirenews.page--]

本文将先容我曾经做过的一个项目标处事器架构和处事器编程的一些重要细节。

一、措施运行情形

操纵体系:Centos 7.0

编译器:gcc/g++ 4.8.3、cmake 2.8.11

mysql数据库:5.5.47

项目代码打点器材:Visual Studio 2013

一、措施布局

该措施总共有 17 个线程,个平分为 9 个数据库事变线程 D 和一个日记线程 L,6 个平凡事变线程 W,一个主线程 M。(以下会用这些字母来代指这些线程)

(一)、数据库事变线程的用途

9 个数据库事变线程在线程启动之初,与 mysql 成立毗连,也就是说每个线程都与 mysql 保持一起毗连,共 9 个数据库毗连。

每个数据库事变线程同时存在两个使命行列,第一个行列 A 存放必要执行数据库增删查改操纵的使命 sqlTask,第二个行列 B 存放 sqlTask 执行完成后的功效。sqlTask 执行完成后当即放入功效行列中,因而功效行列中使命也是一个个的必要执行的使命。大抵伪代码如下:

  1. void db_thread_func()  {   
  2.     while (!m_bExit)   
  3.     {   
  4.         if (NULL != (pTask = m_sqlTask.Pop()))   
  5.         {   
  6.             //从m_sqlTask中取出的使命先执行完成后,pTask将携带功效数据   
  7.             pTask->Execute();               
  8.             //获得功效后,立即将该使命放入功效使命行列   
  9.             m_resultTask.Push(pTask);   
  10.             continue;   
  11.         }   
  12.  
  13.         sleep(1000);   
  14.     }//end while-loop  
  15.  }   

此刻的题目来了:

使命行列 A 中的使命从何而来,今朝只有斲丧者,没有出产者,那么出产者是谁?

使命行列 B 中的使命将去何方,今朝只有出产者没有斲丧者。

这两个题目先放一会儿,比及后头我再来答复。

(二)事变线程和主线程

在先容主线程和事变线程详细做什么时,我们先容下处事器编程中经常抽象出来的几个观念(这里以 tcp 毗连为例):

  1. TcpServer 即 Tcp 处事,处事器必要绑定ip地点和端标语,并在该端标语上侦听客户端的毗连(每每由一个成员变量 TcpListener 来打点侦听细节)。以是一个 TcpServer 要做的就是这些事变。除此之外,每当有新毗连到来时,TcpServer 必要吸取新毗连,当多个新毗连存在时,TcpServer 必要井井有条地打点这些毗连:毗连的成立、断开等,即发生和打点下文中说的TcpConnection 工具。
  2. 一个毗连对应一个 TcpConnection 工具,TcpConnection 工具打点着这个毗连的一些信息:如毗连状态、本端和对端的 ip 地点和端标语等。
  3. 数据通道工具 Channel,Channel 记录了 socket 的句柄,因而是一个毗连上执行数据收发的真正执行者,Channel 工具一样平常作为 TcpConnection 的成员变量。
  4. TcpSession 工具,是将 Channel 收取的数据举办解包,可能对筹备好的数据举办装包,并传给 Channel 发送。

归纳起来:一个 TcpServer 依赖 TcpListener 对新毗连的侦听和处理赏罚,依赖TcpConnection 工具对毗连上的数据举办打点,TcpConnection 现实依赖 Channel 对数据举办收发,依赖 TcpSession 对数据举办装包息争包。也就是说一个 TcpServer 存在一个 TcpListener,对应多个 TcpConnection,有几个TcpConnection 就有几个TcpSession,同时也就有几个 Channel。

以上说的 TcpServer、TcpListener、TcpConnection、Channel 和 TcpSession 是处事器框架的收集层。一个好的收集框架,应该做到与营业代码脱耦。即上层代码只必要拿到数据,执行营业逻辑,而不消存眷数据的收发和收集数据包的封包息争包以及收集状态的变革(好比收集断开与重连)。

拿数据的发送来说:

当营业逻辑将数据交给 TcpSession,TcpSession 将数据装好包后(装包进程后可以有一些加密或压缩操纵),交给 TcpConnection::SendData(),而TcpConnection::SendData() 现实是挪用 Channel::SendData(),由于 Channel 含有 socket 句柄,以是Channel::SendData() 真正挪用send()/sendto()/write() 要领将数据发出去。

实例:一个处事器措施的架构先容

对付数据的吸取,轻微有一点差异:

通过 select()/poll()/epoll() 等IO multiplex技能,确定好了哪些 TcpConnection 上稀有据到来后,激该死 TcpConnection 的 Channel 工具去挪用recv()/recvfrom()/read() 来收取数据。数据收到往后,将数据交由 TcpSession来处理赏罚,最终交给营业层。留意数据收取、解包以致交给营业层是必然要分隔的。我的意思是:最好不要解包并交给营业层和数据收取的逻辑放在一路。由于数据收取是 IO 操纵,而解包和交给营业层是逻辑计较操纵。IO 操纵一样平常比逻辑计较要慢。到底怎样布置要按照处事器营业来弃取,也就是说你要想好你的处事器措施的机能瓶颈在收集 IO 照旧逻辑计较,纵然是收集 IO,也可以分为上行操纵和下行操纵,上行操纵即客户端发数据给处事器,下行即处事器发数据给客户端。偶然辰数据上行少,下行大。(如游戏处事器,一个 npc 移动了位置,上行是该客户端关照处事器本身最新位置,而下行确是处事器要汇报在场的每个客户端)。

(编辑:河北网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读