Python中连接池的分析和应用

连接池(Connection Pool)是在系统初始化的时候,将网络连接作为对象存储在内存中,当用户需要进行连接时,从连接池中取一个已经建立好的空连接对象,使用完后不关闭连接,将连接放回连接池,而不必频繁地创建和关闭连接,这可以减少连接的开销和提高系统响应速度。
连接池的工作原理:

  1. 连接的创建和初始化:初始阶段,设置最小连接数、最多连接数以及连接的时间等参数,然后会创建一定数量的数据库连接。这些连接通常被称为连接池的“空闲连接”。
  2. 连接的获取:当应用程序需要与数据库交互时,可以在连接池中寻找是否有空闲的连接,如果有则使用,没有就创建一个连接或等待其他客户端释放连接。
  3. 连接的使用:应用程序可以使用数据库连接来执行查询、插入、更新或删除操作。一旦操作完成,连接仍然可以保持开放,以便稍后的重复使用。
  4. 连接的归还:当应用程序不再需要连接时,它将连接归还到连接池,以便其他应用程序可以再次使用它。
  5. 连接的管理:连接池通常会跟踪连接的状态和可用性。如果连接变得无效(例如,由于连接断开或发生错误),连接池会自动替换它。

连接池的优势包括:

  • 减少连接开销:连接池避免了频繁创建和关闭连接,从而减少了连接的开销,提高了数据库操作的性能。
  • 提高响应速度:由于连接池中已经预先创建了一些连接,当有数据库操作请求时,可以直接从连接池中获取一个空闲的连接,避免了等待创建连接的时间,从而提高了响应速度。
  • 资源管理:连接池可以通过配置参数来动态调整连接的数量和状态,从而能够更好地适应不同的业务场景和负载情况,避免过多的数据库连接对数据库服务器造成负担。
  • 连接复用:连接池允许多个应用程序共享连接,以实现连接的复用,这对于高负载系统非常有用。

Python 库中的连接池

redis第三方库 redis的连接池

# python3.7.9 redis 5.0.1 
# redis/connection.py

class ConnectionPool(object):
    def __init__(self, connection_class=Connection, max_connections=None,
                 **connection_kwargs):
        # 连接池最大连接数,默认可以创建2**31个
        max_connections = max_connections or 2 ** 31
        if not isinstance(max_connections, (int, long)) or max_connections < 0:
            raise ValueError('"max_connections" must be a positive integer')

        self.connection_class = connection_class
        self.connection_kwargs = connection_kwargs
        self.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()
    	# 连接池的进程ID
        self.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 += 1
        return 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 Redis
            connection.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 it
            self.release(connection)
            raise

        return 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 own
                pass

            if self.owns_connection(connection):
                # 如果是连接池中的连接,再加到可用的连接池中
                self._available_connections.append(connection)
            else:
                # 如果是普通的连接,则断开连接
                self._created_connections -= 1
                connection.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 conn

	def _get_conn(self, timeout=None):
        """获取一个连接"""
        conn = None
        try:
            conn = self.pool.get(block=self.block, timeout=timeout)

        except AttributeError:  # self.pool is None
            raise 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.
            pass
    
    def close(self):
        """关闭所有连接"""
        if self.pool is None:
            return
        # Disable access to the pool
        old_pool, self.pool = self.pool, None

        try:
            while True:
                conn = old_pool.get(block=False)
                if conn:
                    conn.close()

        except queue.Empty:
            pass  # Done.

  • 14
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python 连接数据库时,使用连接池可以提高数据库连接的效率和性能。连接池是一组预先创建的数据库连接,它们可以被重复使用,而不需要每次都重新建立连接。 在 Python ,有多个库可以用来实现数据库连接池,其比较常用的是 `DBUtils`、`SQLAlchemy` 和 `pymysqlpool`。以下是一个使用 `SQLAlchemy` 实现连接池的示例: 首先,确保已经安装了 `SQLAlchemy` 库: ```python pip install SQLAlchemy ``` 接下来,可以使用以下代码实现连接池: ```python from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker # 创建数据库引擎 engine = create_engine('mysql+pymysql://username:password@localhost:3306/database') # 创建会话工厂 Session = sessionmaker(bind=engine) # 从会话工厂获取会话 session = Session() # 使用会话进行数据库操作 result = session.execute("SELECT * FROM table_name") for row in result: print(row) # 关闭会话 session.close() ``` 在上述代码,首先通过 `create_engine` 方法创建一个数据库引擎对象,指定了数据库的连接信息。然后通过 `sessionmaker` 方法创建一个会话工厂,绑定到数据库引擎上。 接着,可以通过 `Session` 对象获取一个会话,然后使用该会话进行数据库操作。最后,记得关闭会话。 这样就实现了一个简单的 Python 连接池连接数据库的示例。你可以根据自己的实际需求进行相应的配置和使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骇客567

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值