すべてが悪い

画像







まあ、すべてが悪いです。 これを言うのは少しおかしいです。カンファレンス( WebàQuébec )では、驚くべき未来と、新しいテクノロジーのおかげで可能になることについて多くの話がありました。 私たちの生活を楽にする新しいツールとデバイスについて。 私の友人は、私が通常、技術について非常に冷笑的な見方をしていることを知っています。 私は個人的に、他のスピーカーが賞賛した私の言葉に反応するこれらすべてのスマートデバイスを恐れています。







これは主に、プログラミングに時間を費やし、この業界に費やす時間が長いほど、すべてが内部からどのように機能するかをより多く学び、これが私にインスピレーションを与えないためです。 スライドの画像をピックアップしました。 これはピーター・ブリューゲルの「死の勝利」です。 ある程度、それは「スマートホーム」に対する私の態度を明らかにしています。







画像







非常に合理的に見える非常に単純なアプリケーションでさえも、その中に隠れて不愉快な驚きを与える可能性のある多くの問題と潜在的なエラーを示したいと思います。 コードに関しては、本当に安全だと感じるのが難しいことを示したいと思います。 怖い話になります!







画像







私の視点を明らかにするために、この部屋の開発者に馴染みのある基本的なアプリケーションから始めます。 ここに小さなウェブアプリケーションがあります。 右側のユーザーは、デバイスを使用して、何らかの言語で記述されたコードを実行し、アプリケーションロジックを担当する私のフロントエンドに接続します。 情報が保存されているデータベースへの接続があります。 次に-cron、多くのバックグラウンドタスクに必要です。おそらくそれほど複雑ではありません。 次にクラウドが登場しますが、これはおそらくシステムの他の多くのコンポーネントによって使用されます。 たぶん、あなたはS3か何かに画像を保存しています。







したがって、これは合理的なアプリケーションですが、問題はありません。メカニズムに障害が発生すると、システム全体が正しく機能しなくなります。 代わりに、次のことを考慮します。







画像







このようなスキームはより安全です。 これで、フロントが追加され、それらのいずれかを接続または切断できますが、クライアントは引き続きアクセスできます。 2番目のデータベースノードは、問題が発生した場合にフェールオーバーのオプションを提供しますが、これはバックアップソリューションではありません。 「ユーザー」テーブルを削除してこのホットリザーブを失うには、DROP TABLEユーザーとリアルタイムレプリケーションの1人だけで十分です。 そこで、このクラウドで賢明に行動し、バックアップしたとしましょう。







したがって、非同期タスクは少し後で解決できるため、cronを備えた1台のサーバーのみが必要です。 それは良いです。 私たちのアーキテクチャは非常に信頼性が高く便利であり、今はコードのみを心配します。







画像







以下にいくつかの抽象概念を示します。







左上隅には、ツリー、マップ、配列、辞書、セット、リストなどのデータ構造があります。これらを使用すると、メモリのビットよりも大きいものに情報を構造化できます。 これは明らかに良いことです。







さらに識別子があります。 私はそれらを抽象化すると考えています。 これらは、データベースの自動インクリメント識別子、UUID、GUID、および変数、ポインター、URL、またはURIです。 基本的に、完全な説明を必要とせずに、要素、データ、またはオブジェクトを参照できます。 通常、識別子は意味のあるコンテキストにバインドされます。 「あなたはジョンです」と言うことができます。特定のジョンを知っている人は、彼の身長、職業、年齢などの指標に基づいて、彼の友人に基づいてジョンが誰であるかを知ることができます。真の要素全体がサポートするものを決定します。







ここに数字があります。 今日ここにいる人は誰も手を挙げて、彼が各プロジェクトで自分の半加算器を実装していると言うことはできません。 基本的に、以前のようにビットではなく、直接数値を使用します。







左下にネットワークがあります。 これはすべて単なる抽象化です。 接続、順序付けられたデータストリーム、IPアドレスとポート番号(これも識別子です!)、パケットなど。幸いなことに、ケーブルを介して電気信号を送信するだけではありません。







