服务器开发之 IO 处理
来源:互联网 发布:淘宝上的日系店铺 编辑:程序博客网 时间:2024/05/28 20:19
服务器的主要事务是处理各种逻辑,为上千上万的用户提供特定的服务。所以,对它的要有能够应对高并发的特点,同时还要有高的响应处理能力,稳定性更是不用多说,这是第一位的,没有玩家希望自己购买的道具丢失。
下面花一个简单的服务器进程的模型图,说明服务器进程的基本事务结构,其实就是和一些他要处理的 IO 的关系。
简单说明一下:
IO(A)负责处理客户端的接入。
IO(B)负责和别的服务器进行通信,交换数据。
IO(C)负责加载和保存数据。
下面说说这些IO特点,这些io的共同特点都是比较慢的,并且他们的操作都是会阻塞的,最快的也应该是0.001秒的数量级别,这也许在我们看来是很快了,如果每个处理都是0.001秒,那么一秒钟也就处理1000个,这个速度对服务器来说还是太慢,所以我们要这些io的操作放到独立的工作线程里面去处理他们的io读和写操作,逻辑放入到主逻辑线程D里面去操作。因为逻辑需要牵涉到方方面面的数据和操作,如果直接在线程里面处理是需要很多的线程安全机制来保证安全,这样会给逻辑开发带来工作量,也给调试带来困难。这就是我想说的,我们应该如何处理这些io数据。这个时候你心里肯定也知道,我弄个线程安全的队列来交换数据。呵呵,是的你想的很多,大的理论就是这样干的,我想说一些细节上面的东西。
struct TDataBlock
{
index; //数据库编号
enter_time; //进入队列的时间
live_maxtime; //最多生命时间
//
yourdatabufer; //你自己的数据信息
}
数据处理的大概流程,
注意:
1: 必须注意 app_run(), ThreadRun(),这个两个函数里面的异常处理,保证队列的正常进入和删除,否则会有内存泄漏,或者造成线程死循环,永远在处理一个数据块,而这个数据块也一直在发生异常。
2: ThreadRun(void)上面的函数如果是子线程可以直接完成的工作,比如本地文件,数据库等操作,也就是说是同步完成的,是不要什么额外的处理工作的。 如果是异步的处理方式,比如网络。你需要添加一个map来保存正在处理的数据块,并且定时的检查他们得儿完成情况,并且做容错处理,这样一方面保证内存的安全,同时也保证客户端不会死等在一个界面里面。同时也降低客户端的冗余工作量。当然了一个好的客户端还是要有超时处理的。
下面花一个简单的服务器进程的模型图,说明服务器进程的基本事务结构,其实就是和一些他要处理的 IO 的关系。
简单说明一下:
IO(A)负责处理客户端的接入。
IO(B)负责和别的服务器进行通信,交换数据。
IO(C)负责加载和保存数据。
下面说说这些IO特点,这些io的共同特点都是比较慢的,并且他们的操作都是会阻塞的,最快的也应该是0.001秒的数量级别,这也许在我们看来是很快了,如果每个处理都是0.001秒,那么一秒钟也就处理1000个,这个速度对服务器来说还是太慢,所以我们要这些io的操作放到独立的工作线程里面去处理他们的io读和写操作,逻辑放入到主逻辑线程D里面去操作。因为逻辑需要牵涉到方方面面的数据和操作,如果直接在线程里面处理是需要很多的线程安全机制来保证安全,这样会给逻辑开发带来工作量,也给调试带来困难。这就是我想说的,我们应该如何处理这些io数据。这个时候你心里肯定也知道,我弄个线程安全的队列来交换数据。呵呵,是的你想的很多,大的理论就是这样干的,我想说一些细节上面的东西。
struct TDataBlock
{
index; //数据库编号
enter_time; //进入队列的时间
live_maxtime; //最多生命时间
//
yourdatabufer; //你自己的数据信息
}
数据处理的大概流程,
//一个现场安全的队列template<typename A>class XThreadSaveQueue{ typedef std::list<A> IN_QUEUE;public: XThreadSaveQueue(){ } ~XThreadSaveQueue(){} void push(const A _Val) { CXXLocker lock(); m_q.push_back( _Val ); } void push_front(const A _Val) { CXXLocker lock(); m_q.push_front( _Val ); } A pop( bool &isok ) { CXXLocker lock(); isok = false; if( m_q.empty() ) return A(); isok = true; A item = m_q.front(); m_q.pop_front(); return item; } A& front() { CXXLocker lock(); return m_q.front(); } unsigned int size() { CXXLocker lock(); return m_q.size(); } bool empty() { CXXLocker lock(); return m_q.empty(); }private: IN_QUEUE m_q;};typedef XThreadSaveQueue<TDataBlock*> QueueData;class CYourWorkThread:public CThread{public: CYourWorkThread(); virtual ~CYourWorkThread(void);public: void push_req( TDataBlock *pData ){ m_req_queue.push(pData); } //这个函数工作在主逻辑线程里面 void app_run() { //处理rep返回的数据 }protected: //这个函数工作在子线程里面 void ThreadRun(void) { //处理req的请求队列 }private: QueueData m_req_queue; //我自己需要处理的请求队列 QueueData m_rep_queue; //我自己需要处理的请求队列};
注意:
1: 必须注意 app_run(), ThreadRun(),这个两个函数里面的异常处理,保证队列的正常进入和删除,否则会有内存泄漏,或者造成线程死循环,永远在处理一个数据块,而这个数据块也一直在发生异常。
2: ThreadRun(void)上面的函数如果是子线程可以直接完成的工作,比如本地文件,数据库等操作,也就是说是同步完成的,是不要什么额外的处理工作的。 如果是异步的处理方式,比如网络。你需要添加一个map来保存正在处理的数据块,并且定时的检查他们得儿完成情况,并且做容错处理,这样一方面保证内存的安全,同时也保证客户端不会死等在一个界面里面。同时也降低客户端的冗余工作量。当然了一个好的客户端还是要有超时处理的。
0 0
- 服务器开发之 IO 处理
- IO之异常处理
- java之IO处理
- java之IO处理
- 服务器IO模型之Select
- Java之IO异常处理
- java IO 之 异常处理
- p2p服务器开发异常处理
- 嵌入式Web服务器学习之阻塞IO/非阻塞IO
- 手游服务器之数据IO进化
- 服务器监控之zabbix监控IO篇
- Linux并发服务器编程之IO多路复用
- Java基础之IO流处理
- 驱动编程学习笔记之IO处理
- 驱动编程学习笔记之IO处理
- JAVA之IO技术异常处理机制
- IO之 处理流包装节点流
- java IO流 之 处理流
- 关于mysql
- android - actionbar
- 4003. I-number
- C++ static、const和static const、引用以及它们的初始化
- #一日一图#中秋快乐之美工也放假
- 服务器开发之 IO 处理
- python代码调试
- 终端下的Ubuntu14.04
- 树和二叉树总结及算法实现
- 卓越的前提
- 第一课之2-STM32-RCC
- Android Fragment 真正的完全解析(上)
- Java异常处理机制
- OutOfMemoryError异常 (笔记)