[API][ADMIN_API]: Improvements to DB driver
* Use native python driver so connection problems don't hang DB * Change connection algorithm: Now uses the first DB as a master and will auto failover as required. It will switch back to the first DB after 60 seconds. Change-Id: I673503b212f6b6e29306c75beeb3fdbb44bdb488
This commit is contained in:
@@ -18,7 +18,6 @@ from sqlalchemy.ext.declarative import declarative_base
|
|||||||
from sqlalchemy.orm import relationship, backref, sessionmaker, Session
|
from sqlalchemy.orm import relationship, backref, sessionmaker, Session
|
||||||
import sqlalchemy.types as types
|
import sqlalchemy.types as types
|
||||||
import time
|
import time
|
||||||
import random
|
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
from pecan import conf
|
from pecan import conf
|
||||||
import logging
|
import logging
|
||||||
@@ -146,12 +145,14 @@ class HealthMonitor(DeclarativeBase):
|
|||||||
|
|
||||||
|
|
||||||
class RoutingSession(Session):
|
class RoutingSession(Session):
|
||||||
""" If an engine is already in use, re-use it. Otherwise we can end up
|
""" Try to use the first engine provided. If this fails use the next in
|
||||||
with deadlocks in Galera, see http://tinyurl.com/9h6qlly
|
sequence and so on. Reset to the first after 60 seconds
|
||||||
switch engines every 60 seconds of idle time """
|
we do this because we can end up with deadlocks in Galera, see
|
||||||
|
http://tinyurl.com/9h6qlly """
|
||||||
|
|
||||||
engines = []
|
engines = {}
|
||||||
last_engine = None
|
engines_count = 0
|
||||||
|
use_engine = 0
|
||||||
last_engine_time = 0
|
last_engine_time = 0
|
||||||
|
|
||||||
def get_bind(self, mapper=None, clause=None):
|
def get_bind(self, mapper=None, clause=None):
|
||||||
@@ -159,14 +160,12 @@ class RoutingSession(Session):
|
|||||||
self._build_engines()
|
self._build_engines()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
RoutingSession.last_engine
|
RoutingSession.use_engine > 0
|
||||||
and time.time() < RoutingSession.last_engine_time + 60
|
and time.time() < RoutingSession.last_engine_time + 60
|
||||||
):
|
):
|
||||||
RoutingSession.last_engine_time = time.time()
|
RoutingSession.last_engine_time = time.time()
|
||||||
return RoutingSession.last_engine
|
RoutingSession.use_engine = 0
|
||||||
engine = random.choice(RoutingSession.engines)
|
engine = RoutingSession.engines[RoutingSession.use_engine]
|
||||||
RoutingSession.last_engine = engine
|
|
||||||
RoutingSession.last_engine_time = time.time()
|
|
||||||
return engine
|
return engine
|
||||||
|
|
||||||
def _build_engines(self):
|
def _build_engines(self):
|
||||||
@@ -175,7 +174,7 @@ class RoutingSession(Session):
|
|||||||
for section in conf.database:
|
for section in conf.database:
|
||||||
db_conf = config._sections[section]
|
db_conf = config._sections[section]
|
||||||
|
|
||||||
conn_string = '''mysql://%s:%s@%s:%d/%s''' % (
|
conn_string = '''mysql+mysqlconnector://%s:%s@%s:%d/%s''' % (
|
||||||
db_conf['username'],
|
db_conf['username'],
|
||||||
db_conf['password'],
|
db_conf['password'],
|
||||||
db_conf['host'],
|
db_conf['host'],
|
||||||
@@ -199,7 +198,8 @@ class RoutingSession(Session):
|
|||||||
conn_string, isolation_level="READ COMMITTED",
|
conn_string, isolation_level="READ COMMITTED",
|
||||||
pool_size=20, pool_recycle=3600
|
pool_size=20, pool_recycle=3600
|
||||||
)
|
)
|
||||||
RoutingSession.engines.append(engine)
|
RoutingSession.engines[RoutingSession.engines_count] = engine
|
||||||
|
RoutingSession.engines_count += 1
|
||||||
|
|
||||||
|
|
||||||
class db_session(object):
|
class db_session(object):
|
||||||
@@ -216,10 +216,14 @@ class db_session(object):
|
|||||||
except:
|
except:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
'Could not connect to DB server: {0}'.format(
|
'Could not connect to DB server: {0}'.format(
|
||||||
RoutingSession.last_engine.url
|
RoutingSession.engines[RoutingSession.use_engine].url
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
RoutingSession.last_engine = None
|
RoutingSession.last_engine_time = time.time()
|
||||||
|
if RoutingSession.use_engine == RoutingSession.engines_count:
|
||||||
|
RoutingSession.use_engine = 0
|
||||||
|
else:
|
||||||
|
RoutingSession.use_engine += 1
|
||||||
self.logger.error('Could not connect to any DB server')
|
self.logger.error('Could not connect to any DB server')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ dogapi
|
|||||||
pecan
|
pecan
|
||||||
sqlalchemy>=0.8.0
|
sqlalchemy>=0.8.0
|
||||||
wsme>=0.5b2
|
wsme>=0.5b2
|
||||||
MySQL-python
|
mysql-connector-python
|
||||||
ipaddress==1.0.4
|
ipaddress==1.0.4
|
||||||
|
|||||||
Reference in New Issue
Block a user