内核的几个组件被设计成Service,也就是说这几个模块都要实现以下接口:数据库
图1 IService接口安全
Start方法用来启动服务。架构
Stop 方法用来关闭服务。异步
IsService 方法用于查询当前服务是否正在工做。函数
内核中的几个Service都不可以直接建立,Applications在使用这些Service的时候首先要获得一个IServiceMgr的实例,这被实现成了一个另类地单例模式。IServiceMgr的接口定义以下:spa
图2 IServiceMgr接口线程
IServiceMgr提供两类接口:设计
1) 获取Service的接口,这样直接获得具体的Service,是由于内核的Service比较固定。没有必要用GetService(strServiceName)这种方法。server
GetAsyncService 返回AsyncService的实例对象
GetDBService 返回DatabaseService的实例
GetTCPService 返回TCPServerService的实例
GetTimerService 返回定时器实例
2) 一个静态的单例方法Instance。它申明在接口层,可是须要在IServiceMgr的实现中去实现它。它返回IServiceMgr的实例。
因为IServiceMgr的实现只是简单地将IAttemptService,ITCPServerServer, IDatabaseService,ITimerService的实现组合在了一块儿,因此它的实现不会详细描述。
1 AsyncService详细设计
图3 AsyncService的详细设计
AsyncService主要是提供给其余3个Service使用的,它实现了IService接口和IAsyncService接口。由于与异步相关的功能基本上都被boost::asio实现,因此AsyncService主要只是管理boost::asio的实例 。
IAsyncService只提供了一个方法:
GetIOService 返回一个可用的boost::asio::io_service的实例
AsyncService组合了boost::asio和ThreadPool,其中boost::asio::io_service的数目和机器的cpu总数相同,而ThreadPool中线程总数为2倍的cpu数。全部ThreadPool中的线程都将做为工做线程,它们的入口函数都是io_service::run。
2 TimerService详细设计
图4 TimerService的结构图
TimerService实现了IService和ITimerService接口。ITimerService提供以下接口:
1) SetTimer(timerId,milisecs,timerFunc,repeatTimes) 设置一个id为timerId的定时器,这个定时器会被激
发repeatTimes次,每两次被小激发的时间间隔为millsecs毫秒。每次被激发都会调用 timerFunc这个函数。
2) KillTimer(timerId) 取消id为timerId的定时器。
3) KillAllTimer() 取消全部的定时器,通常用在系统关闭时调用。
TimerService管理着一些TimerItem,Applications层用一个新的timerId,调用SetTimer时,TimerService就会建立一个新的TimerItem, 而在调用KillTimer时,就会销毁掉与其相关的那个TimerItem。TimerService的实现依赖与AsyncService,由于定时器本质上也是异步操做。将由AsyncService中的io_service来统一调度。
须要注意如下几点:
1) 传给SetTimer的timerFunc这个函数要是线程安全的,由于不肯定会在哪一个工做线程的context中调用它,同时 若是你的好几个定时器公用同一个timerFunc, 就可能对共享资源形成竞争。
2) SetTimer进若是发现已经存在相同id的TimerItem, 不会建立一个新的TimerItem,而是取消先前的定时器。修 改其参数后启动。
3 TCPServerService详细设计
图5 TCPServerService结构图
TCPServerService实现了IService接口和ITCPServerService接口。ITCPServerService的几个主要接口说明:
1) SendData 经过指定的ISocketItem发送数据, 数据在通常状况下由4个参数: MainCmd, SubCmd, Data, DataSize (能够参与总休设计中关于协议的部分的描述) 。有的时候Data为空,就不须要Data和DataSize这两个参数了。
2) SendDataBatch 给全部链接发送数据。这是批量发送的,全部链接池中对应的客户端都会收到。
3) CloseSocket 关闭指定的链接。
4) SetObserver 设置监听者。用以接收异步通知。
TCPServerService 管理着一个客户端来的链接池。这个链接池由SocketItem组成,每个SocketItem都与一个整数标识对应,Applications使用这个标识来发送数据和接收数据。SocketItem主要提供下面几个接口:
1) GetIndex 获取与其对应的惟一标识
2) GetRound 因为每一个SocketItem都是能够重用的,因此为了防止混乱,好比说一个SocketItem在前一时刻对应着client1, 可是如今对应着client2。client1曾经的一个请求如今才要返回,这时若是没有GetRound就会把client1的处理结果错误地返回给client2。从这里也能够看出,每一个SocketItem的round是在链接创建的时候会增长。
3) IsConnected 是否处于链接状态。
4) SendData 发送数据。
5) GetClientAddress 获得客户端的IP地址
6) GetConnectTimer 获取链接时间。
7) Close 关闭链接。
也许你会问了,我怎么只看到发送数据的接口,而没有接收数据的接口呢?由于这是个异步架构,在有链接到来,或者数据到来的时候,你会收到通知的。前提条件是你调用SetObserver设置了监听者。TCPServerService的监听都须要实现ITCPServiceObserver接口, TCPServerService经过这个接口提供的方法来通知你链接和读取事件:
1) OnSocketAccept 在新链接到达时,会调用你这里面的内容。
2) OnSocketRead 在数据读取完成后,会调用你提供的这个方法作进一步处理。
3) OnSocketClose 告诉你链接将要关闭。
须要注意的是若是你这三个方法中有共享的数据,要加锁保护。由于工做线程可能会产生竞争状态。
和TimerService同样,TCPServerService的异步调度依赖于IAsyncService。
4.DatabaseService详细设计
图6 DatabaseService结构图
能够对比一下DatabaseService和TCPServerService的结构图,你会发现他们是那么地类似。对的,它们的设计思路一模一样。DatabaseService实现了IService和IDatabaseService这两个接口。
IDatabaseService主要只提供了3个接口:
1) Connect 链接到一个数据库
2) Query 进行查询。 这里有两点要注意:1) Query之后不会立马获得结果,由于这是异步的; 2) 存储过程的调用也得使用这个方法,你只要将query语句写成 'select stroage_procedure(param1,param2,...)' 就好了。
3) SetObserver 设置观察者。由于查询是异步的,因此你要设一个观察者来获得通知。
DatabaseService管理着一些数据库链接DBConnect, 每个DBConnect也与一个整数标识相关联,能够经过GetIndex得到。同时你能够经过IsConnect来查询这个DBConnect是否处于链接状态。
在实现IDBServiceObserver时,你须要实现下面两个方法:
1) OnDBConnect 在数据库链接创建时会调用
2) OnQueryEnd 在这里你能够获得一个表示查询结果的QueryResult对象。你能够经过它知道查询的状态,以及结果信息。