私たちには、SQLAlchemyを使用してAWS MySQL MultiAZ RDSインスタンスからデータを読み書きするPythonサーバーがあります。AWSでSQLAlchemy接続がハングするフェイルオーバー付きのRDSリブート
フェイルオーバーの再起動をトリガするたびに、開いていた接続がどこにあるかを尋ねて、ステートメントを無期限に送信するような現象が発生しています。これはAWSのドキュメントによれば期待されるものですが、PythonのMySQLコネクタがこのような状況に対処できると期待しています。
私たちがウェブで見つけた最も近いケースは、この問題について話しているPostgres RDSに関する解決策google groups threadです。
たとえば、以下のスクリプトは、フェールオーバーのリブートを開始するときに無期限にハングします(上記のGoogleグループのスレッドを参照)。
from datetime import datetime
from time import time, sleep
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm.scoping import scoped_session
from sqlalchemy.ext.declarative import declarative_base
import logging
current_milli_time = lambda: int(round(time() * 1000))
Base = declarative_base()
logging.basicConfig(format='%(asctime)s %(filename)s %(lineno)s %(process)d %(levelname)s: %(message)s', level="INFO")
class Message(Base):
__tablename__ = 'message'
id = Column(Integer, primary_key=True)
body = Column(String(450), nullable=False)
engine = create_engine('mysql://<username>:<password>@<db_host>/<db_name>',echo=False, pool_recycle=1800,)
session_maker = scoped_session(sessionmaker(bind=engine, autocommit=False, autoflush=False))
session = session_maker()
while True:
try:
ids = ''
start = current_milli_time()
for msg in session.query(Message).order_by(Message.id.desc()).limit(5):
ids += str(msg.id) + ', '
logging.info('({!s}) (took {!s} ms) fetched ids: {!s}'.format(datetime.now().time().isoformat(), current_milli_time() - start, ids))
start = current_milli_time()
m = Message()
m.body = 'some text'
session.add(m)
session.commit()
logging.info('({!s}) (took {!s} ms) inserted new message'.format(datetime.now().time().isoformat(), current_milli_time() - start))
except Exception, e:
logging.exception(e)
session.rollback()
finally:
session_maker.remove()
sleep(0.25)
私たちは、接続タイムアウトで遊んでみましたが、問題がAWSは、フェールオーバーインスタンスに切り替えたら、単純にハングアップし、既にオープンされた接続に関連しているようです。
私たちの質問です - この問題が発生した人がいますか?
クライアントにシームレスになることは間違いありません。 [docs](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_RebootInstance.html)から: "DBインスタンスのフェールオーバーを強制すると、Amazon RDSは自動的に別のインスタンスのスタンバイレプリカに切り替えますDBインスタンスがスタンバイDBインスタンスを指すようにDNSレコードを更新します。その結果、DBインスタンスへの既存の接続をすべてクリーンアップして再確立する必要があります。 – univerio
あなたはまったく正しいです、私はPython DBコネクタがこの状況を検知する方法を持っているのだろうかと疑問に思っています – wilfo
どのように接続タイムアウトを設定していますか?問題が既存の接続である場合、シャットダウン時にリモートホストがFINパケットを送信していないように思えます。これは心配です。通常、ホストを正常にシャットダウンすると、アプリケーションはソケット接続を正常に終了します。途中のルータがTCP RSTパケットをドロップしていない限り、接続はハングアップしません。 – univerio