次は時間です。 そして、ここでは彼について説明しません。 哲学者、形而上学者、科学者は、今日この言葉が私たちが意味するものに近づくために、数千年の間主張しました。







そして、私たちは、私たちが描写する方法を知らない他のすべてのためのフォーマット、ラインを持っています。







これらの重要なツールのそれぞれは、科学、数学、テクノロジーによって何十年もの間作成されてきた知識がなくても作業やタスクを実行できるようにするために必要です。 ただし、これらの抽象化の制限の一部を認識せず、抽象化の実際のプロパティと矛盾する方法でそれらを使用すると、不可逆的な結果につながる可能性があります。







画像







浮動小数点の素数から始めましょう。 0.3 +0000000000000004に等しい0.1 + 0.2の量を見たことがあるなら、それが何であるかを知っています。 0.1から0.2までの無限の数がありますが、それらを表すためのバイト数には限りがあります。 一部の数値は完全に分割されていないため、小数部分を操作しないと、コンピューターが意味をなすように数値を置き換え始めたときに精度を失わないことが非常に困難になります。







あなたはお金を扱うときにこれに会ったかもしれません。 トリックは次のとおりです。お金については、失くしたくない限り、浮動小数点数を使用しないでください。 常に必要な最小の分割できないユニットを使用してください。 セント、ミリドル、ピコドル、フェムトドルのいずれでも構いません。浮動小数点数ではありません。







銀行がnode.jsを使用して古いコードベースをブロードキャストしようとしたプロジェクトについて聞いたことがあります。 チームにとって残念なことに、JavaScriptには浮動小数点数しかないと言われたので、チームはプロジェクトを放棄しなければなりませんでした。







ちなみに、JavaScriptなどの浮動小数点を持つ言語では、整数の精度に上限があります。この場合は2 53です。







画像







整数を使うと少し楽になります。 ほとんどの場合、人々は制限をよりよく理解し、それが助けになります。 しかし、これは十分ではありません。すべての整数が同じことを意味するわけではないため、正しい構造と使用タイプが必要です。 コードの一部が帝国単位で機能し、他の部分がメートル法で機能したために失敗した火星気候オービターを考えてください。 おっと







画像は、これらの複雑なユニットの特別な外観を示しています。 SiriまたはWolfram | Alphaに尋ねると、1平方メートルあたりの中国人の王の数は1,628×10 –4になります。 これが何を意味するのかはよくわかりませんが、毎回確実に決定されます。







画像







言語処理が追加されるとさらに興味深い。 理由はわかりませんが、「米国の王は誰ですか?」という質問に対しては、「15億7000万人の中国の王」と答えられます。







原則として、このようなエラーは簡単に防ぐことができます。 注意してください。奇妙な型システムを扱っている場合は、最大限に活用してください。 すべてのタイプの「全体」を追いかけないでください。 整数とは何か、その単位は何かを示します。







画像







私のアプリケーションがその冗長性の優れた仕事をし、また数字を操作する素晴らしい仕事をしているとしましょう。 おそらくユーザーさえもいました。 ここで、シャーディングなどの有用なことに注意を払う必要があります。そうでない場合は、単に外部サービスを使用します。 いずれにせよ、UUIDまたはGUIDを使用する可能性が最も高いのは、それらが予測不可能であり、一意性を「保証」できるためです。







UUIDは、比較するビットのグループです。 それらがすべて同意する場合、識別子は検証に合格しています。 そうでない場合、彼は異なっています。 さまざまなオプションがあります。いくつかはランダム、いくつかは時間または住所に基づいています。







ご覧のとおり、UUIDはスライドの上部にあり、16進数がハイフンで区切られています。 これは少し危険です。







画像







使用する言語またはスタックによっては、UUIDをバイナリBLOBとしてメモリに保存できるライブラリがあります。 または、それらの抽象的な表現が保存されている行。 場合によっては、たとえば、SQLクエリやJSONなどの生のバイナリデータをサポートしないさまざまなシステムで情報を送信する場合に、文字列を中間形式として使用する必要があります。







