为什么使用连接池
减少socket的三次减少,减少数据库连接开销.....
开源or 自已撸一个
常见的开源
https://github.com/hugoren/sqlalchemy 的自带pool 或queuePool
https://github.com/hugoren/TorMySQL
还有一个很早就不维护,这里就不说了
自已撸一个,好处多多,可以深入各种知识点,出了问题,也比较好hlod住,但也是bug多多,可能是特适合你目前的业务场景用,因为只经过你一个人使用,需要特多业务场景和时间检验。
开源的源码分析
从源码来看,它们都具有相同的点,都是采用pymysql, 再自已实现一个连接池
image.png
tomysql的连接池
https://github.com/hugoren/TorMySQL/blob/master/tormysql/pool.py
采用deque做pool的存储队列
sqlalchemy的连接池
https://github.com/hugoren/sqlalchemy/blob/master/lib/sqlalchemy/pool.py
https://github.com/hugoren/sqlalchemy/blob/master/lib/sqlalchemy/util/queue.py
image.png自已弄一个连接池
目的
做开发的都知道基于进程或线程的方式,cpu上下文是一个很重的开销, py 又是在GIL的方式下运行,想要一个很好的并发,就有人想出了协程异步方式
以下是以 greenlet做任务, tornado的ioloop做异步回调的撸一个线程池
原理
池,说白点就是一个存储的容器,可以是list,也可以queue,py高性能双端队列就是数collections的deque
扩展成其它数据库的连接池
只要继承pool,重写create_raw_conn就行了
完整的例子
https://github.com/hugoren/pool/blob/master/mysql_pool.py
class ConnectionPool(Pool):
def __init__(self, max_size=32, keep_alive=7200, mysql_params={}):
super(ConnectionPool, self).__init__(max_size=max_size, params=mysql_params)
self._keep_alive = keep_alive
def create_raw_conn(self):
conn = Connection(**self._conn_params)
if self._keep_alive:
self._ioloop.add_timeout(time.time() + self._keep_alive, self._ping, conn)
return conn
@green
def _ping(self):
for conn in self._pool:
conn.ping()
self.release(conn)
self._ioloop.add_timeout(time.time() + self._keep_alive, self._ping, conn)
参考
https://github.com/zhu327/greentor/blob/maaster/greentor/mysql.py
网友评论