У меня есть скрипт python, который настраивает нескольких рабочих. Они вызывают некоторые методы на моделях SQLAlchemy, которые у меня есть, которые также используются приложением Pylons.Gearman + SQLAlchemy - продолжайте проигрывать поток MySQL
Все работает нормально в течение часа или двух, затем поток MySQL теряется и все запросы терпят неудачу. Я не могу понять, почему поток теряется (я получаю те же результаты на трех разных серверах), когда я определяю такое низкое значение для pool_recycle. Кроме того, почему бы не создать новое соединение?
Любые идеи вещей для расследования?
import gearman
import json
import ConfigParser
import sys
from sqlalchemy import create_engine
class JSONDataEncoder(gearman.DataEncoder):
@classmethod
def encode(cls, encodable_object):
return json.dumps(encodable_object)
@classmethod
def decode(cls, decodable_string):
return json.loads(decodable_string)
# get the ini path and load the gearman server ips:ports
try:
ini_file = sys.argv[1]
lib_path = sys.argv[2]
except Exception:
raise Exception("ini file path or anypy lib path not set")
# get the config
config = ConfigParser.ConfigParser()
config.read(ini_file)
sqlachemy_url = config.get('app:main', 'sqlalchemy.url')
gearman_servers = config.get('app:main', 'gearman.mysql_servers').split(",")
# add anypy include path
sys.path.append(lib_path)
from mypylonsapp.model.user import User, init_model
from mypylonsapp.model.gearman import task_rates
# sqlalchemy setup, recycle connection every hour
engine = create_engine(sqlachemy_url, pool_recycle=3600)
init_model(engine)
# Gearman Worker Setup
gm_worker = gearman.GearmanWorker(gearman_servers)
gm_worker.data_encoder = JSONDataEncoder()
# register the workers
gm_worker.register_task('login', User.login_gearman_worker)
gm_worker.register_task('rates', task_rates)
# work
gm_worker.work()
Другая мысль, вы высвобождая сеансы sqlalchemy между задачами или просто повторное использование их? – David
@ Давид - нет, я не освобождал их, не использовал их повторно. Больше копал и обнаружил, что «Не удается повторно подключиться, пока недействительная транзакция не вернется» в журналах. Поэтому я попытался сделать session.rollback() после каждого задания, но это противоречит функциональности моего одного задания, которое кэширует объект ответа sqlalchemy и повторно использует его для последующих заданий для больших ускорений. Так что теперь я пытаюсь использовать NullPool - engine = create_engine (sqlachemy_url, poolclass = NullPool) и после каждого задания, вызывая session.close(). Будет знать через 24 часа, если это выигрышная комбинация. – Tony
Использование Nullpool может работать (честно говоря, нельзя сказать так или иначе), но если это не так, возможно, будет создан глубокий клон/копия объекта ответа (отделяя ваше кэширование от DB api). – David