2024.12.10
“放置系”なのにサイバー攻撃を監視・検知、「統合ログ管理ツール」とは 最先端のログ管理体制を実現する方法
リンクをコピー
記事をブックマーク
志賀誠氏:じゃあ今度は、モジュラモノリスの実現の方法について説明します。(スライドを示して)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.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.09
10点満点中7点の部下に言うべきこと 部下を育成できない上司の特徴トップ5
2024.12.09
国内の有名ホテルでは、マグロ丼がなんと1杯「24,000円」 「良いものをより安く」を追いすぎた日本にとって値上げが重要な理由
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.10
職場であえて「不機嫌」を出したほうがいいタイプ NOと言えない人のための人間関係をラクにするヒント
2024.12.12
今までとこれからで、エンジニアに求められる「スキル」の違い AI時代のエンジニアの未来と生存戦略のカギとは
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術
PR | 2024.11.22
「闇雲なAI導入」から脱却せよ Zoom・パーソル・THE GUILD幹部が語る、従業員と顧客体験を高めるAI戦略の要諦
2024.12.11
大企業への転職前に感じた、「なんか違うかも」の違和感の正体 「親が喜ぶ」「モテそう」ではない、自分の判断基準を持つカギ