Contents
  1. 1. forward
  2. 2. socket_pool

科普向

forward

在后端连接数据库的时候,测试时我们一般初始化一个连接对象,把所有的操作都引入这个对象,然后进行数据库的操作。在实际生产时这样有一个问题,如果这个连接对象崩掉了,那么服务器就肯定挂掉。或者同时有大量访问请求的时候,可能访问会变慢。而每次访问去生成一个连接对象,处理完之后就close肯定是不现实的,因为会吃服务器资源。所以我们需要一个连接池,用于处理比较复杂的实际情况。这就是我对连接池的初步理解。

socket_pool

以实际代码为例:

一开始先创建10个连接对象,放入一个连接池中

1
2
3
4
5
6
7
8
9
10
def get_conn():
return pymysql.Connect(host='127.0.0.1',user=MyConfig.USERNAME,passwd=MyConfig.PASSWORD,db='ec_forum',charset='utf8')
'''pymysql socket pool'''
socket_limit = 10
socket_pool = []
socket_update = socket_limit
for i in range(socket_limit):
socket_pool.append(get_conn())

以ID筛选方法为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def id_select(self, ec_id, table='ec_user'):
'''select ec_event just by t_id, and extension'''
conn = socket_pool.pop() # 从连接池pop出一个连接对象
cursor = conn.cursor()
err,res = True,()
query_name = self.get_query_name(table)
sql = "select * from %s where %s=%r;" % (table,query_name,ec_id)
try:
if cursor.execute(sql) == 1:
rs = cursor.fetchone()
if bool(rs):
err,res = False,rs
except BrokenPipeError as e:
conn = get_conn() # 连接对象已失效,重新生成
raise e
except Exception as e:
conn.rollback() # 这里错误类型分开写,以处理不同异常下conn
raise e
finally:
cursor.close()
socket_pool.append(conn) # 总之把连接对象放回连接池
return err,res

从连接池中pop和push连接对象,这样能处理多个用户同时处理的线程问题。当然最好要做个同步锁,我这里没做,因为两个用户如果不小心用到了一个连接对象,也不会造成什么问题。

最后定期更新池中对象的有效性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def update_conn():
global socket_update
socket_update+=1
if socket_update >= socket_limit:
socket_update = 0
print("[update pymysql connection.. Pipe %s]"%socket_update)
socket_pool[socket_update] = get_conn()
global t #Notice: use global variable!
t = threading.Timer(7200.0, update_conn)
t.start()
t = threading.Timer(7200.0, update_conn)
if not MyConfig.TESTING:
t.start()
Contents
  1. 1. forward
  2. 2. socket_pool