2017-10-06 13 views
0

J'ai construit une API dans Flask qui effectue une classification sur des messages texte avec Keras. Je suis actuellement en utilisant sshtunnel et MySQLdb pour se connecter à une base de données MySQL pour récupérer des messages à partir d'une base de données distante. L'application entière est enveloppée dans un conteneur Docker.Comment maintenir un tunnel SSH et une connexion MySQL ouverts de manière fiable avec mon API Python Flask?

Je peux établir une connexion à la base de données distante et l'interroger avec succès, mais j'ouvre et ferme un nouveau tunnel ssh chaque fois qu'une requête POST arrive dans l'API, ce qui ralentit les performances. J'ai essayé d'ouvrir un seul tunnel SSH et une seule connexion à la base de données "pour tous les gouverner", mais la connexion devient obsolète s'il n'y a pas d'activité après une heure, et les requêtes API prennent une éternité .

Comment avez-vous fait cela? Cette lenteur est-elle inévitable ou existe-t-il un moyen d'actualiser périodiquement les connexions ssh et base de données?

Voilà comment je me connecte à ma base de données pour chaque requête entrante:

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) 
+1

Si vous avez vraiment le faire, pourquoi ne pas ouvrir le tunnel à l'extérieur de l'application 'ssh -L 3306: localhost: 3306 user @ remote' puis pointez votre application à' localhost: 3306'? Si vous vous souciez vraiment des performances, vous devriez mettre votre base de données et votre application sur le même réseau si possible. – Suever

Répondre

0

D'accord, je compris. J'ai créé un objet DB comme suggéré dans this answer mais avec une légère modification. J'ai gardé la trace du temps que la connexion à la base de données a été créée, puis rétabli la connexion toutes les 30 minutes. Cela signifie qu'une ou deux requêtes prennent un peu plus de temps car je reconstruis la connexion à la base de données, mais le reste s'exécute beaucoup plus vite et la connexion ne sera pas périmée.

J'ai inclus un code ci-dessous. Je réalise que le code n'est pas parfait, mais c'est ce qui a fonctionné pour moi jusqu'ici.

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