2025年12月7日日曜日

モノリス状態遷移からイベント駆動型アーキテクチャへの移行

 キューイングシステムを深堀りたい

背景:

SidekiqワーカーがWebサーバーが入っているEC2に同居している状態。Railsモノリスから脱却し、疏結合化を進めることで、スケーラビリティを向上させたい。

現状分析:

  • Railsモノリスの巨大な泥団子システム。
  • 調べるとapp/model/concerns/hoge_enum.rbにワーカー呼び出しが集結
    • app/worker配下にsidekiqのワーカー処理たちが書かれている
  • gemのstateful_enumを使用してイベント駆動で状態遷移をするようになっている。
  • イベントが発火したafterで色々なことをしていて、もしかしたら死んでるキューがあるかもしれない
問題:
  • EC2にSidekiqが同居しているため、リソース競合が発生して、CPU負荷が高い
    • メモリもジリジリと上昇していてサーバーダウン発生
  • 結合度が高いため変更する時バグが入る可能性
解決方法
  • SidekiqワーカーをWebサーバーから切り分けて独立したサーバーに設置
    • メッセージキューを使用して非同期のイベント駆動型アーキテクチャを実現する
    • CPU負荷特化のインスタンスファミリータイプを選び、最低限のリソース選択でコスト最適化
  • 信頼性向上のためにDBで冪等性を確立する
    • イベント記録をして二重実行を防止することで信頼性向上
移行時の注意
  • 冪等性確保のための状態管理テーブル作成
    • イベントが記録されてトランザクション追跡が可能
    • 処理前、キューイング、処理後のステータスを管理
    • 一意にレコードを特定できるよう、複合ユニーク制約などの設計
  • DLQ(デッドレターキュー)・・・何度も失敗しているキューの処理
    • リトライ処理5回以上のキューをDLQとして管理
    • 手動で再実行
      • 何かしらの失敗であれば良いが、永続的な失敗の場合はダッシュボードなどからの対処が必要だったりする
    • 自動で再実行
      • 永続的な失敗
        • 自動で削除または処理ができるように設計
      • 一時的な失敗
        • ネットワーク障害などの一時的な失敗であれば、再度実行する仕組みでリトライ
  • CI/CDの二重デプロイ
    • Webサーバーとワーカーを分離
  • 出品者商品情報のDB書き込みとメッセージキューの送信の整合性
    • Outboxパターンを適用
      • Outboxテーブルを個別用意。出品者のDB書き込みが発生したとき同一トランザクションでOutboxテーブルに書き込む。
      • メッセージキューはOutboxテーブルを見て送信。
      • 実質、「商品の状態=Outboxの状態」となり、冪等性を担保することでメッセージキューはDBとの整合性が保証される。
移行手順
  • ストラングラーフィグパターンを実行
    • ツルが木を巻きつけるようにして徐々に入れ替わる様からそう言われている
      • 段階的に進めるにあたり、一部の処理からスタートしていき徐々に全体へと進める
    • よくSIerはビッグバンリプレイスをするけど、DevOpsをしている会社はこちらを採用する方式になると思う
  • フィーチャートグルスイッチ
    • 外部コンフィグからON/OFFをして失敗時の復旧を外部から瞬時に戻すことができる
    • ブランチバイアブストラクト
    • カナリアリリース
      • 何パーセントのユーザーにだけ新しいリリースの実行結果が行われるようインフラを構成
技術選定
  • メッセージキュー
    • Amazon SQS・・・フルマネージドで運用の負荷は軽い
    • RabbitMQなどOSS
      • オンプレミスとかではこっちだけどクラウドで選ぶなら理由は自分たちで色々と実装をしたいとか?
    • Kafka、Amazon Kinesisなどのイベントストリーム系
      • シャーディングの仕組みなどでSQSよりも大幅なスループットが可能
      • パーティションで区切り、処理を分けることが可能
      • FIFOの先入先出し削除でデータ処理後に削除するのではなく、データの永続化が可能
  • サーバー
    • Webサーバーは継続してEC2だろうね。常時つけるから
    • 問題はワーカーサーバー
      • こっちはコンテナ化してみて部分的にECSを実現してみるとかいいんじゃないかな?

2025年12月6日土曜日

強みねーな・・・っていうとき

👥「naohiroさんの強みって何ですか?」

👦「(やっべ...全部必要だと思ってたし強みとかないな)設計です!」

👥「では、何をされていましたか?」

