こんにちは。料理研究家のプロレタリアプログラマー人間です。ここのところ梅雨がね。梅雨が短い…あの…季節ですね。はい。バイウハザードっつってね。えぇ。
毎日のお献立に困っていらっしゃる主婦の方が多いとか多くないとか小耳に挟みまして、大変そうだなと。可哀そうに。可哀そうなので救済を与えたいなと存じました。
ですから、普段お料理をなさらない雑魚でも簡単に作り置きできる、体に嬉しいシステムアーキテクチャを紹介します。
◆何の話をするのか
ITなシステムって言えばコンピューターの上で動くようなイメージであろう。でもコンピューターひとつでは大したもん作ることではできない。複数のコンピューターが協調して動いて複雑っぽいシステムが動いてくれないと幸せになれない。
コンピューターと言っているものには、いま貴様が利用しているパソコンであったりスマホであったりが含まれている。コンピューター同士の通信は素朴に行うこともできるんだけど、愚直に組んだら障害が発生して爆発して給料がゼロとかになって飲みたい牛乳すら買う金がなくなる。だから安全な通信をしたい。
コンピューター内部ですら部品同士で通信が行われていて、それはそれで工夫が凄い。でも専門的で難しい話になってくるから今回はもっと高い層の通信についてパターンを一つ紹介する。
題材はHTTPであれど、普遍的な情報のやり取りの話をする。
◆HTTP通信ってなぁに
それはね。お前を食べるためさ。
パソコン同士は電気とか電波のカタチに変換した信号をやり取りして通信をする。あるパソコンがお前に対して電気を流したり怪電波を照射してきたとしても、どういう意味合いで信号をぶつけてきてんのかって読み取れない。解釈するためには、どういうルールで信号を伝達しあうのかって事前に決めておく必要がある。だからOSI参照モデルという(略
通信の決まりにはいろいろあるんだけど、その中にHTTPってやつがあるんすね。そのHTTPの上にさらにREST(Representational State Transfer)という形式があったりなかったり。
ここまでもこれからも、あいまいにふんわりしたスフレプリン的説明を試みておるので、厳密には違うことが記述されていたりもする。スフレプリン美味しいよね。実家のそばにあるグートロンっていう洋菓子屋の「ふわふわちーず」「ふわふわちょこれーと」っていうスフレ菓子が昔っから激烈に好きで(略
◆POST
お前の求める情報、すなわちエロ画像やエロ動画をパソコンAが持っていた時、そのエロ画像を表示したいパソコンBはAに対して「エロ画像キボンヌ」のリクエストを送ることになる。パソコンBがボーっとしていたら未来永劫にしてエロ画像を得ること叶わず。Aはエスパーではないのでお前の性的嗜好を知らない。
「情報くれ」はHTTPというプロトコル(仕様、ルール、標準)にGETというメソッド(動作種別)で定義されている。
かたや、パソコンAが持っている情報を更新したいだとか、新しい情報を増やしたいときにはPOSTというメソッドを使えばいい。
POSTでは、情報を更新/登録したい側がそれなりの情報を渡し、その情報を受け取った側が保存処理をすることとなる。
◆暗躍するHTTP
パソコンAを今後サーバーと呼ぶ。
元来HTTPはサーバーが持っているエロティック・インフォメーションを閲覧するために定められしプロトコル(エロトコルと言えるかも知れませんね笑笑笑)であるために、インターネットを彷徨っているとHTTPに規定されたエラーコードである500 Internal Server Errorや404 Not Foundを見ることもあるだろう。GETでもPOSTでも500が起こるんだけど、どちらにせよサーバーの側でなんかのエラーが起こってリクエストが失敗したことを示している。
404だのの400系はサーバーに問題がなく、リクエストの内容に問題がある。これ豆な。
HTTPの仕様自体に汎用性があったんで、エロサイトを見るためだけに使うのではなく、裏で動くサーバー同士の情報のやり取りにも使おうよとか言い始めたやつらがいた。みんなもいいじゃ^~んとか言いながらその流れに乗っていった末、調べたことはないけどかなりのシェアでHTTP通信がインターネットを飛び交っている。
例えば自社で建てているサーバー同士の情報のやりとりであれば500とか起こっても割と悠長にハナクソほじりつつクッソ焦燥しながら障害調査するんだけど、これが他の会社で持っているサーバーとの通信とかなってくると調整面で面倒なこともある。なるべく安全な方法で通信をしたい。
◆コラム:安全とは
システムを組むと障害が起こる。障害が起こらないシステムは存在しない(二重否定)。
安全にするためには
- 障害の発生を抑制する
- 障害が発生したときに必要な情報を自動的に通知する
- 障害が発生したときに復帰することができる
- 致命的に壊れないこと
- 手元で復帰できること
- つまり巻き込んでしまう部署を減らすこと
- 自動的に復帰できることがベスト
みたいなことを考えておかねばならない。おちんちん。
◆コラム:おちんちんとは
男性のまたぐらに生えている茎状の陰である。凶器として人に挿し込むと相手を黙らせることができるし逮捕される。慈悲として人に挿し込むと相手を安心させることができるし逮捕される。あまり簡単に挿し込みすぎると病気になるから、石橋をちんちんでペチペチ叩きながら渡るべき。でも慈悲をくださいと請願された日には断る権利を放棄し相手が如何なるメスであろうと男らしく気合込めてちんちんを(略
他人のおちんちんを扱う際には常に自分の優位を誇示し、挿し込まれないように注意する。犬を扱うが如く、まずは「待て」「ハウス」を躾けること。うまく手懐けると可愛いし便利で、バスタオルを干したりバーベキューの串にしたりバウムクーヘン作るときに芯棒にしたりバスケットボールのボールを磨いたり。
は?
◆500エラー
500エラーは、サーバー側で情報の処理に失敗したときに発生する。
データをPOSTで受け取ったとき、処理が予期せぬエラーで失敗したら500のステータスコードを返さねばならない。管理者が失敗に気づいた段階ではすでにリクエストの内容は消失しているので、POSTでデータを受け取る側だけでは調査やリカバリができない。リカバリできないし、データを送った側でも500が返されたことはわかるんで電話がかかってくる。
500、ひいては処理例外が起こる理由はさまざまで、一時的に発生した内部エラーとか、相手が送ってきたデータの解釈に失敗したとか、DBサーバーへの保存に失敗したとか。いろいろ。何はともあれ500返したサーバーを抱えている側が調査せねばならん。
(正常系とか異常系とか準正常系とかエラーハンドリングの話を書きかけて消した。)
◆飛んできた通信をとにかく食って正常ステータスコード返しつつキューで食いなおすやつ
前提の話終わり。どういうアーキを組むかの話をする。
なんでエラーが起こるかって、大まかにいえば受け取った情報を処理するプログラムに不具合があるから。さらに元を正せば、情報を処理してしまっているから。
おまえ「処理しないと処理できないじゃん」
黙ってろバカが何も知らねぇくせに口答えすんじゃねぇ殺すぞ。つまり「受け取る」と「処理する」っていうふたつを両取りヘップバーンしようとしている愚かなテメーの愚かしい思い上がりがゴミなんすわ。
▼受信と処理を分けるという発想
受信とビジネスロジックを分離しましょう。
- 情報を受け取ってそのまま保存する
- 保存されたことを検知してサーバーのプログラムを動かす
- 保存されたデータを処理する
って感じで分ける。分けることによって
- 役に立たないエラー情報を対向システムに送らずに済む
- 500系は送った側が悪いんでそれを返されても困る
- 受けたデータが残るので検証できる
- 障害を解消したのちデータの再配置で食いなおせる
こんな感じになる。
弱点もある。
- 機密情報を含む場合は保存できない
- 機密を保存すると流出して社会からビンタくらう
- サニって(無毒化して)保存してもいいが再配置によるリカバリができなくなる
- 俺は認証情報のことをクソ毒と呼びながら劇物取扱している
- 世間では通用されてない
- 俺は認証情報のことをクソ毒と呼びながら劇物取扱している
- データの工夫で回避可能
- ストレージが必要
- 保存しておく場所が必要
- 受信と処理を分けてそれぞれ作らねばならない
- ありふれた手法なのでそれ用のプログラムはそのへんに落ちている
- クラウドのリソースとして仕組みごと用意されていたりもする
- 詳細はあとで説明する
- 全体の処理時間は伸びる
- 処理結果の情報を返却するPOSTには適用できない
トレードオフっすね。適用できる場面は限られる…ように見えて、設計次第で使いどころはそれなりにある。
▼バリデート
データの内容がルールに沿っているかどうかの検証(バリデート)について、その検証処理をどこでやるのか。受け取ったデータが壊れていても受け入れてしまっていいのか。
好きにすりゃいいんだけど、大抵の場合は受け取った口、つまり受信処理で検証を実施する。検証処理中でエラーが発生することも当然ながらあるし、限度はあるけど単体テストでカバーしてください。
永続化層へのアクセスを必要とする検証があるときは、データそのものやAPI、運用の設計を見直してください。データの主体はデータを送ってくる側であって、受け取ったデータについてはそれが正しいとか正しくないとかの判定を極力しないほうがいいです。せいぜいチェックできるのが記法、必須項目の有る無し、データ型。そこが正しければ全部受けられるようなシステムになるよう設計してください。データに間違いがあった場合は主体に正しいデータを再送信させるか、受け取ったデータ自体を変更することなく整合性を取るような仕組みを設計してください。そのアーキについて今回は説明しないけど。
◆Queue
キュー。単にキューと言えばデータ構造のほうのキューが思い出されるけど、ちょい高い概念としてのキューがある。
処理したいデータをどこかに積んでおいて、積まれていく先から処理したいよねという考え方に付いた名前がキュー。キューにデータを積むことはエンキューと呼ばれる。
(出版購読について書きかけてやめた。 ⇒ 出版-購読型モデル – Wikipedia)
処理したいデータそのものをエンキューすることもあれば、任意のストレージにデータを保存してそのアドレス(保存場所)をエンキューすることもある。大きいデータを取りまわすのは大変だから、エンキューするのはアドレス情報だけにしたいところ。
キューは基本的な構造だから、その仕組みは大抵のパブリッククラウドにマネージドサービスとして用意されている。パブリッククラウドとかマネージドサービスっていうのは(略
細かい動作について書いてみる。個別の動作はキューの実装による。
- キューメッセージを食った処理がこけたときの動き
- 規定回数リトライする?
- 失敗したキューを退避して次のキューを処理する?
- そもそも失敗成功ステータスをキューサーバーに返却できない実装もある。
- 順序を守るかどうか
- 処理失敗したキューメッセージが読み込めるようになるまでキューの読出しを停止する?
- 一度に複数のキューメッセージを食うことを許可する実装もある。
厳密にはキューじゃないような実装もある。使いやすければいい。
- Azure Queue Storage の概要 – Azure Storage | Microsoft Docs
- Amazon SQS(サーバーレスアプリのためのメッセージキューサービス)| AWS
- Cloud Tasks キューを構成する | Cloud Tasks のドキュメント | Google Cloud
- AlibabaMQ for Apache RocketMQ: Distributed Message Queue – Alibaba Cloud
- MQ on Cloud – 使ってみる – 日本 | IBM
◆リカバリ
基本的な流れは
- キューメッセージの取り込みでこけたら
- 自動的に5回くらいリトライして
- 既定のリトライ回数を超えて失敗したら
- 他のキューストレージに元のキューメッセージをコピーして
- 元のキューメッセージを削除する
ほいで
- 失敗キューメッセージを検出するポーリング処理を回し
- 失敗を見つけたらそれに対応する例外スタックトレースをログから引いてきて
- メールを投げたりTeamsやらSlackに通知したりして
- それを俺らが発見してリソースの状態を見たりコードを追ったりする
みたいな。前半の処理はクラウドリソース自体がマネージ(管理)してくれていたりする。
プログラムに不具合がある場合はリトライしてもしょうがないけど、ネットワーク瞬断はリトライで越えることができる。
こうしておけば受けた側でリカバリを完結させることができるので、対向システムのベンダーに迷惑が掛からん。しあわせ。
▼データ設計
落ちたキューメッセージを刺し直すだけで解決すればいいなぁ…
と思いながら実装してください。気を抜かないでください。
裏側のデータ構造が間違っていればリカバリは困難になる。ライフサイクルの異なるデータを単一のレコードに押し込めると取り扱いづらくなってムズムズムラムラしてきてモゾモゾ触っちゃって気持ちよくなってきて触り続けると体液が出てくる。だから俺はJSONもケースに依り正規化しろと言ってるんです。
最終的に、リカバリできるかどうかはデータ構造に係っている。冪等とかってワードでググってみよう。
◆結
いかがでしたでしょうか。旬のキューとかキュウリとかキューカンバーとか🥒を取り入れることで食卓に彩りを添えれば、日々の生活も豊かになることでしょう。生活っていうか保守が豊かになるでしょう。
簡単なお料理からでも食卓に取り入れていき、徐々に難しいアーキテクチャーを扱えるようになりゃいいですよね。せいぜい頑張れよ。
お時間となりました。また次回の放送でお会いしましょう。
じゃっあね^~🤗
匿名
は?じゃねえんだわさ
もっと使用用途について詳しく