読者です 読者をやめる 読者になる 読者になる

フツーって言うなぁ!

フツーなサラリーマンのフツーな嘆き.

Web APIプラットフォームの設計をやってみた

お久しぶりです… また4ヶ月放置してしまいました.

現在関わっているプロジェクトで,Tech LeadとしてイチからWeb APIプラットフォームを1本書く,ということをやっています. 初めての経験だったので,いろいろ回り道もありましたが,なんとか軌道に乗りそうなところまでは持っていけたかと思います.

メモとして,やったことと今考えていることを残しておこうと思います.参考になれば幸いです.

業務要求

あまり詳しいことは書きませんが,現在開発中のAPIは,いわゆる決済業務系Web APIとして,主に社内のサービスから使われることを想定しており,かつそこそこの量の秒間リクエストが来ることが想定されます. 最終的には,現在稼働中のAPIを置き換える形で,開発したAPIプラットフォームを使うことを目的としています.

議論の結果,今回の業務要求として,

  • 最低5年程度は現役で使い続けられること
  • 知識の乏しい開発者が短い時間でAPI開発を始められること
  • 運用が比較的スムーズにできること
  • トラフィックをスムーズにさばけること
  • 障害に強く,復旧も早いこと
  • 他サービスからの利用が容易であること(API利用者が容易に開発を進められること)
  • セキュリティ対策ができていること

といったことなどが挙げられました.

ちょうど,エンプラ系のガチガチのシステムと,スタートアップなどの「とりあえず動けばなんでもいい」ようなシステムのちょうど中間,ぐらいのイメージでしょうか.

アーキテクチャの検討

業務要求を受け,これを具体的な設計に落とし込んでいくことを行いました. いろいろ悩んで議論したのですが,最終的にはこんな感じになりました.

  • URL設計においては最近流行りの(?)RESTfulアーキテクチャを採用する
    • 既存APIではRPCを採用していたが,似た挙動をするAPIが乱立する,そのAPIが参照系なのか更新系なのかがわかりにくい,といった問題があった
    • RESTfulを採用した結果,URLが宣言的になり,リクエストを見るだけである程度何をするAPIなのかが明確になるというメリットがあった.反面,URLのパス設計が難しくなったのと,ログを設計する際に,どのパスがどのAPIに対応しているのか何らかの形で保持しておく必要がでてきた
  • URLについては,主流のWeb APIにならってバージョニングを行う
    • 度重なる業務要求の変更に対応するため
  • リクエスト,レスポンスの形式にはXMLJSONを用いる
  • WebフレームワークにはSpring Bootを用いる
    • 実績,ノウハウ面からJVM言語(というかJava)を開発言語として使うことは最初から決まっていた
    • 自分としては,将来Scalaを使用することを見据えてPlay Frameworkを使いたかったが,Playにはまだ枯れていない部分があることと,これまでの実績があったことからSpringを選ぶこととなった
  • 将来のマイクロサービス化を見据え,(パッケージ構成も含め,)サービスはできるだけ疎結合に保つ
    • 現状はまだ開発の1stフェーズであるというところと,マイクロサービスアーキテクチャがどこまで流行るかが未知数ということから,一度ひとつのデプロイ可能jarで作成し,いつでもサービス分割が可能な形を保つこととした
  • キャッシュにはRedisを用い,キャッシュ層はサービスとして分離する
    • インメモリKVSならなんでもよかった
    • Redisを使用したのは,実績があるのと,ドキュメント類が充実していたため
  • DBは変更の対象外とする
  • Docker+Kubernetes+JenkinsのCI/CD環境を用いて,開発者はコードをGitリポジトリにpushするだけでデプロイまでが自動で行われるようにする
    • アプリ側としては,開発環境に依存する設定項目をできるだけ減らし,(DB接続情報などを除き)環境間での差分を最大限減らすことを目標とした
  • ログに関しては,Elasticsearch+Fluentd+Kibanaでの集約,解析を可能にする
  • Junitによる自動ユニットテスト,Cucumberによる自動end2endテスト,SonarQubeによるコードカバレッジ測定など,テストとそれに関連する機能についてはできるだけ自動化を行う

全体的に,「Web系にしてはオーソドックスだなぁ」という構成にはなっているかと思います. 人の出入りが激しく,自分もいついなくなるかわからないので,とにかく「わかりやすさ」を重視したつもりです*1. そういった制約の中でも,Dockerをベースとした運用環境など,「イケてるしこれからもしばらくは使われそうなもの」については,積極的に導入するようにしています.

今後検討したいところ

  • 不正利用の検知,将来のデータ分析に向け,独自のクライアント認証システムを導入する
    • OAuth2など,一般に使われる認証,認可アルゴリズムの適用も考えていたが,今後,社外からAPIをコールされるようになる可能性がかなり低く,多くの場合クライアントにとってこういった作業は手間となるため,見送ることとなった
  • ドキュメントの構成管理
    • 既存のAPIは,ドキュメントをPowerPointなどで作成しており,ドキュメントが散逸する,仕様変更の反映がなされないなど,構成管理に大きな問題があった
    • できれば,ドキュメントはソースコード中のJavadoc等と同期させるようにし,開発者の責任で適宜更新させるようにしたい
    • もっとできれば,ドキュメントとAPIのテストページをまとめてしまいたい*2
  • Dockerコンテナベースでのローカル開発環境の構築
    • 「俺の環境では動く(動かない)」をゼロにしたい
    • まだ検討中
  • 障害対応の方法
    • まだノウハウが足りない
  • 開発フローの構築
    • 開発チケット起票からリリースまでをどう進めるのがよいか
    • ブランチ戦略,ChatOpsなど
  • 他プロジェクトメンバへの教育
    • 特に,Spring自体への理解を深めることと,網羅的なテストケースの作成方法を理解することが必要
    • 最低限,どの開発者も,サービスロジックとコントローラ,そのそれぞれのテストを自力で書けるレベルまでには持っていきたい

こんなところでしょうか. やってみて思うのは,実際に業務で開発されるAPIには大きな制約が課されるということです. 特に,今回のAPIは想定ユーザが多く,いちから基盤を作り直すということだったので,5年後,あるいは10年後を見据えた形での開発が必要でした*3

機会があれば,もう少し実装寄りの部分の解説をしたいと思います.

ではでは.


以下,参考にした本.

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

*1:現状,開発者のレベルもマチマチなので,「保守され続ける」ことを考えると,こういった構成になるのもやむを得ないかと思います

*2:REST APIでは,Swaggerなどのツールで実現できるようだ

*3:チャレンジングではありましたが