发现问题



    前些日子维护编写的通讯服务器时遇到了这么一个问题:在通讯服务器里有一个数据库连接池,为他人提供数据库连接服务,结果发现在使用过程中连接有时会耗尽,这个问题通过调试跟踪发现,有“客户”在使用数据库连接时,总是不释放连接(已提供了释放连接的方法)。其实问题很好解决,找出未释放连接的那个“客户”然后按照GetConnection,ReleaseConnection的方式来正确调用就可以了。





解决问题?



    但是找出那个“客户”很容易吗?看看我们的整个系统吧,多达五个子系统插件在使用这个服务,而且其中的数据库连接调用很多,这样找可费了大劲了。在经过大量的代码审核后,终于找出未释放连接的那个客户,解决了这个问题。








思考之下,作为一个关键的公共服务是不是可以做相应优化来应对这种“客户”犯下的错误。





采用RAII机制,把释放链接的那个方法也写入析构函数中



    举例(采用伪码加不标准类写法方式,主要是说明思路;参考effective c++章节2 构造/析构)



class ConnectionPool 
    
 { 
    
public: 
    

   ... 
    

   ~ConnectionPool( 
    void); 
    
   { 
    
      
    if (!bRelease) 
    
     { 
    
       Release连接(); 
    
     } 
    
   } 
    

    
    void  ReleaseConnection() 
    
   { 
    
     Release连接(); 
    
     bRelease =  
    true; 
    
   } 
    
private: 
    

   bool  bRelease;     (初始化为 
    false) 
    
 };





这样”客户“如果是采用栈或智能指针实例化的对象来使用服务,即使忘记释放连接都可以利用RAII机制安全释放;





但是如果”客户“直接用new出的对象使用服务忘记释放连接呢,又回到了最先遇到的问题上,在一大推调用里找究竟是谁未释放连接。继续解决:



    既然现在我们的困扰集中在找违规”客户“的麻烦上,想想图书馆借书,谁借去了必须把他的名字登记下来,谁谁谁借走了这本书,到时候即使他不还,咱也有办法找到他让他给咱还回来。于是我们可以再改造一下这个服务,在每个”客户“获得连接时都传入他的标识然后把这个连接和标识捆绑起来。这样,哪个”客户“未释放连接一目了然了吧,立马找到他让他改正。OK,快速解决。

原文链接http://blog.51cto.com/yaocoder/838130