これがリスクです。 デフォルトでは、ほとんどの言語のほとんどの文字列には、大文字と小文字を区別する比較演算子があります。 したがって、これらの3つのUUIDは、それらの正規のバイナリ表現では同一ですが、等しい文字列として比較されません。 文字列表現はUUIDの真のプロパティの理想的な抽象化ではないため、大文字と小文字の区別はどのような場合でも存在し、システムで考慮する必要があります。







画像







実際、まったく同じ表現を使用しないさまざまなコンポーネントは深刻な頭痛の種になります。 ユーザー、フロントエンド、バックエンド、データベース、およびクラウドサービスは、大文字と小文字を区別しないか、一般的な考え方と一致させる必要があります。







特定の言語には特別なライブラリが必要です。その一部はすべて正常に機能しますが、一方は他方から同じことを期待できません。 データベースは複雑になる可能性があります。









それにもかかわらず、たとえあなたがあなたのためにすべてを正しく行ったとしても、システムが機能するという保証はありません。 すべてを破壊するには、たった1つのサブシステムで十分です。 たとえば、一部のAmazonサービスなどの外部サービスには、常に一貫性のないさまざまなオファーがあります(たとえば、DynamoDBとSimpleDBは大文字と小文字が区別されるため、これらに基づく3番目のAWSサービスはこれらのプロパティを継承する可能性があります)。 これが発生した場合、たとえば、ローカルでPostgreSQLを使用し、UUIDをUUIDとして保存すると、何も良い結果が得られません。 理論的には、ローカルサービスの小文字表現は大文字のサービスには存在しないため、オブジェクトは互いに競合したり、単に消えたりする可能性があります。







残りのように機能しないシステムの部分は、問題を引き起こす可能性があります。 正規のUUID(比較用)を小文字のコピー(元のバージョン)と保存するか、各サービスが素材を保存する方法を調べる必要があります。 あまり楽しくありません。







画像







ただし、文字列の比較は大きな問題につながる可能性があります。 比較された文字列(文字列だけでなく、ほとんどの配列やデータ構造)のもう1つの興味深い特性は、できるだけ早く操作を進めたいという要望です。







パスワードハッシュを比較し、一番上のものが正しいもので、2番目と3番目が他の試行である場合、演算子「==」が差に達すると、ゼロにリセットされ、falseを返します。







計算の期間は情報であるため、これは興味深いです。 セキュリティと暗号化の分野では、できるだけ多くの情報を隠すよう努めています。 攻撃者はさまざまな前提で多くの要求を送信し、処理にかかる時間を確認し、意図した答えがソリューションにどれだけ近いかを理解できます。 これにより、ハッシュの値に関する情報が漏洩する可能性があり、クラッカーは時間に基づいて新しいオプションを提供できます。







実際、これはタイムアタックです。 それらの種類ははるかに多くありますが。







画像







この問題は、比較演算子を厳密な選言に置き換えることで解決できます。 falseに設定してから、XORでビット単位またはバイト比較を行います。 両方の値が同じであるたびに0(false)が返され、値が異なるたびに1(true)が返されます。 ORは元の値につながり、最終的に0でない場合、違いがあることがわかります。







まだ注意する必要があります。 データ量に関する情報の漏洩がないこと、および特定の最適化があなたに害を与えないことを確認する必要があります。 とにかく、優れた暗号化ライブラリはこれを行います。 bcryptまたはscryptを使用すると、パスワードに問題はありませんが、知識があればあるほど良いです。







面白いことですが、暗号化では、設計の面ではすべてをできるだけ遅くする必要がありますが、ブルートフォース攻撃を防ぐため、実装ではできるだけ早く実行する必要があります。







画像







もちろん、一部のデバイスはこれをあまりにも心に留めており、実際にはその遅さはオプションです!







画像







この素晴らしいアプリケーションがあります。 現在、冗長性、整数、浮動小数点、UUID、およびパスワードの素晴らしい仕事をしています。 より多くのユーザーを獲得し、応答時間に対するパフォーマンスが低下し始めています。 ブログの投稿から、費やした時間の10分の1ごとに応答を受け取らないユーザーの重要な割合が失われていることがわかりました。 これは行動への合図です!







