1000,000個の異なる要求があります(要求が異なることは、クエリパラメータが異なることを意味します。ペイロードのないGET要求のみです。要求と応答のサイズはKB単位でのみ表示されます。画像や複雑な項目はありません)。 cURLの後に実際のURLが続きます。実際、各行はhttp URLにすることができ、応答をjqにパイプし、条件が満たされるとログファイルに書き込みます。(これが私が達成したいものです)。
1000から始めて5000に達する予定です。要求10,000個/秒。私たちは約持続することを好みます。数時間(例:48〜72時間)、1秒あたり10,000件のリクエストです。
どのような方法が最善ですか?
- テキストファイルにGnu並列処理を使用すると、各テキストファイルに準備されたhttp URLが10000個あります。 (ここではテキストファイルのhttpよりもカールが良いですか?)
- 上記の操作を実行すると、各カール要求は独自のシェルで実行されますか?リクエストを送信し、1 秒あたり 10000 件のリクエストに応答できる単一のシェルに、どのように変更しますか?
xargsとgnuの並列の間に2.5日を過ごしました。しかし、スタックオーバーフローでは、gnuの並列性に対するいくつかの答えがxargsに適用され、その逆の場合も同様です。また、1秒あたり10000個の要求を送信し、基準を満たすすべての応答に対してログファイルに書き込むことができるより良いツール(Pythonツールやabツールなど)がありますか?助けてください。ありがとうございます。
PS:golanがgnuの並列よりもこの作業をよりよく並列化するのに役立ちますか?
答え1
長すぎます。
Gb / sの速度を目指していますが、シェルを起動することは言うまでもなく、プロセスを十分に速く作成することはできません。したがって、シェルスクリプトはあなたのソリューションではありません。libcurl
アクセス許可を使用してくださいlibcurl-multi
。
完全な答え
どのような方法が最善ですか?
- テキストファイルにgnuパラレルを使用すると、各テキストファイルに準備されたhttp URLが10000個あります。 (ここでテキストファイルの場合、カールはhttpよりも優れていますか?)
- 上記の操作を実行すると、各カール要求は独自のシェルで実行されますか?リクエストを送信し、1 秒あたり 10000 件のリクエストに応答できる単一のシェルに、どのように変更しますか?
毎秒「KB単位」(複数)10,000個の要求を実行しようとしているため、これは単純な1Gb / sイーサネットケーブルではありません。建築学的意味を理解したことを確認してください!
まず、伝送媒体(一部のイーサネット?)はシリアルです。最も深い技術レベルでは、複数のパケットを並列に送信することは不可能です。考えられるアプローチは、複数のコアで送信されるパケットキューを入力し、着信応答を並列に処理することです。
curl
その後、1つのリクエストを実行するためのプロセス全体を作成する素晴らしい効率が低い。しかし、全体のシェルを作成するのは(bashを考えていますか?)はるかに悪いです! (プロセスの作成とは、新しいプロセスを作成/パッキングし、実行可能ファイルのイメージに置き換え、実行可能ファイルが依存するすべてのライブラリをロードし、構成/起動スクリプトを解析し、実際の作業を実行することを意味します。実際のことは簡単に(Cのクイックテストループは約3500×以上を実行できないことを示しています。vfork()
その後、PIDを確認してから、exec
8スレッド3.6GHz CPUで毎秒空のプログラムを実行します。非常に重いタスクを実行したいです。 )は、生成できる1秒あたりのプロセスの3倍を生成し、生成されたプロセス内でまだネットワーキングと処理を実行しますが、ほとんどの場合、これは発生しません。
jq
すべての要求に対してプロセスを作成することは完全に災いです。jq
2つのことを行う必要があります。
- パラメータとして渡したクエリを解析し、
- このクエリに基づいてJSONを解析します。
今度はJSONは毎回異なりますが、クエリを知った後(そしてクエリが複雑すぎません)、解析するのは比較的簡単ですが、クエリ自体を解析するのは基本的にコンパイラです。同じコンパイルを複数回実行すると、実際にはクエリは同じままです。
したがって、このような高性能テストでは、シェルを介してparallel
実行するとxargs
機能しません。システムの非効率性により、必要な速度で作業できません。
だからプログラムを書いてみてください。プログラミング言語は適切なマルチスレッドを可能にし(PHP、Delphi、およびVisual Basic 6.0を避けることができます)、比較的高速なJSONパーサーにアクセスできる限り問題ではありません。 Pythonは動作しますが、Pythonは有名ではありません。いいねマルチスレッド。しかし、それでも動作する可能性があります。個人的に私はC ++で簡単に書きたいです。
おすすめ:
epoll
詳細を扱うのを避けたいだけにJSONパーサーについて十分に知っていると思う場合は、libcurl
これを行うための素晴らしいAPIがあります。libcurl たくさんマルチインターフェイス。 CPUコアごとにこれらの操作のいずれかを実行すると、サーバー接続が飽和状態になる可能性があります。
複雑さを犠牲にして全体的にCPU使用率を最大化するアプリケーションを作成するには、要求を送信するのが受信データを処理するよりもはるかに簡単であるため、別々の送信および受信ワーカースレッドが必要です。これに関しては、まず
- マルチスレッドセーフロギングシステムを初期化します(私はspdlogが好きですが、1秒あたり10000個の潜在的なログを見て、人間が読めるテキストファイルよりもバイナリデータを集約して書き込む方が適切かもしれません)。
- パーサーを設定し、
- (アサルト推測:CPUスレッド数/ 3 - 1)転送ワーカースレッド(TX)を生成します。
- 複数(アサルト推測:CPUスレッド・2/3 - 1)受信ワーカースレッド(RX)を生成します。
- データを読み取る準備が整った TCP ソケットのオペレーティング・システム通知トークンを保持するスレッドを生成します。 Linuxでは、このメカニズムは
epoll
Pythonのselect
モジュールを介してselect.epoll
。 - 要求を準備し、TCP接続を確立して、ワーカーのリスニングキューに割り当てるスレッドを作成します。
各TXワーカーでは
- 準備された要求をします。 (これはおそらく
curl_
関数呼び出しだけです。libcurlは実際にはコマンドラインツールではなく良いライブラリです。)
各RXワーカースレッドで
- 取得したばかりのデータを取得して解析し、結果を計算し、適切な場合はロギングシステムにそれを記録するように指示します。
epollスレッドでは
- イベントは、データを取得してRXワーカーに公平に渡すように処理されます(例:ラウンドロビン方式)。
epoll
libcurlを使用する例が必要な場合は、curl
次のようなものがあります。はい(実際にはユースケースに非常に近いです!)
C ++でマルチスレッド、カール、ネットワーキングを処理する方法について議論したい場合は、これStack Overflowの回答が役に立ちます。
答え2
@MarcusMillerは、単一のシステムで1秒あたり10000の要求を実行できると期待してはいけない理由をまとめています。しかし、たぶんあなたはそれを尋ねなかったかもしれません。たぶんこれを行うために使用できる100台のコンピュータがあります。それで可能になりました。
100台のマシンのそれぞれで、以下を実行します。
ulimit -n 1000000
shuf huge-file-with-urls |
parallel -j1000 --pipe --roundrobin 'wget -i - -O - | jq .'
URLを複数回実行する必要がある場合は、moreを追加してくださいshuf huge-file-with-urls
。
forever shuf huge-file-with-urls | [...]
(https://gitlab.com/ole.tange/tangetools/-/tree/master/forever)
GNU Parallelは1,000以上のタスクを並列に実行できますが、コンピュータはそれほど多くのタスクを処理できません。 1000000秒前に開始されましたがsleep
(参照:https://unix.stackexchange.com/a/150686/366317)私の64コアコンピュータを限界までスライドさせました。実際に1,000,000の同時プロセスを開始します。した特定の状況により、サーバーが完全に停止する可能性があります。
プロセスはあるコアから別のコアに移行されるため、どのコアが何を実行しているのかわかりません。プロセスを実行する必要があるコアを制限するために使用できますが、taskset
これは非常に特定のシナリオでのみ意味があります。タスクをアイドルCPUコアにオフロードしたい場合がよくありますが、コアはこれを非常にうまく実行します。
答え3
@MarcusMillerは、単一のシステムで1秒あたり10000の要求を実行できると期待してはいけない理由をまとめています。
修正する必要があると思います。
私は64コアコンピュータにインストールしvarnish
てab
実行しました。
$ seq 64 | parallel -N0 ab -c 100 -n 100000 http://lo:6081/
Server Software: Apache/2.4.41 (really Varnish)
Server Hostname: lo
Server Port: 6081
Document Path: /
Document Length: 10918 bytes
Concurrency Level: 100
Time taken for tests: 132.916 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 1127168742 bytes
HTML transferred: 1091800000 bytes
Requests per second: 752.35 [#/sec] (mean)
Time per request: 132.916 [ms] (mean)
Time per request: 1.329 [ms] (mean, across all concurrent requests)
Transfer rate: 8281.53 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 94 484.9 1 15453
Processing: 0 38 68.9 28 4672
Waiting: 0 37 68.9 27 4672
Total: 1 132 498.4 29 15683
毎秒64 * 720の要求=約45,000の要求と応答を受け取ります。
応答あたり10KB = 4.5Gbit/s
CPUの約50%はですvarnish
。ab
私はあなたを考えるできる16コアシステムでは、1Gbpsで毎秒10,000の要求を行いました。しかし、結果としては何もできず、ab
他の要求を使用するように指示する方法も見つかりませんでした。
使用する場合https://github.com/philipgloyne/apachebench-for-multi-url他の URL を使用することもできます。
parallel --pipepart --block -1 --fifo -a urls ./ab -L {} -c 100 -n 100000