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

Mercari Engineering Blog

メルカリのエンジニアブログです。技術情報を日々発信していきます。

Widebullet〜API Gateway with JSON-RPC〜

SRE(Site Reliability Engineering)チームの@cubicdaiyaです。今年のはじめから開発しているWidebulletというシンプルなAPI Gatewayを紹介します。

Widebullet〜API Gateway with JSON-RPC〜

WidebulletはJSON-RPCをベースにしたシンプルなAPI Gatewayです。Goで書かれています。

github.com

JSON-RPCはJSONによるRPC(Remote Procedure Call)プロトコルで、リクエストやレスポンスのボディに含まれるJSONを利用してクライアント/サーバ間の通信を行います。

# リクエストボディ

{ "jsonrpc": "2.0", "method": "echo", "params": {"msg": "ok"}, "id": "1"}

# レスポンスボディ

{"jsonrpc": "2.0", "result": "ok", "id": "1"}

WidebulletはこのJSON-RPCをベースに少し拡張したプロトコルを用いてRESTful APIサーバのためのゲートウェイとして動作します。以下はWidebulletが受信可能なリクエストボディの例です。

[
  {
    "jsonrpc": "2.0",
    "ep": "ep-1",
    "method": "/user/get",
    "params": {
      "user_id": 1
    },
    "id": "1"
  },
  {
    "jsonrpc": "2.0",
    "ep": "ep-1",
    "method": "/item/get",
    "params": {
      "item_id": 2
    },
    "id": "2"
  }
]

設定にも依りますが、Widebulletはこのリクエストボディを解析して以下のURLに対してGETリクエストを実行します。(この例ではGETのみですが、WidebulletはPOSTもサポートしています。詳しくはmercari/widebullet/SPEC.mdをご覧下さい。)

  • http://ep-1/user/get?user_id=1
  • http://ep-1/item/get?item_id=2

各リクエストはゴルーチンによって並行して実行されるのがミソです。Widebulletと通信するクライアントは単一のHTTPリクエストを発行するだけでバックエンドのRESTful APIサーバに対して複数のAPIリクエストを同時に発行することができます。

WidebulletとメルカリAPI

メルカリにはサービス当初から稼働しているAPIサーバがあります。これはPHPで書かれたそれなりの規模があるコードベースで、メルカリのコア機能が集約されたものでもあります。以前はAPIへのリクエストはアプリから発行されるだけでしたが、現在はメルカリの内部ネットワーク内にある各サブシステムからも飛んでくるようになっています。(すべてのAPIリクエストはnginxでロードバランスされています。)

f:id:cubicdaiya:20160321024917p:plain

このように各サブシステムはAPIサーバに対してHTTP(あるいはHTTPS)リクエストを発行するだけでメルカリのコア機能を利用することができ、コードの再利用性やプログラマの生産性の向上にもつながります。

一方でサブシステムがAPIを利用する際、パフォーマンスを出すために同時に複数のAPIに対してHTTPリクエストを発行しなければならないケースが少なくありませんでした。この際、言語によってはHTTPリクエストの並行実行が少々面倒なのでその部分をWidebulletが肩代わりするというわけです。

f:id:cubicdaiya:20160321024952p:plain

当初はlua-resty-jsonrpc-batchみたいにngx_luaを利用することも考えましたが、ミドルウェアの性質上サブシステムからAPIを叩くエンジニアの開発環境にもインストールするので配布が簡単なGoで開発しています。今のところWidebulletはメルカリの比較的小さなサブシステムで稼働しているのみですが、特に問題もなく安定して動いています。

メルカリAPIと共通技術基盤

ところで、なんでもかんでも単一のAPIサーバに機能を集約してしまうと結果的にモノリシックなシステムが出来上がってしまい、開発スピードやコードベースのメンテナンス性に大きな影響が出てくることもあり、昨年頃からはサービス当初からあるAPIサーバに機能を詰め込むのではなく、異なるシステムでも共通して利用できるよう基盤ソフトウェアスタックとして切り出す動きが出てきています。すでに本ブログで紹介しているものだと、

があります。最近の新しい事例だとGRPCを利用した共通ID基盤が稼働を開始しており、今後もこういった流れは続くでしょう。また、共通基盤となるシステムはパフォーマンスやスケーラビリティを重視してることからGoやOpenResty(ngx_lua)が選ばれる傾向があります。

メルカリのバックエンドを支えるSREを募集中です

メルカリでは共通のソフトウェア基盤となるバックエンドの開発や運用を行うSREを募集しています。SREチームの役割は範囲が広いですが、大まかにいくつか列挙すると以下のようなものです。

  • システムのパフォーマンスや信頼性、スケーラビリティを向上させるためのソフトウェアの開発と運用
  • システム上の技術的な問題や課題の発見と解決、そしてそのためのソフトウェア開発
  • サーバ・ネットワークの構築・運用、システムの自動化や障害対応などのシステム管理者的な業務

興味のある方は「エンジニア(Site Reliability Engineering) | 株式会社メルカリ」からご応募ください。

参考