blog

建築家が書いたバグ、並大抵ではない!

新しい建築家の部署、BAT出身、第三リング在住、BMWで通勤、チャイルドシートあり。 あまり多くを語らないが、一度話すと揺るぎない自信で断固とした態度。その理由は、彼は数億の高い同時実行の経験を持って...

Oct 2, 2020 · 5 min. read
シェア

この部署には新しい建築家がいます。BAT出身で、環状3号線に住み、BMWで通勤し、駐車スペースもあります。

口数は少ないが、一度釘を刺すと揺るぎない自信を持つ男。その理由は、彼は数億の高い同時実行の経験を持っていることです、要求の毎秒は、他の企業が1年を実行して到達することはできません。これは、人々は非常にうらやましい、結局のところ、彼は私がより多くのお金を稼ぐよりも、これに依存しています。

諺にもあるように、あなたが会社で事故に巻き込まれないようにしたい場合は、コードを記述しないでください。仕事より簡単に事故、すべての簡単な誰も聞かなかった、これは現実です。

しかし、時にはそれはまだ結果についてです。新しいR&Dリーダーは技術を理解していませんが、技術的な指標は理解しているので、gitの投稿数を数え、gitのアクティビティがA株のように緑色であれば合格です。

アーキテクトはそれについて考え、インターフェイスの平均応答時間と起動時からのリクエスト数をカウントし、最も高い同時実行性を持つ要求をリードすることにしました。

なぜ同時実行性が高いのでしょうか?AOPコードのパッケージは、各インターフェイスは彼からラウンドする必要があります。

現場の設計者たち示すようなコード。

プロジェクトの中で最も並行性の高いコードとして、シニアアーキテクトの信頼から、コードレビューを行う必要はなく、テストを行う必要もありません。誰もが忙しく、コードあなたは、行にそれを歩くことはありません。

もし問題が見つかれば、それはアーキテクトより優れています。もし問題が見つからなければ、それはあなたがアーキテクトより弱いという証明にはなりません。

ここで、思考を停止させるためのイラストをお見せしましょう。

雷に打たれたふりをして、しばらく線を走らせた後、メモリがオーバーフローしました。

結局、xjjdogは、メモリオーバーフロー問題のトラブルシューティングのサイクルは非常に長く、問題を解決するのに平均40日ほどかかると言いました。MATはメモリ問題の分析に非常に適していますが、スタックをマッシュダウンする必要がある場合に限ります。

アーキテクトはjmapを使うことができ、主な点はパーミッションが大きいことなので、オフラインで分析するために自分でコピーを入手しました。

彼の気持ちは理解できます。結局のところ、彼自身のコードに問題があることは、喜ばしいことではありません。彼は、MonitorKeyとMonitorValueでいっぱいのメモリのヒープの内部を見つけました。

Monitor$MonitorKey@15aeb7ab

アーキテクトと私は仲が良いので、彼は私にこう尋ねました。

いや、アクセス数の多さには目を向けないでください。数百のインターフェースで十分です。

彼はこう言いました。

そのあと、彼は話をやめました。それはパラメーターに違いないので、彼はコードにこれを追加して、?の後を切り捨てるようにコードに追加しました。

key = key.split("\?")[0];

その結果、電線に放出され、いつの間にかまたメモリがオーバーフロー。今回は、最終的に雄牛の注目を集め、みんなの分析の後、コードはMonitorKeyのequalsとhashCodeメソッドを書き換えることを忘れていることがわかりました。

私は赤面せずにはいられませんでした。親友として、彼を馬鹿にさせてはいけなかったのです。でもまた、彼の方が私より給料をもらっていたので、漠然と嬉しかったのです。

これが大きな問題なんですね。ハッシュマップをよく知っていて、赤黒木を具体的に暗記している学生もたくさんいます。でも、違う形で聞かれると混乱してしまうのです。

普通のオブジェクトはHashMapのキーとして使えますか?

答えは当然イエスですが、hashCodeメソッドとequalsメソッドの書き換えには注意が必要です。書き換えを忘れると、メモリ・リークを引き起こす可能性が高いからです。

残念ながら、現実には忘れてしまうケースが多々あります。大物アーキテクトでもやられます。

hashCodeメソッドとequalsメソッドを書き換えた後は、メモリ・オーバーフローが発生することはなくなりました。

待ってください、それだけではありません。結局のところ、私たちはアーキテクトであり、このようなバグはレベルの証明にはならないのです。アーキテクトがバグを書くとしたら、それは並大抵のことではないはずです。

こういうことが頻発すると、研究開発のリーダーも技術の権威にあぐらをかいて冷静ではいられなくなります。そこで、最も同時並行性の高いコードからコード・レビューを行うことにしました。

残念ながら、アーキテクトのVISITコードには問題がありました。大きな問題ではありませんが、問題です。

このコードでは統計を取るときにConcurrentHashMapを使っていますが、大したことはできません。

visitメソッドでは、まずキーを取り出し、次にそれを空と判断し、それから値を詰め込みました。これは明らかにアトミックな操作ではありません。

スレッド1:キーaで値を取得する
スレッド2:キーaで値を得る
スレッド1:aがnullならbを生成する
スレッド2:aがnullならcを生成する
スレッド1=b
スレッド2:節約する=c

この時点でBは失われています。

ビジネス部門はこれに耐えることができましたが、厳格なテクニカル・ブルはこれに耐えられず、変更を提案しました。

アーキテクトは、訪問メソッドにシンクロナイズを追加するだけでは不十分だと言いました。

public synchronized void visit(String url, String desc, long timeCost) 

私はノーと言いました。もっと効率的でエレガントな書き方があります。それは、putIfAbsentメソッドを次のようにコードを変更して使うことです:

MonitorKey key = new MonitorKey(url, desc);
MonitorValue value = monitors.putIfAbsent(key, new MonitorValue());
value = monitors.get(key);
value.count.getAndIncrement();
value.totalTime.getAndAdd(timeCost);
value.avgTime = value.totalTime.get() / value.count.get();

人々はこの2つの方法について議論しました。

テクニカルディレクターは頬を押さえて半日考え、顔を真っ赤にして議論している学生たちを見て言いました。オンライン環境は可能な限り安定させ、最小限の変更を加えるべきです。シンクロナイザーを追加するだけで、簡単に問題を解決できるのだから、それを使えばいいじゃないですか。以下のようなコードの変更が多すぎると、リスクがあります。

このバグは珍しい、みんなに警告させるために、あなたは全体の事故のレビューを行います問題のトラブルシューティングや教訓を共有することで、みんながこのようなミニマリスト・アーキテクチャを目指すようになります。普段の仕事でも、結果を重視するように心がけてください。どんな手段を使ってもいいのです。

これがこの記事の原点です。謙虚に教えを受け入れますが、給料が上がらないことも理解しています。

Read next

Java開発者として、このJavaジェネリックスとコンテナの知識ポイントは、本当によく見ておく必要がある!

以下のメソッドは、一般的に2つのコンテナ間の操作に使用されます。しかし、1つのコンテナ、それ自身と独自の交差、マージ、差分、およびその他の操作を使用することもできますが、一般的には必要ありません。 以下のコードは私が独自に作成したもので、練習問題4のコードとの本質的な違いは、サイズと具体的な表現の意味です。 以下の私のコードは、sizeがコンテナ内の要素数、array.len...を表しています。

Oct 1, 2020 · 11 min read