一部の操作は長持ちし、他の操作は抑制されます。 原則として、それが何であるかを予測することは本当に難しく、ピーク時間は迷惑です。 チームの誰かが、すべての問題の解決に役立つアイデアを思いつきます。 この考えは何ですか?







画像







行に固執する! 外部サーバーは単純な短いクエリをデータベースに直接送信するだけで、複雑で時間のかかるクエリはすべてキューに送られます。 データは処理されずにキューに入れられ、結果をすばやくユーザーに返すことができます。







画像







それで何? すべてのアクションが返されます。 地獄、それは以前よりもさらに高速です!







ただし、いくつかの問題があります。







画像







キューを追加すると、興味深いことが起こりました。システムの一般的な状態の外部サーバーへの転送が停止しました。 エンドツーエンド操作から結果が早く返されたために、システムのユーザーがすべての要求が処理されたかどうかを確認できた場合、キューの導入によりこの概念が破壊されました。







これで外部サーバーにより、直接接続の存在についてのみ検索できるようになりました。 キューコンシューマ、非同期サーバー、データベースとの対話機能、または非同期キュー自体との関係についてはわかりません。







画像







実際、作業が慎重に行われないと、イベントが繰り返される可能性があります。 これは、ゲームを12.74ドルで購入したRedditユーザーです。 彼は一度それを購入しましたが、銀行口座に–93千ドルを超える金額が形成されるまで、何度も支払い要求を受け取りました。







もちろん、この問題がキューによって正確に引き起こされるという保証はありませんが、それは非常に似ています。 何かがうまくいかず、エンドツーエンドのデータストリームが不可解な方法で中断した場合、結果は通常非常に顕著です。







画像







しかし、それだけではありません。 アプリがゆっくり動作し始めた理由は、アプリが過負荷になったためです。 そのため、システムの実際の負荷から知覚パフォーマンスを完全に分離しました。







バックエンドがどれほど悪くても、フロントエンドのパフォーマンスは変わりません。 このスキームは、一部の大規模な操作で一時的な過負荷が発生した場合に機能しますが、長期的な安定性に関しては正当化されません。 フロントエンドのパフォーマンスを制御し、本質的にシステム全体を監視しました。 2つの部分に分割すると、私の監視は操作性だけでなく、システムの半分だけのパフォーマンスも示します。







画像







その結果、キューがオーバーフローしてクラッシュします。 もちろん、彼女が失敗するだけではありません。







画像







エラーはインターフェイスノードに到達し、最終的に壊滅的な障害が発生します。







私たちはどうですか? 誰かが会議を開いて、これは受け入れられないと言っています。 そして、開発者は何をしますか?







画像







キューを増やします。 しかし、それだけではありません。 事故の間にキュー内のすべてのデータが失われたため、会議のすべての参加者もそれを永続的にすることに同意します。 これは彼女を遅くし、冗長性が大好きなので、別のキューを追加してみませんか?







画像







次回エラーが発生したときに、同じことができます。







画像







これらの行はすべて良い決定です。 しかし、私たちはクールな大企業であるため、次世代のテクノロジーが必要です。 私たちは皆、このアーキテクチャスキームがひどいことを知っています。 だから、私たちは何か特別なものを紹介しています...







画像







そして、これらはマイクロサービスです!







画像







もちろん、問題は同じです。 複雑さは依然としてシステムの一部のみの監視に関連しています。 このようなアーキテクチャの変更はユーザーには見えないはずですが、システムのメンテナンスと操作に非常に重要な影響を及ぼします。







ユーザーとオペレーターを組み合わせたり、そのうちの1つを除外したりすることは、プロジェクトにとって致命的な間違いです。 操作は非常に複雑になっています。







もちろん、それだけではありません! すべてのコンポーネントは相互にやり取りできる必要があります。







画像







JSONのようなものを選択できます。 これは、seriot.chのグラフで、10以上の言語で約50個のJSONライブラリの実装を追跡しています。







それらのほとんどは、独自の方法で情報を処理します。







画像







これはあまり良くありません。







画像







JSON標準は非常に小さいですが、これはおそらく解釈のためのスペースを提供することを意味し、したがって、特別な非標準の動作のために提供します。