👦「実装とかDB設計とかAWS触ったりとか運用とか...」

👥「...(なさそうや)不採用」

👦「ああああなんでいつもこうなんや」

今までフルスタック(全部やれ)をやっていたから全然強みとかないな。。どうしよ。と将来大人になったときが心配になってしまったので強みを探していく実際の流れを書いてみたいと思います。

背景:そもそも前職では技術力というより、リーダーシップの発揮がとても大切な会社でした。そうするとエンジニアとしての強みというのは技術的にはあまり主張できないことになってしまいます。

テーマ:T字型人材を目指す

幅広い強みがあることはいいことですが、何か専門的なスペシャリティを持っていた方がよいというのが最近のトレンドなんじゃないかな?と最近面接していて思いました。(される方です)

なので、T字型人材を目指すために振り返りをしたことや分析してみたことを実際にステップごとに書いていきます。

前提

  • 今まで強みとかないし何でもかんでもやっていた人
  • 選ぶ=他を捨てる

自分の好き・得意を掘り下げる

  • 今まで自分がやっていてこれは得意そうだとか好きだなって思ったこと
  • 気づいたらなんか情報収集してるやつ
  • こういうことをやっていた時結構集中して熱中してたなと思うこと
経験が多いこと
  • 何だかんだ経験が多いことは?
相手を見る
  • 市場に幅広く求められている
  • スペシャリティ
    • ニッチな分野
    • 他の人が見てなさ過ぎて競合がいないため枯渇している部分
  • インパクトの大きさ
    • ビジネス的なインパクト
    • 開発チームへのインパクト
      • 会社へのインパクトが大きい
テーマで区切る
  • 自動化
    • IaC
    • テスト自動化
  • 信頼性
  • セキュリティ
  • クラウド
    • クラウドアーキテクチャ設計・構築
    • マルチクラウド対応
    • AWS特化、GCP特化、Azure特化
  • パフォーマンスチューニング
    • 性能調査
    • オブザーバビリティ
  • データ設計
    • データ構造→非構造、半構造、構造化データ
  • コーディング
    • 言語別
  • アジリティ・デリバリー
  • アーキテクチャ
    • ドメイン駆動設計
    • 分散型アーキテクチャ
  • コスト最適化
  • マネジメント
  • 顧客折衝
  • 品質保証
  • ...etc
何が欲しいか
  • 年収
  • 将来性
    • 安定性
    • ワークライフバランス
  • 自由さ・責任の境界
  • 会社のブランド
    • 会社規模
    • 社名
  • 活躍度・楽しさ
  • 0→1
  • 知名度
  • ...etc

自分は?
  • 年収欲しい
  • 将来性欲しい
  • 責任感からか、より根本を直したいと思う性格からか結構事業リスクとか考えてやっていたかもしれない
    • 開発プロセスとか
    • サーバーの障害リスクとか
    • 技術負債とか
    • やべー誰も分からねぇっていう状況をゼロにしたいと思った
      • ドメインをいの一番で理解しておいて人に教える
      • リファクタリングとかコメントとかめっちゃ書いてた
      • ていう割にはテストはあまり書いてなかった
    • ドキュメンテーションみんなやらなすぎじゃね・・?って思った
      • 逆に言うと割と書きたいかもしれない
  • だから逆にいうと新規機能開発ってあんまりやってなかったかも
    • ていうかやりたい人多すぎてた
    • そういえばSIerの時にやってたのってほぼほぼ拡張か構成管理かリプレイスだった
      • 新規機能の耐性ついてないな
      • カオス好きじゃないな。不確実性はめっちゃ減らしたい
  • 設計とか楽しい
    • DB設計とかは楽しいんじゃないかな
      • 一番負債になるのここだったし
    • DDDとかも結構勉強はしてた
      • でもRailsではやらない方がよいっぽい
    • システム移行とかリアーキテクチャには興味がある
      • でかいことやりたいな
    • AWS
      • めっちゃコストかかってね?って思ってからは最適化したいと思った
      • 運用大変じゃね?って思ってからは自動化したいって思った
      • これ構築とか楽しくね?って思った
      • サーバーの冗長化とかDRとかマルチAZとかレプリケーションとかDBの移行とか楽しくね?って思った
  • 実装
    • 楽しくはなかったかもしれない
    • AIでよくね
    • 実装めんどくせって思っちゃう
  • 勉強してて楽しいのは?
    • スケーラビリティ
      • オートスケーリング
        • 垂直スケール、水平スケール
      • キューイングメッセージ
      • ロードバランサー
        • リクエスト負荷分散
      • データベース
        • レプリケーション
        • パーティショニング
        • シャーディング
    • パフォーマンスチューニング
      • 可観測性
      • クエリ分析
