2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
リンクをコピー
記事をブックマーク
志賀誠氏:じゃあ今度は、モジュラモノリスの実現の方法について説明します。(スライドを示して)Railsでモジュラモノリスを導入するにあたって、パッと思いつくもので、このスライドにあるような問題があるかと思います。
1個は、やはりRailsはRubyなので、なんでも書けちゃうということがあると思います。もうやろうと思ったらいくらでも越境できちゃう境界区域とかがあると思います。
もう1個はActive Recordが強力ですよね。「Arel」もあると思いますが、けっこう自由に書けるので、「どこのテーブルに対して何のクエリを投げる」という制限をかけるのを真面目にやろうとするとなかなか大変だというような思いがあって。このあたりをhacomonoでどんな感じで対応したのかを説明します。
弊社も例に漏れずにpackwerkを使っています。packwerkの詳細については先ほどタイミー社さんから説明があったので、私のほうでは触れる程度にします。
弊社の場合だと、packagesみたいなディレクトリを切っていて、その中にパッケージを何個も作っているような状態です。論理的分割をしています。弊社もタイミー社さんと同じで、パッケージごとにコードオーナーを設定しています。これによって、「『GitHub』でほかのチームが修正した」とか、そういったことを検知できるようにして、安心して運用できるようにしようという取り組みをしています。
(スライドを示して)packwerkはYAMLでルールを設定するんですが、ざっくりとここに書いてあることができるようになっています。「エントリーポイントを外部のパッケージに公開するメソッドがこれですよ」みたいなものを定義できるエントリーポイントの定義と、パッケージが依存できるパッケージ。例えば「共通基盤パッケージ」と言えばいいですかね。メール配信だったりの共通の機能は依存したくなると思うので、そういったルールも書けるようになっています。
あとは「パッケージが一時的に依存するnamespace」と書いてあるんですが、既存のコードベースをパッケージ化する時に、一気にやるのは無理だと思うので、一時的な許容ができる仕組みがあります。「RuboCop」を使ったことがある方だと「.rubocop_todo.yml」みたいなものがあるイメージですね。
あとはパッケージのステータスですね。そのチームのパッケージを公開中か開発中かみたいなものも設定できるようになっていて、bundle execコマンドで静的に精査ができるようなものになっています。
弊社の場合だと、これに加えてもう1個取り組みを入れていて、パッケージの公開エントリーポイントに対しては、protoでどういうリクエストをもらうかと、どういうメソッドが生えているかを定義するようにしています。
protoファイルを各チームでパッケージを用意するチームが作って、それをRubyのコードにコンパイルして生成されたRubyのクラスを用いてやり取りするみたいなイメージです。後でちょっと実例のコードを紹介したいと思います。
protoを使っている背景は2点あります。冒頭の検討で「モジュラモノリスとマイクロサービス、どっちにするか?」みたいな話があったと思うんですが、弊社の場合だと、マイクロサービスはGoで作ろうという意思決定があるんです。
そうなった時に、protoでAPIの部分を定義しておいたら、protoを使ってそのままマイクロサービス化も比較的推進しやすいというのがあって、protoを一枚かませている状況です。
あとはRubyなので、protoの定義に沿った引数を渡してもらうという制約を設けることで、なんでも渡せちゃうという状況を排除している状況ですね。型チェックぐらいの役目としてprotoを入れています。
そのprotoからRubyのコードを生成するところは、gRPCが公式で出している「grpc_tools_ruby_protoc」というものがあります。これをprotoファイルにかませると、そこでRubyのコードが作られるイメージです。
(スライドを示して)ざっくり例が書いてあるんですが、mailer.protoみたいなものがあった時に、protoファイルに対してコンパイラをかませると、2個の成果物ができるんですね。
「mailer_pb」がメッセージみたいな情報を持っていて、RPCがどういうリクエストとレスポンスを扱うかの情報を持ったRubyのクラスみたいな「mailer_service_pb.rb」が生成されます。
実際の例です。プロダクトのコードそのままではないんですが、「こんなイメージで使っていますよ」というコードになります。見えなかったら後でスライドの確認をお願いします。
継承しているクラス、Mailer::MailService::Serviceがprotoコンパイラが生成したほうのクラスで、GetMailが私が実装したクラスですね。GetMailはRPCの名前で揃えている状況です。
外からの使い方としては、1クラス1RPCみたいなかたちでファイルを分割していて、それぞれのクラスがexecuteメソッドを持っている。外からAPIっぽく呼べるようなファイル構成にしています。
肝になるところが、rpc_descというやつが真ん中ぐらいにあると思うんですが、それが親クラスで持っているメソッドで、この中で「そのRPCがどういうリクエスト、レスポンスを扱うか」みたいなものが取れる、便利なメソッドなんですね。
このrpc_descを処理の前と後に挟んで、「GetMailクラスはどういうレスポンスとリクエストを扱うか」みたいなバリュエーションに今は利用しています。
(スライドを示して)これはベタで書いているんですが、共通Concernみたいなやつに切り出して、それぞれのクラスにincludeしているようなかたちです。こういう仕組みを入れています。
gRPCで通信しているわけじゃないんですが、これによって「protoのファイルに沿ったやり取りができていますか?」ぐらいの簡易チェックをするものとして利用しています。コードの例は以上です。
次が、永続化層への制限をどうやっているかですね。コードベースで分かれていたとしても、そのパッケージがアクセスするデータベースが有象無象だったらあまり意味がないので、データベースへのアクセスの制限も簡易的なものですが作っています。実現する手段としては、「Arproxy」という、クックパッドさんが作っているgemを利用しています。
これに関してすごく簡単に話すと、ArproxyはActive Recordとデータベースアダプターの間をフックして好きな処理を挟めるみたいなgemで、今回はそれを利用しています。
使い方の例です。(スライドを示して)「ざっくりとこんなことをしていますよ」という図になります。外部からのパッケージのアクセスが来たタイミングで、RailsのThread.currentにそのパッケージが許可するテーブル一覧を突っ込んでいます。
そのパッケージ内部で実際にクエリを呼ぶところです。「QueryObserver」というArproxyのプラグインを実行すると生SQLが流れてくるんですが、それに対して愚直に正規表現を書いています。ちょっと小声になっちゃいますけど。
100パーセントは弾けませんが、今の弊社のRailsの使い方だと、Railsなのであまりアソシエーションとかを貼っていないんですね。比較的シンプルなクエリが流れてくるので、今はそれでだいたい弾けているような状況です。
これはちょっと想像に難くないんですが、本番で動かすとたぶん重いので、今のところデベロップとステージングとQA環境で動かしています。「検知したい」というのは顧客にぜんぜん関係なく、開発者都合なので、「開発段階で気づけたらいいや」という背景でそのようにしています。
最後です。すごい細かい取り組みもしています。今僕が口頭でバーッと説明したことをエンジニアの人に「じゃあ、やって」と言うと、たぶんなかなか難しいと思うので、Rails generatorで「hacoway」というものを作っています。「hacoway」は「hacomono way」の略なんですけど。これでモジュール名を渡して実行すると、パッケージとprotoファイルを含めて全部自動生成できるみたいな仕組みを用意しています。
以上です。あっ、忘れていました。最後にちょっとリクルートになってしまうんですが、ここまでの話を聞いて、お客さまの中に「WOW!」を届けるような基盤作りに興味を持っている方がいたら、ぜひお声掛けいただけると幸いです。
また、選考に進まなかったとしても、単純に「ここらへんの技術、どうなっているの?」みたいな、気になっているところとかがありましたら、Twitter(現X)で@maco_tasuにメンションしてもらえたら答えるので、質問などをお待ちしています。
以上となります。ご清聴ありがとうございました。
関連タグ:
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05