最も興味深いのは、複数のマイクロサービスを実行し、それらすべてに等しく慎重に処理されたデータセットを送信すると、一貫性のない動作が発生する可能性があることです。 たとえば、意味の異なる多数の同一キーを持つ無効なJSONを考えてみましょう。 「name」属性が2回表示され、1回目は「Mark」、2回目は「John」である「person」オブジェクトがあるとします。







ほとんどの場合、アナライザーは次の3つの方法のいずれかで動作します。







  1. 必要に応じて、レコードの解析を拒否します。
  2. 名(マーク)を保存します。
  3. ミドルネーム(John)を保存します。


最後の2つの方法の選択は、分析の順序(スタックを使用して、または順番に)に依存します。







3つのサービスがあり、それぞれに独自の動作バージョンがあるとします。 次に、1つのサービスが停止してレコードの処理を拒否し、他の2つのサービスは同じオブジェクトに対して異なる値を表示します。 それらには注意が必要です。







画像







別の問題は時間に関連しています。 異なる時計は異なる速度で動作します。 昨年、カレンダーに関するプレゼンテーションの実験を行いました(いいえ、笑わないでください、カレンダーは実際には非常に興味深いです)。その間、コンピューターのクロック同期をオフにしました。 次に、オーブンと電子レンジで同じことを行い、最大の逸脱がどこにあるかを確認しました。 約3〜4週間後、電子レンジの時間はラップトップで約3分、約2分16秒移動しましたが、オーブンでは変化しませんでした。







時計は、ハードウェア、温​​度、電圧、湿度などによって異なります。長時間正確に保つことはできません。







画像







これは、同期を行わないと、同じイベントのタイムスタンプが分離され、結果が異なる可能性があることを意味します。 これを回避するには、NTPが必要です。 時間を監視し、その偏差がわずかであることを確認できます。 それにもかかわらず、非常に迅速に発生するイベントの場合、NTPでも問題を引き起こすのに十分な方法があります。







そして、これは1つのデバイスでも起こります。 最後の作業で、Hadoopクラスターを何らかの形で壊しました。 ミリ秒単位でクイックトレードを開始し、2つのポイントで時間を記録していることが判明しました。リクエストの受信時とオークションの完了時です。 次に、このデータを使用してイベントを記録し、時間差を計算して、処理全体にかかる時間を調べることができます。







運命の日に、トランザクションが特に迅速に実行されたとき、コンピュータークロックのNTP同期により、数分の1秒の偏差が生じました。最初の時刻の前に2番目のタイムマークを付けるだけで十分です。 完全な幸福のために、これはその月の最後の日の真夜中頃か他のサイクルで起こりました。







イベントは開始する前日に終了しましたが、これはクラスターにとって非常に恥ずかしいことでした。クラスターは明らかにジャンクデータに落ちていました。







ここでのコツは、単調な時間と全身的な時間の間に大きな違いを作り出すことです。







画像







しかし、それだけではありません。 時間は常に問題を引き起こします。 同様のシステムを使用すると、まったく異なる論理的な終了を取得できます。







この場合、クライアントは要求を送信して、それを最初のサービスに転送してから、2番目と3番目のサービスに転送できます。 サービスが商品の購入を確認し、それに関する通知をインターフェースに送信するとします。 3番目のサービスの後、すぐに4番目のサービスの注文を送信します。これにより、たとえば配達などが確認されます。 また、インターフェイスに通知を送信します。







この段階では、ネットワークの遅延により、インターフェースは、購入が確認される前に発送が行われるという情報を受け取る場合があります。







あなたがフロントエンド開発者であれば、そのようなイベントを予測し、適切に対処することができます。 代わりに、同じイベントが何らかの監査システムに分類される場合、間違いを起こしたり、アラームを発生させたり、送信をキャンセルしたりする可能性があります。







次に、因果関係を無条件と見なすのではなく、論理時間を使用して因果関係を追跡する必要がありますが、これはあまりにも広範囲にわたるトピックであるため、ここで説明することはできません。







画像







