2011-02-03 2 views
4

У меня есть скрипт 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() 
+1

Другая мысль, вы высвобождая сеансы sqlalchemy между задачами или просто повторное использование их? – David

+0

@ Давид - нет, я не освобождал их, не использовал их повторно. Больше копал и обнаружил, что «Не удается повторно подключиться, пока недействительная транзакция не вернется» в журналах. Поэтому я попытался сделать session.rollback() после каждого задания, но это противоречит функциональности моего одного задания, которое кэширует объект ответа sqlalchemy и повторно использует его для последующих заданий для больших ускорений. Так что теперь я пытаюсь использовать NullPool - engine = create_engine (sqlachemy_url, poolclass = NullPool) и после каждого задания, вызывая session.close(). Будет знать через 24 часа, если это выигрышная комбинация. – Tony

+0

Использование Nullpool может работать (честно говоря, нельзя сказать так или иначе), но если это не так, возможно, будет создан глубокий клон/копия объекта ответа (отделяя ваше кэширование от DB api). – David

ответ

3

Я видел это через борт для Ruby, PHP и Python независимо от используемой библиотеки БД. Я не мог найти, как исправить этот «правильный» способ использования mysql_ping, но есть решение SQLAlchemy, как объяснено здесь лучше. http://groups.google.com/group/sqlalchemy/browse_thread/thread/9412808e695168ea/c31f5c967c135be0

Как указывает кто-то в этом потоке, установите для параметра рециркуляции значение равным True эквивалентно установке его в 1. Лучшее решение может заключаться в том, чтобы найти значение тайм-аута подключения к MySQL и установить порог рециркуляции до 80% от него.

Вы можете получить это значение из живого набора, просматривая эту переменную http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_connect_timeout

Edit: Взял меня немного, чтобы найти документацию authoritivie на использованияКонтактная pool_recycle http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/connections.html?highlight=pool_recycle

+0

Я преследовал этот проспект без успеха, см. Мой комментарий выше. – Tony

Смежные вопросы