关于网络服务端多线程的处理及缓冲区的设置有关问题

关于网络服务端多线程的处理及缓冲区的设置问题
请教网络版的各位大牛:

在下目前想弄一个能承载较多负荷和并发连接数的网络服务端,目前暂时有RAKNET和ACE IOCP两者之间选择一套内核的方案——这个不是重点,重点是我根据到处找资料所获得的一鳞半爪的知识,自己弄了一个服务端的接收数据和处理数据的模型,请各位看看这样的做法是否合理,如果不对,问题在哪里,应该如何做等等。

大致上,我打算采用一个线程接收客户端的连接和传过来的数据,然后使用STL的QUEUE队列作为缓冲区存放,再另外调用2-3个数据库线程读取缓冲区内的数据,对数据库进行访问,这样做的原因是因为数据库的访问和读取较慢,我不想将他们和网络服务端的工作放在一个线程上,以提高网络服务端的接收和处理效率。然后为了防止多线程之间数据读写的扰乱问题,我在QUEUE队列的PUSH和POP处各加了一把临界区的进程锁(Critical Section)。

目前在局域网的小范围环境和低压力下测试貌似正常,可我很担心这套模型设计有问题:

1、STL的QUEUE队列在PUSH和POP的时候,分配和释放内存的动作在高压力环境下是否会开销大量的系统资源导致性能下降?
2、临界区的那两把锁加的地方是否正确?

这是测试时使用RAKNET所写的服务端接收部分的一段代码,使用了STL QUEUE作为缓冲和CS进程锁:
C/C++ code

DWORD NetServer::ReceiveProc(LPVOID lpParam)
{
    NetServer *InP = reinterpret_cast<NetServer*>(lpParam);

    while (true == InP->m_IsRuning)
    {
        Sleep(1);

        for (InP->m_RakPack = InP->m_RakInterface->Receive(); 
            InP->m_RakPack; 
            InP->m_RakInterface->DeallocatePacket(InP->m_RakPack), InP->m_RakPack = InP->m_RakInterface->Receive())
        {
            InP->m_PacketId = InP->GetPacketIdentifier(InP->m_RakPack);
            memset(&InP->m_Receive, 0, sizeof(InP->m_Receive));
            memcpy(&InP->m_Receive.Addr, &InP->m_RakPack->systemAddress, sizeof(RakNet::SystemAddress));

            switch (InP->m_PacketId)
            {
            case CONST_ID:
                {
                    int Lenth = InP->m_RakPack->length;
                    if (Lenth > BUFFER_SIZE)
                    {
                        Lenth = BUFFER_SIZE;
                    }

                    memcpy(InP->m_Receive.Buffer, InP->m_RakPack->data, Lenth);
                    InP->m_Receive.Lenth = InP->m_RakPack->length;

                    EnterCriticalSection(&InP->m_ReceiveCS);
                    InP->m_ReceiveQueue.push(InP->m_Receive);
                    LeaveCriticalSection(&InP->m_ReceiveCS);

                    ::PostMessage(InP->m_hWnd, InP->m_MsgID, InP->m_WPID, SOCKET_RECEIVE);
                }
                break;
            case ID_NEW_INCOMING_CONNECTION:
                {
                    EnterCriticalSection(&InP->m_AcceptCS);
                    InP->m_AcceptQueue.push(InP->m_Receive);
                    LeaveCriticalSection(&InP->m_AcceptCS);

                    ::PostMessage(InP->m_hWnd, InP->m_MsgID, InP->m_WPID, SOCKET_ACCEPT);
                }
                break;
            case ID_CONNECTION_LOST:
            case ID_DISCONNECTION_NOTIFICATION:
                {
                    EnterCriticalSection(&InP->m_CloseCS);
                    InP->m_CloseQueue.push(InP->m_Receive);
                    LeaveCriticalSection(&InP->m_CloseCS);

                    ::PostMessage(InP->m_hWnd, InP->m_MsgID, InP->m_WPID, SOCKET_LOST);
                }
                break;
            default:
                {

                }
            }
        }
    }

    return 1;
}



我原本想自己写一个类似QUEUE的链表专门作为缓冲,一启动就NEW几百几千个容器,每当有新的数据放进来时,就不用重新NEW而是直接使用;等使用完毕后也不释放,而是循环再利用;然后开个计时器定时监视剩余容器数量,不够的话再另外加。但是这样的设计貌似不是一般的复杂,也不太好写,因此想偷懒使用STL,但又担心它的资源开销问题……

如果我这样做是不对的,请各位牛人指点一下,一个合格的网络服务端到底应该怎样处理相关的问题?谢谢!

------解决方案--------------------
raknet udp 内外网通讯很麻烦
ace不熟.
boost asio可以考虑.
自己写套iocp.
------解决方案--------------------
1 首先要分析瓶颈在什么地方?
是输入的网络带宽?网络连接?
还是中间STL对方开销的内存?
还是数据库处理线程的速度跟不上导致拥堵?
2 找到最短的这个板之后,以这个最短板为基础
设计协议

因为你并没有给出 你的数据库究竟是单机数据库,还是普通的MYSQL数据库,或者干脆是大型机上的DB2 ORACLE等,也没有给出网络带宽? 根据经验,遇到大规模并发的时候,一般数据库是最大的短板,而如果数据库阻塞,而你的STL对象没有进行合理的超时判断,很容易导致内存过载

另外,我个人的开发经历,最开始我也是用STL对象,毕竟管理和操作方便,不过现在已经回归最基本的C结构struct + 原子操作了,锁在这里不会对效能产生大影响,放心用好了