オンラインログ書き込みディスク遅延の問題
1169 ワード
オンライン環境では、高同時シーンでローカルディスクの書き込みが遅延している場合があります.たとえば、現在の時刻17:00、ログの最近のレコードは14:00で、複数時間遅延しますが、ログの数は失われません.また、メモリの消費量は10数Gに達し、他の正常な機械より何倍も高いことが分かった.
プロセス
アプリケーションはメモリ内でキューを維持し、ユーザーリクエストが到着し、ユーザーログが生成されると、ユーザーログがキューに格納されます.同時に適用すると、非同期スレッドが起動し、キューがポーリングされ、キューのキューヘッダ要素がキューから出て、IO関数を呼び出してディスクに書き込まれます.
改造前
ぶんせき
この問題はJMeterがローカル環境で高同時性をシミュレートすることによって再現された.原因を詳しく分析すると、問題は非同期スレッドの輪訓の過程でIO関数が絶えず呼び出され、このIO関数はflushを呼び出してバッファデータをリフレッシュし、毎回キューヘッダ要素というログだけがディスクに書き込まれ、これは頻繁なコンテキスト切替を招き、設定されたバッファは無効で、毎回1行のログだけがバッファに書き込まれ、flushがディスクにブラシされることを発見した.ログがディスクに書き込まれる速度よりも、ログがキューに入る速度を大きくします.ログがキューに蓄積され続け、マシンメモリが上昇します.
解決する
非同期スレッドは、ローテーション中にキューのすべての要素を毎回取り出し、IO関数を呼び出してログに書き込む.このライン上の問題は,CPUのコンテキスト切替が非常に時間がかかり,IOバッファの存在も必要であることを示している.
改造後
プロセス
アプリケーションはメモリ内でキューを維持し、ユーザーリクエストが到着し、ユーザーログが生成されると、ユーザーログがキューに格納されます.同時に適用すると、非同期スレッドが起動し、キューがポーリングされ、キューのキューヘッダ要素がキューから出て、IO関数を呼び出してディスクに書き込まれます.
改造前
public class AsyncThread{
public void doWork(){
while(queue.Count>0){
String log = queue.dequeue();
IOUtil.WriteLine(log);
IOUtil.flush();
}
}
}
ぶんせき
この問題はJMeterがローカル環境で高同時性をシミュレートすることによって再現された.原因を詳しく分析すると、問題は非同期スレッドの輪訓の過程でIO関数が絶えず呼び出され、このIO関数はflushを呼び出してバッファデータをリフレッシュし、毎回キューヘッダ要素というログだけがディスクに書き込まれ、これは頻繁なコンテキスト切替を招き、設定されたバッファは無効で、毎回1行のログだけがバッファに書き込まれ、flushがディスクにブラシされることを発見した.ログがディスクに書き込まれる速度よりも、ログがキューに入る速度を大きくします.ログがキューに蓄積され続け、マシンメモリが上昇します.
解決する
非同期スレッドは、ローテーション中にキューのすべての要素を毎回取り出し、IO関数を呼び出してログに書き込む.このライン上の問題は,CPUのコンテキスト切替が非常に時間がかかり,IOバッファの存在も必要であることを示している.
改造後
public class AsyncThread{
public void doWork(){
while(queue.Count>0){
String log = queue.dequeue();
IOUtil.WriteLine(log);
}
IOUtil.flush();
}
}