_______. _______.___ ___ .______ ____ ____ _______ .______
/ | / | / / | _ / / | ____|| _
| (----` | (----` V / | |_) | / / | |__ | |_) |
> < | / / | __| | /
.----) | .----) | / . | | ----. / | |____ | | ----.
|_______/ |_______/ /__/ __ | _| `._____| __/ |_______|| _| `._____|
SSXRVERは、Linuxプラットフォームで実行されている高性能で高電流ネットワークライブラリです。 C ++ 17で記述され、TCPおよびUDPプロトコルをサポートしています。
私と同じ開発環境を一致させてみてください。データベースモジュールが必要ない場合は、それに応じてcmakelists.txtを変更してください。
cmakeインストール
# debian/ubuntu
sudo apt-get install cmakeライブラリのインストールをブーストします
wget http://sourceforge.net/projects/boost/files/boost/1.72.0/boost_1_72_0.tar.bz2
tar -xvf boost_1_72_0.tar.bz2
cd ./boost_1_72_0
./bootstrap.sh --prefix=/usr/local
sudo ./b2 install --with=allssxrverディレクトリで./build.shを実行すると、build.shを変更してデバッグバージョンまたはリリースバージョン(デフォルトリリースバージョン)を生成することを選択できます。
./build.shコンパイルされたものは、ビルド/ディレクトリを生成し、実行可能ファイルは対応するバージョンディレクトリにあります。たとえば、リリースバージョンを選択すると、実行可能ファイルは/build/release/ssxrverにあります。
conf/ssxrver.json.exampleの形式を模倣して、構成ファイルを作成します(構成ファイルはコメントできず、コメントされておらず、コメントされていないことに注意してください)。以下の各構成ファイルのオプションについて説明します。実際に多くのパラメーターのデフォルト値を設定します。構成されていない場合、それはそれに影響しません。
{
" port " : 4507, # 端口号,不填的话默认4507
" address " : " 127.0.0.1 " , # 绑定的地址
" worker_processes " : 4, # IO 线程数量,不填默认为 4 个
" worker_connections " : -1, # 一个 IO 线程最多支持多少连接, -1 表示最多能创建多少就创建多少,不做限制
" task_processes " : 0, # 任务线程,不填的话默认为 0
" cpu_affinity " : " off " , # cpu 亲和度 ,默认关闭
" http " : { # http 模块
" max_body_size " : 67108864, # 单个 http 包最大支持大小
" root_path " : " /home/randylambert/sunshouxun/ssxrver/html/ " # 文件访问根路径
},
" log " : { # log 模块
" level " : " INFO " , # 输出等级,可填三种等级, DEBUG,INFO,WARN 不填默认为 INFO 等级
" ansync_started " : " off " , # 是否打开异步日志线程,不填默认关闭
" flush_second " : 3, # 异步线程每隔多久持久化一次
" roll_size " : 67108864, # 日志文件滚动大小
" path " : " /home/randylambert/sunshouxun/ssxrver/logs/ " , # 日志文件存放路径
" base_name " : " ssxrver " # 日志文件基础名
},
" mysql " : { # 数据库模块
" mysql_started " : " off " , # 是否打开数据库模块,默认关闭
" address " : " 127.0.0.1 " , # 以下是对应数据库连接信息
" user " : " root " ,
" password " : " 123456 " ,
" database_name " : " ttms " ,
" port " : 0,
" unix_socket " : null,
" client_flag " : 0
},
" blocks_ip " : [ " 122.0.0.2 " , " 198.1.2.33 " ] # 可屏蔽部分恶意 IP
}実行可能ファイルを実行します。
./ssxrver -f /配置文件的路径
# 例如
./build/Release/ssxrver -f ./conf/ssxrver.json| テスト環境 | 価値 |
|---|---|
| オペレーティングシステムのヘアスタイルバージョン | Deepin V20.1コミュニティエディション(1030) |
| カーネルバージョン | 5.4.70-AMD64-DESKTOP(64ビット) |
| コンパイラバージョン | GCC 8.3 |
| ブーストライブラリバージョン | 1.72 |
| プロセッサ | Intel(R)Core(TM)I7-8750H CPU @2.20GHz |
| L1キャッシュサイズ | 32K |
| L2キャッシュサイズ | 256K |
| L3キャッシュサイズ | 9216K |
| ハードディスク速度 | 1.8 TIBメカニカルハードドライブ5400 rpm |
| ハードディスクの読み取り速度と書き込み速度 | 3.03秒で370 MB = 122.27 MB/秒 |
| メモリ | 7.6GB |
| パーティションを交換します | 4.7GB |
| 論理コアカウント | 12コア |
変数を制御するには、テスト前にコンピューターを再起動して、テスト環境に高いCPU負荷とIO負荷が高い他のアプリケーションがないことを確認します。
テストツールはWebbench1.5です。最初のウォームアップデータを削除します。テストコマンドは次のとおりです(100人のクライアントが15秒間継続的にアクセスされています)。
./webbench -c 100 -t 15 http://127.0.0.1:8081/テストオブジェクトはApache/2.4.38、nginx/1.14.2、SSXRverです。
注:WebbenchまたはABを使用するかどうかにかかわらず、この圧力測定ツールで測定されたデータは、簡単な参照としてのみ使用できます。圧力測定は、単にコマンドを実行するのではなく、完全にラウンドおよびマルチアングルを必要とするテストです。圧力測定中であっても、データはネットワークを介して送信されるのではなく、カーネルで動き回るだけです。
| ネットワークライブラリ | 速度(ページ/分) | 成功率を要求します |
|---|---|---|
| SSXRVERは、メモリで生成された応答を返します | 7107414 | 100% |
| SSXRVERは静的ファイルを返します | 5114376 | 100% |
| Apache/2.4.28 | 2884072 | 100% |
| nginx/1.14.2 | 4728748 | 100% |
SSXRVERのテスト結果はかなり良いですが、奇妙なことに、私は初期に開発していたとき、私はその時点で多くの最適化を行わなかったので、データが高くなると思いました。メモリで直接生成された応答を返すと、最大8000000ページ/分近くで測定されました(8000000ページ/分のテスト結果はスクリーンショットで撮影されておらず、7550778を残します)。当時、Nginx/1.14.2の最大5000000ページ/分がありました。ただし、SSXRverであろうとnginx/1.14.2であろうと、このような高い値を見つけることができませんでした。私は何の理由がわからない、それが最終結果にそのような大きなギャップにつながった(それは私のコンピューターが老化しているからですか?
現在、時間があれば、SSXRverのバッファモジュールとログモジュールを個人的に変更します。
まず、バッファモジュールを変更する最も簡単な方法は、それを環状バッファーに変更することであり、それによりバッファーがデータを前方に移動する回数を効果的に削減するか、このバッファーの実装を直接放棄し、高性能バッファーを再実装することです。
第二に、現在のログモジュールは、C ++のストリーム形式で記述されます。 ioStreamでC ++を直接使用するよりもパフォーマンスは間違いなく高くなっていますが、<<シンボリック形式でログをオーバーロードすると、機能コールチェーンによって引き起こされる不便な形式のコントロールとパフォーマンスの問題が発生します。これらの問題は両方とも、PrintFの形式でログを実装することで解決できます。
時間の理由により、SSXRverはメモリ管理モジュールを実装していないため、一般的な高性能メモリ管理モジュールを作成することはほとんど不可能です(JemallocまたはTcmallocに直接移動する方が良いです)。ただし、ネットワークライブラリシナリオを分析することにより、このシナリオでより高いパフォーマンスを備えたメモリ管理モジュールを作成する可能性はまだ少しあります。時間があれば、nginxの実装を見てそれを学びます。
情報を照会したとき、C ++ 17では、STD :: String_Viewを使用してConst Stringを置き換えることができるという結論に達しました。したがって、私はconst string&私のプロジェクトのすべての場所をstd :: string_viewに置き換えようとしました。しかし、最終的にperf -topを使用して変更された負荷を表示したとき、STD :: String_Viewを使用してそれを置き換えると、いくつかの関数が実際に増加したことを予想外に発見しました。なぜこの状況が起こったのか、私は非常に困惑していました。時間の理由により、私はこの問題の特定の原因を当分の間調査しません。基礎となる実装をチェックして、特定の理由を確認する機会があります。
HTTP解析モジュールを実装するとき、最初のバージョンの文字列に直接一致する手書きの状態マシンを使用しました。次に、Ragelによって実装されたState Machineに置き換えました。ただし、最近のテストでは、HTTP解析機能の負荷が非常に誇張されており、10%に達することがわかりました。 Ragelを使用してパフォーマンスの低下を引き起こしたのでしょうか? (ヘッダーを解析すると、システム負荷が非常に高い場合、HTTP/2.0はパフォーマンスが大幅に向上するように思われます)残念ながら、以前に状態マシンを手書きしたとき、対応する解析機能の負荷をテストしませんでした。今、私は一度に2つの間のデータ比較を取得することができず、ベンチマークテストを書く機会があります。
SSXRVERは簡単なUDP送信をサポートしていますが、私は個人的には、混雑制御、交通制御、パケット損失の再送信機能のないUDPフレームワークは、基本的に正常に使用できないと言えると思います。将来的には、QUICおよびKCPプロトコルを学ぶ時間があります。 UDP関連の知識を補完します。より効率的で柔軟なUDPプロトコルは、将来ますます広く使用されると思います!
実際、私は実際に最適なネットワークフレームワークは、ポートマルチプレックスアドレスの多重化と複数のスレッド(マルチプロセス)が同じアドレスとポートにバインドし、カーネルは自動的に受け入れられた負荷分散を実行することだと思います。同時に、Coroutineフレームワーク +フックを介してシステムコールをブロックします。このフレームワークを使用した後、メインスレッドを使用して接続を配布することなく高性能を確保でき、非同期コールバックHellに分類する必要はありません。
さらに、Linuxカーネル5.1の後に追加された非同期IOメカニズムIO_URINGを使用できる場合、サーバーのパフォーマンスが高くなると思います。ただし、現在IO_IRINGについてはあまり知りません。IO_URINGに基づいて非同期IOネットワークライブラリを設計する機能はありません。