连接池(Connection Pool)是在系统初始化的时候,将网络连接作为对象存储在内存中,当用户需要进行连接时,从连接池中取一个已经建立好的空连接对象,使用完后不关闭连接,将连接放回连接池,而不必频繁地创建和关闭连接,这可以减少连接的开销和提高系统响应速度。
连接池的工作原理:
- 连接的创建和初始化:初始阶段,设置最小连接数、最多连接数以及连接的时间等参数,然后会创建一定数量的数据库连接。这些连接通常被称为连接池的“空闲连接”。
- 连接的获取:当应用程序需要与数据库交互时,可以在连接池中寻找是否有空闲的连接,如果有则使用,没有就创建一个连接或等待其他客户端释放连接。
- 连接的使用:应用程序可以使用数据库连接来执行查询、插入、更新或删除操作。一旦操作完成,连接仍然可以保持开放,以便稍后的重复使用。
- 连接的归还:当应用程序不再需要连接时,它将连接归还到连接池,以便其他应用程序可以再次使用它。
- 连接的管理:连接池通常会跟踪连接的状态和可用性。如果连接变得无效(例如,由于连接断开或发生错误),连接池会自动替换它。
连接池的优势包括:
- 减少连接开销:连接池避免了频繁创建和关闭连接,从而减少了连接的开销,提高了数据库操作的性能。
- 提高响应速度:由于连接池中已经预先创建了一些连接,当有数据库操作请求时,可以直接从连接池中获取一个空闲的连接,避免了等待创建连接的时间,从而提高了响应速度。
- 资源管理:连接池可以通过配置参数来动态调整连接的数量和状态,从而能够更好地适应不同的业务场景和负载情况,避免过多的数据库连接对数据库服务器造成负担。
- 连接复用:连接池允许多个应用程序共享连接,以实现连接的复用,这对于高负载系统非常有用。
Python 库中的连接池
redis第三方库 redis的连接池
# python3.7.9 redis 5.0.1
# redis/connection.pyclass ConnectionPool(object):def __init__(self, connection_class=Connection, max_connections=None,**connection_kwargs):# 连接池最大连接数,默认可以创建2**31个max_connections = max_connections or 2 ** 31if not isinstance(max_connections, (int, long)) or max_connections < 0:raise ValueError('"max_connections" must be a positive integer')self.connection_class = connection_classself.connection_kwargs = connection_kwargsself.max_connections = max_connections# 保护_checkpid()临界区self._fork_lock = threading.Lock()self.reset()def reset(self):self._lock = threading.Lock()# 连接池大小self._created_connections = 0# 可用得连接self._available_connections = []# 正在使用得连接self._in_use_connections = set()# 连接池的进程IDself.pid = os.getpid()# 创建一个连接,并加到连接池中def make_connection(self):"Create a new connection"if self._created_connections >= self.max_connections:raise ConnectionError("Too many connections")self._created_connections += 1return self.connection_class(**self.connection_kwargs)# 从连接池中获取一个连接def get_connection(self, command_name, *keys, **options):"Get a connection from the pool"self._checkpid()with self._lock:try:# 从可用的连接池中pop一个连接connection = self._available_connections.pop()except IndexError:# 如果无可用的连接,就创建一个connection = self.make_connection()# 然后加入到已用的列表中self._in_use_connections.add(connection)try:# ensure this connection is connected to Redisconnection.connect()try:if connection.can_read():raise ConnectionError('Connection has data')except ConnectionError:connection.disconnect()connection.connect()if connection.can_read():raise ConnectionError('Connection not ready')except BaseException:# release the connection back to the pool so that we don't# leak itself.release(connection)raisereturn connection# 释放一个连接def release(self, connection):"Releases the connection back to the pool"self._checkpid()with self._lock:try:# 从已用的列表中移除self._in_use_connections.remove(connection)except KeyError:# Gracefully fail when a connection is returned to this pool# that the pool doesn't actually ownpassif self.owns_connection(connection):# 如果是连接池中的连接,再加到可用的连接池中self._available_connections.append(connection)else:# 如果是普通的连接,则断开连接self._created_connections -= 1connection.disconnect()return
内置模块 http 中的连接池
# urllib3/connectionpool.py
class HTTPConnectionPool(ConnectionPool, RequestMethods):def __init__(self):# 初始化连接池self.pool = self.QueueCls(maxsize)def _new_conn(self):"""新建一个连接"""conn = self.ConnectionCls(host=self.host,port=self.port,timeout=self.timeout.connect_timeout,strict=self.strict,**self.conn_kw)return conndef _get_conn(self, timeout=None):"""获取一个连接"""conn = Nonetry:conn = self.pool.get(block=self.block, timeout=timeout)except AttributeError: # self.pool is Noneraise ClosedPoolError(self, "Pool is closed.")"""........."""# 获取一个连接,如果不存在创建一个新连接return conn or self._new_conn()def _put_conn(self, conn):"""连接使用完后,放回连接池"""try:self.pool.put(conn, block=False)return # Everything is dandy, done.except AttributeError:# self.pool is None.passdef close(self):"""关闭所有连接"""if self.pool is None:return# Disable access to the poolold_pool, self.pool = self.pool, Nonetry:while True:conn = old_pool.get(block=False)if conn:conn.close()except queue.Empty:pass # Done.