2016-10-19 9 views
1

複数のワーカーとuWSGIで実行されているFlaskアプリケーションからMySQLデータベースに対してクエリを実行しています。私はIDでリソースを照会するときに、返される行のIDが照会されたIDと異なる場合があることに気付きました。複数のuWSGIワーカーからMySQLに照会すると、一致しない行が返される

クエリの分離は、これが不可能であると考えました。しかし、MySQLがクエリを混同しているようです。私はuWSGIを使用していないときにこれを再現することはできませんが、Flaskサーバーを単独でテストするときに、サーバーではなくローカルホストで実行されている可能性があります。

なぜ入力IDと結果IDの間に不一致がありますか?この問題に直面して誰のために

from flask import Flask 
import pymysql.cursor, random 

class Database: 
    def __init__(self, user, password, host, database): 
     self.connection = pymysql.connect(
      user=user, 
      password=password, 
      host=host, 
      database=database, 
      cursorclass=pymysql.cursors.DictCursor 
     ) 

    def query(self, sql, **kwargs): 
     with self.connection.cursor() as cursor: 
      cursor.execute(sql, kwargs) 
      return cursor 

app = Flask(__name__) 
database = Database('user', 'password', 'localhost', 'database') 

@app.route('/resources/<path:id>') 
def resource(id): 
    item = database.query(
     'SELECT resources.id FROM resources WHERE resources.id = %(id)s', 
     id=id 
    ).fetchone() 

    identifier = random.random() 
    print(identifier, 'ID 1:', id) 
    print(identifier, 'ID 2:', item['id']) 

    if int(item['id']) != int(id): 
     print('Error found!!!') 

    return 'Done', 200 

if __name__ == '__main__': 
    app.run() 
[pid: 2824|app: 0|req: 1/1] xxx.xxx.xxx.xxx() {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/10 => generated 4 bytes in 6 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0) 
0.687535338604848 ID 1: 11 
0.687535338604848 ID 2: 11 
[pid: 2821|app: 0|req: 1/2] xxx.xxx.xxx.xxx() {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/11 => generated 4 bytes in 5 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0) 
0.9216930740141296 ID 1: 13 
0.9216930740141296 ID 2: 13 
[pid: 2823|app: 0|req: 1/3] xxx.xxx.xxx.xxx() {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/13 => generated 4 bytes in 6 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0) 
0.9053128320497649 ID 1: 12 
0.9053128320497649 ID 2: 14 
Error found!!! 
0.794023616025622 ID 1: 15 
0.794023616025622 ID 2: 15 
[pid: 2824|app: 0|req: 2/4] xxx.xxx.xxx.xxx() {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/15 => generated 4 bytes in 1 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0) 
[pid: 2822|app: 0|req: 1/5] xxx.xxx.xxx.xxx() {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/12 => generated 4 bytes in 31 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0) 
0.3608322871408709 ID 1: 14 
0.3608322871408709 ID 2: 16 
Error found!!! 
[pid: 2825|app: 0|req: 1/6] xxx.xxx.xxx.xxx() {44 vars in 737 bytes} [Wed Oct 19 18:38:07 2016] GET /resources/14 => generated 4 bytes in 18 msecs (HTTP/1.1 200) 2 headers in 78 bytes (1 switches on core 0) 
0.8346421078513786 ID 1: 16 
0.8346421078513786 ID 2: 17 
Error found!!! 

答えて

0

、私は次の解決策を発見しました。

http://uwsgi-docs.readthedocs.io/en/latest/ThingsToKnow.htmlによると、

uWSGIは可能な限りfork()呼び出しのコピーオンセマンティクスを使用しようとします。デフォルトでは、アプリケーションをロードした後にできるだけ多くのメモリを共有するようにフォークします。この動作が何らかの理由で望ましくない場合は、lazy-appsオプションを使用してください。これにより、各作業者のfork()後にアプリケーションをロードするようにuWSGIに指示します。

uWSGI, Flask, sqlalchemy, and postgres: SSL error: decryption failed or bad record macを見てからは、複数のプロセスが作成されているという問題があることに気付きました。

しかし、uWSGIはデフォルトですべてのプロセスを1つのマスターワーカーからロードするため(毎回Flaskアプリケーションの全体を実行しません)、すべてのワーカーがデータベース接続を共有することになりますやっぱり終わり!)。

解決策は、lazy-appsパラメータを含めることで、各ワーカーが作成されるときにすべてのコードが実行されるようにします。

関連する問題