2016-11-10 3 views
0

J'ai construit un micro service web mais je trouve que ça pend beaucoup. Par pendre je veux dire toutes les demandes seront juste expirées, quand il se bloque, je peux voir que le processus fonctionne bien dans le serveur en utilisant seulement environ 15 Mo de mémoire comme d'habitude. Je pense que c'est un problème très intéressant à poster, le code est super simple, s'il vous plaît dites-moi ce que je fais mal.Python micro web service toujours accrocher

app = Bottle() 
# static routing 
@app.route('/') 
def server_static_home(): 
    return static_file('index.html', root='client/') 

@app.route('/<filename>') 
def server_static(filename): 
    return static_file(filename, root='client/') 

@app.get('/api/data') 
def getData(): 
    data = {} 
    arrayToReturn = [] 
    with open("data.txt", "r") as dataFile: 
     entryArray = json.load(dataFile) 
     for entry in entryArray: 
      if not entry['deleted']: 
       arrayToReturn.append(entry) 
     data["array"] = arrayToReturn 

    return data 

@app.put('/api/data') 
def changeEntry(): 

    jsonObj = request.json 
    with open("data.txt", "r+") as dataFile: 
     entryArray = json.load(dataFile) 
     for entry in entryArray: 
      if entry['id'] == jsonObj['id']: 
       entry['val'] = jsonObj['val'] 
     dataFile.seek(0) 
     json.dump(entryArray, dataFile, indent=4) 
     dataFile.truncate() 

    return {"success":True} 

run_simple('0.0.0.0', 80, app, use_reloader=True) 

Fondamentalement mydomain.com est la route à mes index.html et charger JS nécessaires, les fichiers CSS, qui est une partie de ce routage statique est en train de faire. Une fois la page chargée, une requête ajax GET est envoyée à /api/data pour charger les données et lorsque je modifie les données, elle envoie une autre requête ajax Put à /api/data pour modifier les données.

Comment reproduire

Il est très facile de reproduire le coup, j'ai juste besoin de visiter mydomain.com et actualiser la page pour 10-30 fois rapidement, alors il cessera de répondre. Mais je n'ai jamais été capable de reproduire cela localement à quel point je rafraîchis rapidement et data.txt est le même sur ma machine locale.

Mise à jour

s'avère que ce n'est pas un problème de lecture/écriture au fichier, mais un problème en essayant d'écrire broken pipe. Le client qui a envoyé la demande ferme la connexion avant de recevoir toutes les données. Je cherche dans la solution maintenant ...

+0

Si vous utilisez le serveur de développement inclus dans le cadre de la bouteille, je l'ai remarqué que les erreurs de tuyaux cassés sont pratiquement inévitables, étant donné le temps de disponibilité suffisante (il est un serveur dev après tout). Si cela s'applique à vous, je vous recommande de passer à l'exécution de votre application Bottle sur un serveur plus prêt pour la production. J'ai personnellement eu de très bons résultats en utilisant Bottle avec cherrypy. – user3351605

Répondre

3

Il semble que vous essayez d'ouvrir et de lire le même fichier data.txt avec chaque demande PUT. Finalement, vous allez rencontrer des problèmes de simultanéité avec cette architecture car vous aurez plusieurs requêtes essayant d'ouvrir et d'écrire dans le même fichier.

La meilleure solution est de conserver les données dans une base de données (quelque chose comme MySQL, Postgres, Mongodb) au lieu d'écrire dans un fichier plat sur le disque.

Toutefois, si vous devez écrire dans un fichier à plat, vous devez écrire dans un fichier différent par requête où le nom du fichier peut être jsonObj['id'], afin d'éviter le problème de demandes multiples de lecture/écriture au même fichier en même temps.

+0

Parce que le service est vraiment simple, je ne veux utiliser aucune base de données pour cela. Je lis et modifie des entrées dans un fichier texte au format json, donc je ne pense pas que je puisse écrire dans des fichiers séparés, alors lire des données sera très complexe. – Arch1tect

+0

En outre, je pense que le problème est avec les requêtes 'GET' pas" PUT "parce que je n'ai pas besoin de modifier les données pour reproduire le problème, rafraîchir ne fera que déclencher la requête' GET' qui lit les données. – Arch1tect

1

La lecture et l'écriture dans votre fichier data.txt seront victimes des conditions de course mentionnées par Calvin. Les bases de données sont assez faciles en python en particulier avec des bibliothèques comme SqlAlchemy. Mais si vous insistez, vous pouvez également utiliser un dictionnaire global et un verrou en supposant que votre serveur Web ne s'exécute pas en tant que processus multiples. Quelque chose comme

entryArray = {} 
mylock = threading.Lock() 
@app.put('/api/data') 
def changeEntry(): 

    jsonObj = request.json 
    with mylock.lock: 
     for entry in entryArray: 
      if entry['id'] == jsonObj['id']: 
       entry['val'] = jsonObj['val'] 
+0

J'aime ça, je vais essayer maintenant! Merci! – Arch1tect

+0

Je ne pense pas que ce soit les conditions de course maintenant, il semble que ce soit par défaut - http://werkzeug.pocoo.org/docs/0.11/serving/ – Arch1tect