我们有一个Python服务器,它使用SQLAlchemy从AWS MySQL MultiAZ RDS实例读取/写入数据。
我们正在经历一种行为,我们希望避免每当我们触发故障转移重启时,已经打开的连接然后发出声明无限期挂起。虽然根据AWS文档可以预期这一点,但我们希望Python MySQL连接器能够应对这种情况。
我们在网上找到的最接近的案例是google groups thread,其中讨论了该问题并提供了有关Postgres RDS的解决方案。
例如,下面的脚本将在启动故障转移重启时无限期挂起(从上面提到的谷歌群组线程中采用)。
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切换到故障转移实例,该连接就会挂起。
我们的问题是 - 是否有人遇到此问题或有可能的方向值得检查?
答案 0 :(得分:3)
如果您再次阅读@univerio评论,AWS将为SAME RDS端点名称重新分配新的IP地址。在进行切换时,您的RDS端点名称和旧IP加密器仍在您的服务器实例DNS缓存中。所以这是一个DNS缓存问题,这就是AWS要求你“清理......”的原因。
除非您重新启动SQLAlchemy以再次读取DNS,否则会话无法知道发生了什么并动态切换。最糟糕的是,问题可能发生在SQLAlchemy使用的连接器中。
恕我直言,在代码内部处理切换是不值得的。我将订阅像lambda这样的AWS服务,它可以在切换事件时起作用,触发应用服务器重新启动连接,这意味着反映新的IP地址。