2016-11-10 8 views
0

私はマイクロウェブサービスを構築しましたが、それはたくさんハングすることがわかりました。ハングアップすると、すべてのリクエストがタイムアウトし、ハングアップすると、プロセスが通常どおり約15MBのメモリしか使用していないサーバーで正常に動作していることがわかります。私はポストするのは非常に興味深い問題だと思う、コードは非常に簡単です、私が間違っていることを教えてください。Pythonマイクロウェブサービスは常にハングします

基本的
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) 

mydomain.comことがスタティックルーティング部分が何をしているかですが、私のindex.htmlへの経路であり、必要なJS、CSSファイルをロードします。ページが読み込まれると、Ajax GETリクエストが/api/dataに送信され、データがロードされ、データを変更すると、別のajax Putリクエストが/api/dataに送信され、データが変更されます。これは、ハングを再現するのは非常に簡単です

を再現する方法

は、私はちょうどそれが応答を停止します、mydomain.comを訪問し、急速に10〜30回のページを更新する必要があります。しかし、私はこれをローカルで再現することは決してできませんでした。data.txtは私のローカルマシンで同じです。

更新

それがファイルへの読み取り/書き込みに問題はなく、パイプを破らへの書き込みしようとしているとの問題ではないのですが判明。要求を送信したクライアントは、すべてのデータを受信する前に接続を閉じます。私は現在解決策を探しています...

+0

ような何かが、私は十分な稼働時間(それはすべての後のdevのサーバーで)与えられた、壊れたパイプのエラーが事実上避けられないことに気付きました。それがあなたに当てはまるなら、私はボトルアプリケーションを実稼動環境の良いサーバーの上で稼動させることをお勧めします。私は個人的には、ボトルとサクランピーを使って本当に良い結果を出しました。 – user3351605

答えて

3

PUTリクエストごとに同じファイルを開いて読もうとしているようです。最終的には、同じファイルを開いて書き込もうとする複数の要求があるため、このアーキテクチャーで並行性の問題に遭遇します。

最適な解決策は、ディスク上のフラットファイルに書き込むのではなく、データベース(MySQL、Postgres、Mongodbなど)にデータを保存することです。

フラットファイルに書き込む必要がある場合は、ファイル名がjsonObj['id']になるような要求ごとに別のファイルに書き込む必要があります。このようにして、複数の読み込み/書き込み要求同じファイルに同時に

+0

サービスは本当にシンプルなので、私はそれのためのデータベースを使用したくないです。私はjson形式のテキストファイルで項目を読み込んで変更しているので、別々のファイルに書き込むことはできないと思うので、データを読み込むことは非常に複雑になります。 – Arch1tect

+0

また、問題を再現するためにデータを変更する必要がないので、 'GET'要求は' PUT'ではないと思います。リフレッシュすると、データを読み取る 'GET'要求が発生します。 – Arch1tect

1

あなたのdata.txtファイルを読み書きすることは、カルビンが言及しているように競争条件として犠牲になります。データベースは、特にSqlAlchemyのようなライブラリを使って、Pythonでかなり簡単です。しかし、あなたが主張している場合は、Webサーバが複数のプロセスとして実行されていないと仮定して、グローバル辞書とロックを使用することもできます。あなたがボトルフレームワークに含まれている開発サーバーを使用している場合

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

私はこれが好きです、私は今試してみましょう!ありがとう! – Arch1tect

+0

今は競合状態だとは思わないが、デフォルトではシングルスレッドと思われる - http://werkzeug.pocoo.org/docs/0.11/serving/ – Arch1tect

関連する問題