【问题标题】:How can I reliably keep a SSH tunnel and MySQL connection open with my Python Flask API?如何使用我的 Python Flask API 可靠地保持 SSH 隧道和 MySQL 连接打开?
【发布时间】:2018-03-18 08:02:59
【问题描述】:

我在 Flask 中构建了一个 API,它使用 Keras 对文本消息进行分类。我目前正在使用sshtunnelMySQLdb 连接到MySQL 数据库以从远程数据库中获取消息。整个应用程序被包装在一个 Docker 容器中。

我能够建立到远程数据库的连接并成功查询它,但是每次 POST 请求进入 API 时我都会打开和关闭一个新的 ssh 隧道,这会降低性能。

我曾尝试打开一个 ssh 隧道和数据库连接“来统治它们”,但如果一个小时左右后没有任何活动,连接就会失效,然后 API 请求需要永远和一天才能完成。

你是怎么做到的?这种缓慢是不可避免的还是有办法定期刷新 ssh 和数据库连接?

这是我为每个传入请求连接到我的数据库的方式:

with SSHTunnelForwarder(
          (host, 22),
          ssh_username=ssh_username,
          ssh_private_key=ssh_private_key,
          remote_bind_address=(localhost, 3306)
     ) as server:
          conn = db.connect(host=localhost,
          port=server.local_bind_port,
          user=user,
          passwd=password,
          db=database)

【问题讨论】:

  • 如果你真的必须这样做,为什么不打开应用程序外部的隧道ssh -L 3306:localhost:3306 user@remote,然后将你的应用程序指向localhost:3306?但是,如果您真的关心性能,则应尽可能将数据库和应用程序放在同一网络上。

标签: python mysql docker ssh flask


【解决方案1】:

好的,我想通了。我按照this answer 中的建议创建了一个数据库对象,但稍作修改。我记录了创建与数据库的连接的时间,然后每 30 分钟重新建立一次连接。这意味着一两个查询需要稍长一些,因为我正在重建与数据库的连接,但其余查询运行得更快,并且连接不会过时。

我在下面包含了一些代码。我意识到代码并不完美,但到目前为止它对我有用。

import MySQLdb as mydb
import time
import pandas as pd
from sshtunnel import SSHTunnelForwarder

class DB:

    def __init__(self):
        self.open_ssh_tunnel()

        self.conn = None

        self.server = None

        self.connect()

        self.last_connected_time = time.time()


    def open_ssh_tunnel(self):
        connection_success = False

        while not connection_success:
            try:
                self.server = SSHTunnelForwarder(
                        (host, 22),
                        ssh_username=ssh_username,
                        ssh_private_key=ssh_private_key,
                        ssh_password=ssh_pwd,
                        remote_bind_address=(localhost, 3306))
                connection_success = True
            except:
                time.sleep(0.5)

        self.server.start()


    def connect(self):
        connection_success = False

        while not connection_success:
            try:
                self.conn = mydb.connect(host=localhost,
                        port=server.local_bind_port,
                        user=user,
                        passwd=password,
                        db=database)
                connection_success = True
            except:
                time.sleep(0.5)


    def query(self, sql):

        result = None
        current_time = time.time()

        if current_time - self.last_connected_time > 1600:
            self.last_connected_time = current_time
            self.server.close()
            self.conn.close()
            self.open_ssh_tunnel()
            self.connect()
        try:
            result = pd.read_sql_query(sql, self.conn).values
            self.conn.commit()
        except:
            self.server.close()
            self.conn.close()
            self.open_ssh_tunnel()
            self.connect()
            result = pd.read_sql_query(sql, self.conn).values

        return result  

【讨论】:

    猜你喜欢
    • 2011-05-20
    • 2015-05-18
    • 2018-01-13
    • 2014-03-21
    • 2016-05-21
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多