結論:お前、それWebエンジニアか?
総括:共通してるのは分析して解決かなぁ。今の問題点ってなんだろう?っていうところから考えて解決するまでの調査と分析をして解決策を考えて実装。


会社が動かない問題のなぜなぜ分析

テーマ:全然会社が動かない

開発者の意見が通らない

数字に目がいきすぎて全然ユーザー価値考えていない

  • やることが多いと錯覚をしていて、動いていない
  • 負債が溜まっていてなかなか動けない。
  • 改善が進められていない
    • 社内の業務の生産性が悪い
    • 人材が定着していない
    • 改善を進める前に成果を求めてしまう
      • 元いた社員の重圧が大きい
      • 覚えてから成果へ繋げる前に辞めさせちゃう
      • 成果を評価するため、それ以外の成果を出す場を作る下地が作れずに少量の成果しか出せていない
        • 社長からの人材への期待値が高い
        • 一人のスーパースターを求めている
        • 少数の社員で成り立たせたいと思ってリソースを節約している
          • その他がその人を支えるという仕組みを作る
          • イメージが先行して、どういう人材がよいかという固定観念が強い
            • 短期的な投資と成果を求めている
              • 資金がショートするかもしれないという焦り
              • 事業が投資家にとって魅力ではない

総括

資金難と人材の確保ができていない、業務効率が悪い、成果も出せない

というループができてしまっていて、成長していない

これの改善方法

  • 開発部は開発部で仕切り、一人が開発部を責任を持って生産する
  • 痛みを伴う変化というのを間違って解釈しているので修正をしてもらう
    • 人を変えるんじゃなくて、システムを変える
    • こだわりが変化を遠ざけているため、自分の意識だというのを理解してもらう

定期購読プランの設計

 主要テーブルは2つ

  •  ポイント
    • 冪等性を確保する
      • 状態管理テーブル
    • 会社保有のチケット
      • チケットの失効の仕様策定
    • 契約テーブル
  • 実装計画
    • 第一phase
      • 定期購読契約テーブルとバッチ状態管理テーブルを作成
      • 過去のデータで不整合が生じるため削除orデータ変更
    • 第二phase
      • Railsアプリケーション側開発
      • バッチを実装(Lambda、EventBridgeのクラウドネイティブなバッチ)
    • 第三phase
      • チケット失効仕様のためチケットテーブルを追加設計
      • チケット失効バッチを実装
  • 制約
    • 定期購読停止申請は契約更新月の前月末までにしないと次回更新時になる
      • 参考にしたのはNintendo Switchオンライン契約の定期購読の仕組み(ちょっと違うけど、人と会話する時に参考になりやすい)
      • https://support.nintendo.com/jp/nso/automatic-purchase-extension/index.html
    • チケット効力失効が新たに追加
      • 定期購読停止とはまた違い、チケット自体の効力である
        • Amazonポイントとかわかりやすい
  • 定期購読契約テーブル
    • 契約開始
    • 契約終了
    • 次期契約開始
    • 次期契約終了
    • 次回停止申請期限
    • 次回更新停止申請日
    • ステータス
      • 契約中、契約更新停止申請中、契約解除、契約更新処理中
  • バッチ状態管理テーブル
    • バッチの二重実行の防止
    • 冪等性の確保のための設計
      • 複合ユニーク制約の作成バッチ実行日時+ID
      • ステータス管理
        • 失敗、成功、保留、実行中
  • バッチ設計
    • 契約更新バッチ
      • 次回更新停止申請日がNULLでない
        • 次回更新停止申請日が次回更新停止申請期限より前である
        • ステータスを契約更新処理中に
        • ステータスを契約解除に
      • 次回更新停止申請期限を次期契約終了日の一ヶ月前に更新
      • 次期契約開始日を契約開始日にコピー etc
    • チケット補充バッチ
      • 契約している分のチケットを追加する


これからの時代に備える

2026年は失業の年か跳躍の年か アメリカではブルーカラーへの雇用が増加しており、ソフトウェア産業をはじめとしてホワイトカラーの就職が困難になっている。 データで分かるのは、若手、中間管理職層がリストラ対象というもの。アメリカでは『ジョブ型雇用』であるのに対して日本は『メンバーシ...