論理エラーは実際にはかなりおかしいです。 時間内に旅行することができます。







画像







しかし、それだけではありません。 ここにいる人は、おそらくタイムゾーンに精通しているでしょう。 しかし、ここで誰かがベルトについて30分聞いたことがありますか?







(ほとんどの人が手を挙げます。)







はい、そのようなベルトはニューファンドランドにあります。 これは国内にあります。ご存知の通りです。







しかし、15分でタイムゾーンが存在することを誰が知っていますか? 同様のことがニュージーランドにありました。 または、リベリアに44分の記録がありますか? 1927年に中国のタイムゾーンで5分と数秒の偏差があったと聞いた人がいるかもしれません。







しかし、それだけではありません。 タイムゾーンの変更は必ずしも軽微ではありません。 たとえば、サモアはUTC -11とUTC +13の間に存在し、完全に曜日が切り替わります。 秘Theは、それらが日付変更線上にあるということです。 1892年、島は市場の考慮事項に基づいて、カレンダーを米国と調整することを決定しました。 その年、彼らは7月4日を2回持ちました。 7月1日、7月2日、7月3日、7月4日、7月4日、7月5日...







そして再び、2011年に(最近!)彼らは中国とカレンダーに合意し、今回は12月31日ではありませんでした。







また、夏時間もあります。 ブラジルのシステム管理者に精通している場合、ブラジルのすべての地域/州/州が毎年DSTを遵守するかどうか投票するという面白い事実を聞いたことがあるかもしれません。 タイムゾーンファイルを更新する必要があるかどうかを事前に知ることはできません。







画像







次に、うるう秒。 タイムゾーンの問題は、単にUTCで解決されます。 しかし、これは非常に興味深い結果をもたらします。各タイプは依然としてUNIXタイムスタンプを使用しており、UTCと1970年1月1日に始まるUNIX時代との間で自由に変換できるからです。







これは、UTCがうるう秒を考慮しているためです。これはしばしば修正されます。これらは、時計を現実世界と同期させるために、地球の軌道の回転に基づいて追加または削除されます。 1970年以来、私たちは27秒のオフセットのネットワークにいます。 システムのUNIX時代では、これらの秒は考慮されていません。







, , - iPhone, 1 1970 . - . , , .







, ( , ), . — — , 1 1970 , , UTC , -27, . . 32 2106 , , .







画像







. . , , . - , ? ( .)







そんなにない。 , , — :









はい、そうです。 . .







画像







いえいえ . : , . . ( .)







はい , , . Latin-1 ( ISO-8859-1) UTF-8.







画像







, UTF-8 ISO-8859-1 , ASCII.







. , HTTP ( ), , ( UTF-8), ( SQL , ), . , .







, , . , .







画像







— . . :









, , .







. 40+ .

, (code points). , , . 30 , - , .







, , . .







画像







. , , .







画像







, . Spotify, . , , .







画像







. Spotify, .







画像







- ! ! 2012 « : SSL- », .







, . , , ( -), , « » . 幸せな時間。







画像







OpenSSL. .







画像







GnuTLS .







画像







API cURL PHP . , , CURLOPT_SSL_VERIFYHOST true. , PHP ( , C C++) true — , 1. 1 CURLOPT_SSL_VERIFYHOST . — 2.







おっと







画像







, class breaks, .







, . , . , .







class breaks, . .







画像







« », , . . , , IoT .







. , (, , ?), , , -, . .







画像







. , , , , . . ? , ?







, , , . - , . , , - , , . .







作品の安全性を確保するために適切な手段を使用していますか?まだ十分な数の人を殺していないからといって、すべてをそのままにしておくのでしょうか?おそらく私たちはすべて問題を知っているかもしれませんが、何かを私たちがもっと達成するために全体として行動することを強制するまで、私たちは個人的な責任を単に否定しますか?







よくわかりませんが、これはすべてとても怖いです。私は、私が最終的に法律の採択を要求するのに十分な危害を引き起こす者の一人ではないことを望みます。おそらく私たち全員がこれを少し恐れるべきでしょう。すべてが悪いです、そして私たちは責任があります。








All Articles