当前位置: 首页 > 科技观察

连接池就是这么简单(一分钟系列)

时间:2023-03-20 13:39:42 科技观察

1.如何通过连接访问下游在工程架构中访问下游有很多需求。下游包括但不限于服务/数据库/缓存。通信步骤为:(1)与下游建立连接(2)通过此连接,收发请求(3)交互结束,关闭连接,释放资源Driver、Document、DemoCode教用户建立一个连接和调用接口,以MongoDB的C++官方DriverAPI为例(伪代码):以MongoDB的C++官方DriverAPI为例(伪代码):DBClientConnection*c=newDBClientConnection();c->connect("127.0.0.0.1:8888");c->insert("db.s",BSON("shenjian"));c->close();这个DBClientConnection是与MongoDB的连接,官方的Driver提供了几个API,允许用户连接MongoDB,进行增删查查修改关闭操作,从而实现不同的业务逻辑。2、为什么需要连接池?当并发很低的时候,上面的伪代码没有问题,但是当服务单机QPS达到几百上千的时候,建立连接和销毁连接close就会成为瓶颈。如何优化?结论也很简单。服务启动时,首先建立几个连接Array[DBClientConnection]。有请求过来,从Array中取出一个,执行下游操作,执行完放回去,避免重复建立和销毁连接,提高性能。而这个维护Array[DBClientConnection]的数据结构就是连接池。有了连接池,数据库操作的伪代码就变成了:DBClientConnection*c=ConnectionPool::GetConnection();c->insert("db.s",BSON("shenjian"));ConnectionPool::FreeConnection(c);三、连接池核心接口及实现通过上面的讨论可以看出,连接池ConnectionPool主要有三个核心接口:(1)Init:初始化Array[DBClientConnection],该接口只在服务启动时调用一次(2)GetConnection:请求不是每次需要访问数据库就连接一个连接,而是通过连接池的接口获取(3)FreeConnection:请求不是每次访问数据库就关闭一个连接,而是把连接返回连接池连接池核心数据结构:(1)连接数组ArrayDBClientConnection[N](2)互斥锁数组Arraylock[N]连接池核心接口实现:Init(){fori=1toN{ArrayDBClientConnection[i]=new();ArrayDBClientConnection[i]->connect();Arraylock[i]=0;}}说明:初始化所有连接和互斥体GetConnection()fori=1toN{if(Arraylock[i]==0){Arraylock[i]=1;returnArrayDBClientConnection[i];}}}描述:找到一个可用的连接,锁定它,并返回连接FreeConnection(c)fori=1toN{if(ArrayDBClientConnection[i]==c){Arraylock[i]=0;}}}解释:找到连接,释放锁就知道了。简单的连接池管理并不是很复杂,基本原理如上所述。4.未完成的事情上面的伪代码忽略了一些细节,在连接池的实现中需要考虑:(1)如果所有连接都被占用,是返回失败还是让上游等待(2)需要实现连接可用性检测(3))为了让调用者更加友好,可能还需要包裹一层DAO层,让“连接”对于调用者来说是一个黑盒子(4)通过freeArray,connectionMap可以使连接和返回连接达到O(1)时间复杂度(5)ID序列化可以通过hash实现(6)负载均衡、故障转移、自动服务扩展都可以在这一层实现【本文为原稿】专栏作者《58神剑》,转载请联系原作者】点此阅读作者更多好文