写真:複雑な探検家、Unsplash
今日、私は私のお気に入りの「プログラミング神話」の1つを思い出しました。これは都市伝説かもしれませんが、デバッグが必要な「ブラックボックス」の自分のバージョンです。
都市伝説は、コンピューターシステムにバグを引き起こしたウクライナからの放射性鉄道車両について語っています。ここで読むことができ ます。
私たちは「ブラックボックス」とそれらが今日何であるかを扱います
ブラックボックスは、コードに直接アクセスできないシステムまたはコンポーネントの外部にいることを前提とした一般的なプログラミング概念です。これは、さまざまな要因によって引き起こされる可能性があります。
- 開発者がコードを開示しないサードパーティソフトウェアを使用します。
- 内部ロジックが抽象化されているAPIを操作しています。
- Gitリポジトリにアクセスするために必要な権限がありません。
- フルアクセスのシステムでさえ、その複雑さのために事実上のブラックボックスになる可能性があります。
- すべての鍵と知識を持っていた従業員は突然辞める/消える/死ぬでしょう。
- レガシーシステムは、サーバー上で「常に機能」し、バージョン管理システムに接続されていない.dllで構成されています。もちろん、コードを見るには、可能であれば逆コンパイルする必要があります。
これらすべての要因は、すぐに修正できない問題があり、エラーが何であるかがわからないという事実に要約されます。したがって、私たちは仕事に取り掛かる必要があります。
私たち自身の問題は、上記のすべての組み合わせでした
上記の要因のリストは、私たちの状況に影響を与えた要因の直接のリストであるため、おそらくすべての状況を網羅しているわけではありません。複数のサーバーに分散された複雑なシステムである開発者を解雇したばかりで、コア.dllが「その仕事をした」のですが、その理由や理由は誰にもわかりませんでした。
サードパーティのサービスと呼ばれ、実際にはログインしていませんでした。バックアップは、この.dllが
あり、コードがないファイルシステムのストレージだけでした 。ご存知のように、これを維持することはできず、彼らはやがてシステムを書き直すことを計画しましたが、エラーは緊急であり、排除する必要がありました。
ほとんどの場合、システムはほぼ完全に作業に対応しており、一貫性があれば問題の部分的な解決策を我慢できたと言えます。ただし、約100分の1のデータセットで誤った結果が得られ、外部からデバッグすることしかできませんでした(今ではこれを笑顔で覚えています)。
ほとんどの企業がそれほど深刻な問題に直面することはなく、それらを解決するために最近の卒業生を任命しないので、これは私が育った混沌とした世界に感謝したその時の1つです。その意味で私は幸運でしたが、プロセス全体を通して私を助けてくれた経験豊富な開発者のサポートがあったので、さらに幸運でした。これが私たちの解決策でした。
エラーを再現します(理想的にはいくつかのテストケースで)
実際のバグが何であるかがわかれば、問題はほぼ解決されますが、バグが不規則に発生した場合、問題に到達するのは非常に困難になる可能性があります。列車の例についてもう一度考えてみてください。パターンを特定できなかった場合、理由を見つけることはほとんど不可能です。これがそのような状況で私たちが探しているものだからです-エラーが発生したときのパターン。
私たちの場合、それは比較的単純でした。エラーのタイプを知っていて、それが繰り返し発生しましたが、ケースの検索スペースを絞り込んでそのロジックを明らかにするのに何度もかかることはめったにありませんでした。
定期的に失敗につながる多くのテストケースを特定したら、デバッグを開始できます。これは、パターンを照合することによって問題の原因の検索を絞り込んだ別のプロセスの例です。システムの1つが毎週木曜日の夜にハングし、ログファイルに何も奇妙なことはありませんでした。
- システムがエラーメッセージを表示していないことはわかっていましたが、ハングしました。
- 問題が木曜日に発生し、他の日は発生しないことが確実になるまで、ケースを比較しました。
- 今回は自動更新がスケジュールされていないことを確認し、同じサーバーで実行されているすべての自動タスクを確認しました。何もありません。
- システムがメタレベルで何をしているかを調べ、共有ディスクタイムアウトに絞り込みました。共有ディスクタイムアウトは、サービスの実行中に完全に異なるサーバーで実行されているディスククリーンアップタスクによって2週間ごとにアクセスされました。どちらも朝の3時に打ち上げられるとは誰も思っていませんでした。
テスト環境を作成します(本番環境であっても)
一連のエラーが発生したら、テストシステムを必要とする真の原因と解決策に取り組み始めることができます。
つまり、2つの定数が必要です。
- 使用するデータは他のシステムによって変更されるべきではありません
- 起こりうる損傷は可能な限り制限する必要があります
私たちの場合、テストサーバーでエラーを再現できませんでした。これは明らかでした。これは、.dllライブラリが本番サーバーとは完全に異なる状態であったためです。この古い状態に戻すことは、同じように重要な他の要素を壊したため、機能しませんでした。
そこで私たちは集まって、「これを台無しにした場合に起こりうる最悪の事態は何ですか?」という質問をし、その後、後続のシステムがそれらを処理しないようにすべての結果をエラー状態に書き換えるデータベーススクリプトを作成しました。
たとえば、サーバーとタスクを切断したり、プロセスから次の論理ステップを削除したりすることは可能でしたが、その可能性は特定のシステムのアーキテクチャによって異なります。
入力データを比較して、作業データセットとの類似点と相違点を見つけます
「ブラックボックス」の場合、コードが正確に何をするのかはわかりませんが、一種の「リバースエンジニアリング」を実行することは可能であり、問題の原因をよく理解することができました。
私たちの場合、入力が依存していた以前のシステムからの適度に適切にフォーマットされたJSONファイルの贅沢がありました。すべての設定が完了した後、エラーの原因となっているファイル間の類似点が見つかるまで、メモ帳++でいくつかのテキストファイルの比較を文字通り開始し、次にそれらと正しく機能するファイルとの違いを見つけました。
ここでは幸運でした。バグが顧客フラグの特定の組み合わせを引き起こしていることがすぐにわかり、このケースは類似しているが異なるフラグで「模倣」される可能性があるため、すぐにそれらをバイパスすることができました。したがって、システムが書き直されることはすでにわかっていたので(実際、選択の余地はありませんでした)、逆コンパイルして修正するのではなく、このバグを回避することにしました。
入力を変更して、推測が期待される結果につながることを確認します(そして損傷を制限します)
明らかに、本番環境でデータベース内のライブデータを変更して、実際のテストなしですべてが機能することを期待するのは悪い考えですが、他に選択肢はありませんでした。
ケースの数が少なく、最初のいくつかのテストを手動で実行したところ、まさに私たちが望んでいたものであることが判明したため、うまく機能しました。
そのため、システムに到達する前にこれらの問題を修正するための別の自動タスクを作成し、3か月のプロジェクトに着手して、バージョン管理とビルドパイプラインを使用して、このプログラムを最初から透過的に書き直しました。
これが冒険です。
結論:システムを歩き回って棒で突くだけでも、システムについて多くのことを学ぶことができます
私はこのデバッグ方法とエラーの発見方法に満足しています。プログラミングとアドレナリンラッシュを組み合わせるのが大好きです。
SQLインジェクションとデータベースリバースエンジニアリングのエラーメッセージに関するビデオをまだご覧になっていない場合は、ぜひご覧になることをお勧め します。このビデオで使用されている手法は、悪意のないデバッグに使用できる手法とほぼ同じです。
広告
すぐに注文して作業してください!最大4000GBの大量のデータを保存するためのサーバーを含む、任意の構成の VDSを1分以内に作成します。エピック:) テレグラムでチャットを
購読して ください。