一回tornado QPS最適化を記す


この記事は個人ブログに最初に発表されました:Pylixm'Wiki
プロジェクトのニーズに応じてtornadoを用いてapiシステムを開発し,システム開発が完了した後,8コア16 Gのダミーマシン上で圧力測定qpsを経て200+しかなかった.我々が初期に定めたQPSが2 kより大きいと1桁差があり,長い最適化の道が始まった.最適化の過程で、多くのことを学び、記録を整理して調べる必要がある.
デルのテクノロジー選択:
  • python2.7
  • tornado4.4.3
  • sqlalchemy1.1.5
  • mysql5.6
  • rabbitmq

  • 当初技術が型を選ぶ時tornadoを選んで、その優秀な性能のためで、こんなに低いQPSは自然に悔しいです.果たしてtornadoはどのくらいのQPSに達することができるのだろうか.そこで簡単なhello worldを作成し、上の仮想マシンの中で16のプロセスの下で、ab圧測QPSを使って驚くべき6 Kに達し、平均応答時間はミリ秒級だった.これでapiのQPSを最適化し続ける自信があります.
    初歩的な分析
    QPSを向上させるには、2つの側面から着手することができ、1つは同時数を増加させることであり、2つは平均応答時間を減少させることである.現在の状況から見ると,プロセスの同時数を増やすことが最も直接的な手段であるが,機械資源のボトルネックに達すると,確実に機械を積み重ねて解決する.比較すると,平均応答を低減することがより重要である.我々が開発したapiを初歩的に解析し,平均応答時間は数百ミリ秒レベルであった.ほとんどの時間はシステムとデータベースのインタラクションに費やされ、これにより、平均応答時間を最大限に低減する最適化されたテーマ構想が得られます.
    私たちのAPIが完成した機能は、要求パラメータを受け入れていくつかの列の認証判断(データベースとインタラクティブ)を行い、メッセージをrabbitmqにブロードキャスト形式で消費者に送信し、最後にクライアントに結果を送信することです.この論理によると、応答時間に影響する箇所は、以下のように分析される.
  • mysqlデータベースとのインタラクション
  • rabbitmqを使用してメッセージをブロードキャストする場合の時間消費量
  • 消費時間のトラフィック論理コードフラグメント
  • 構想の最適化
    上記の問題に基づいて、以下のいくつかの面から着手します.
  • tornadoの非同期特性
  • を増加する
  • データベースとのインタラクションを分析し、データベースとのインタラクション時間を減らす
  • rabbitmqを解析する時間の消費量を低減し、情報送信時間
  • を低減する.
  • 最適化ビジネスコードロジック
  • 具体的な実施
    tornadoの非同期特性
    apiを開発する際,tornadoの非同期特性にあまり詳しくないため,使用しなかった.その後、テストが進むにつれて、使用する必要があることに気づき、理解し始めました.理解が深まるにつれて、tornadoはデータベースの非同期特性をよくサポートしていないことがわかり、より多くはネットワークに対する非同期であり、公式サイトにも「ネットワーク非ブロックフレームワーク」と書かれている.公式ドキュメントを調べ、tornadoの非同期実現は、公式ドキュメントの総じて言えば、プログラムを非同期にする方法は3種類あり、ここを参考にする.
  • 第1種は、tornadoのgen.coruntineを使用する.
          ,           ,                     mysql python  ,      。
  • の2つ目は、tornadoのスレッドモジュールを使用します.
            ,                 ,    ,          ,          。
                ,           。
  • の3つ目は、外部キューを使用して、workerプロセスまたはスレッドを個別に処理します.例えば、celeryなどです.
                ,                 ,      。
    

  • 非同期特性の増加に加えて著しく向上した.
    mysqlデータベースの最適化
    データベースは便利で、SQLAlchemyに適しています.ORMを使用すると、裸のsqlによるクエリーの複雑さを減らすと同時に、クエリー・データベースの消費時間が必然的に増加します.私たちもテストをしたことがあります.pymsqlリンクmysqlを使用して、裸のsqlクエリーを直接使用することと、sqlalcemyを使用するオブジェクトクエリーの時間の違いは7、8ミリ秒で、sqlalchemyの裸のsql方式の実行時間とほぼ一致しています.sqlalchemyのorm方式は一定の時間損失があることがわかる.stackoverflowの1つの問題、私の考えも検証して、Why is loading SQLAlchemy objects via the ORM 5-8 x slower than rows via a raw MySQLdb cursorを見ますか?
    データベースについて、次の最適化を行いました.
  • SQLAlchemyクエリをコアヌードsql方式に変更するには、ここを参照してください.
  • データベースを最適化し、必要なインデックスを追加します.
  • 論理のフィルタ条件をできるだけsqlに移動し、sql結果セットのサイズを減らし、クエリーの速度を速める.
  • 単語検索可能なデータセットを1回のクエリーに配置し、データベースへのリンク回数を減らす.

  • rabbitmqを分析する時間の消費量を減らし、情報送信時間を減らす
    rabbitmqでは,pikaをドライバライブラリとして接続し,データを送信するたびにリンクとチャネルを作成し,送信が完了するとすぐにリンクを閉じる.長いリンクを使用できるかどうかを考慮して、リンクを作成して閉じずにchannelだけを閉じます.修正後、エラーが発生しました.具体的なコードは以下の通りです.
    # -*- coding:utf-8 -*-
    import pika
    from settings import settings
    
    
    class Client(object):
        def __init__(self, host, port, username, pwd):
            self.host = host
            self.port = port
            self.username = username
            self.pwd = pwd
            self.init_connection()
    
        def init_connection(self):
            user_pwd = pika.PlainCredentials(self.username, self.pwd)
            self.connection = pika.BlockingConnection(pika.ConnectionParameters(
                host=self.host, port=self.port, credentials=user_pwd))
    
        # ... 

    補足エラー材料分析-todo
    pikaのドキュメントをめくると、非同期の使用方法があり、tornandoフレームワークと結合した例があります.ドキュメントを参照してください.pikaの非同期方式は,tornadoと同じepullベースのイベントループモデルを用いて,tornadoのIOloopとどのように結合するかが問題であり,tornadoのリンクアダプタがあり,そのコードをめくってもどのように使用するかは不明であり,時間があるときに検討を続ける.
    rabbitmqの最適化についてはあきらめたが、最適化の過程で分析に値する文章がいくつかあり、以下のように整理された.
  • rabbitmq-amqp-channel-best-practices
  • rabbitmq-best-practices-for-designing-exchanges-queues-and-bindings
  • tornadoとpikaの結合例
  • ビジネスコードロジックの最適化
    コードロジックの最適化は、次のように便利です.
  • 減少サイクル
  • reviewロジック、冗長ロジック
  • を除去
  • 共通変数を抽出し、1回付与し、クエリー・データベースを削減します.

  • まとめ
    以上の最適化を経て,我々のapiのQPSは1200+に向上し,時間の問題のため,継続的な最適化を一時停止した.今回のQPSの最適化過程を通じて、いくつかの悟りがある.
  • 新しい技術を使用する場合は、必ず公式文書をよく読んで、よく知ってから使用してください.
  • 公認の「技術の真理」を簡単に否定しないで、データを持って話してください.

  • 個人の仕事の総括、伝言の交流を歓迎します!