Go で始める JSON-RPC 入門

osamingo
osamingo
Dec 15, 2016 · 6 min read
Gopher artwork is taken from gophericons. Created by Olga Shalakhina, based on original work by Renée French. Licensed under Creative Commons 3.0 Attributions.

この記事は、 Go Advent Calendar 2016 の 15 日目の記事です。

みなさんは、JSON-RPC を使ったことがありますか?
この記事では、 Go で JSON-RPC を使用する方法をレクチャーしたいと思います。(※ この記事は、 golang.tokyo #2 での LT 内容をベースに加筆修正を加えたものになります。)

JSON-RPC とは

概要

JSON-RPC は、 JSON を媒体とした Remote Procedure Call です。

そのため、 Content-Type: application/json で Request と Response をやり取りします。また、 RPC なので Endpoint も任意で決めた Path のみとなります。

JSON-RPC の利点のひとつに、新しく覚える要素がほとんど無いという点があります。最新の仕様である、 JSON-RPC 2.0 も、コンパクトな内容でシンプルです。

簡単な例

Echo という method を定義し、Request で name を受け取ったら、 Response の message という Property に Hello, {{name}} という文字列を生成して返却するとします。

そうすると、Request は、

{
"jsonrpc": "2.0",
"method": "Echo",
"params": {
"name": "John Doe"
},
"id": "243a718a-2ebb-4e32-8cc8-210c39e8a14b"
}

となり、 Response は、

{
"jsonrpc": "2.0",
"result": {
"message": "Hello, John Doe"
},
"id": "243a718a-2ebb-4e32-8cc8-210c39e8a14b"
}

となります。

標準 Package での JSON-RPC

Go には、 net/rpc/jsonrpc というPackage があり、標準で JSON-RPC をサポートしています。

実装例

上記のように実装することが、出来ます。

また、上記の実装では省いていますが、 Debug Handler も付属しており、登録済みの Method 一覧と Call 数を確認することが出来ます。

The debug html page by Debug Handler

標準 Package での所感

  • 実装を通して、 RPC をレクチャーしてくれる Go らしさを感じる。
  • JSON-RPC 2.0 の仕様は満たしていない。
  • HTTP で受け取るには、 net.Conn を取り出さないといけない。
  • Package 内を覗くと reflect を多用している印象がある。

Third Party Package での JSON-RPC

Gorilla Toolkit が、JSON-RPC 2.0 の仕様を実装してくれています。

実装例

上記のように実装することが、出来ます。

定義してある、 Interface が変更されていて、第一引数で *http.Request を受け取ることが出来るようになっています。また、 net.Conn を取り出すことも無く、 Codec を登録し Handler を Endpoint に設定するだけになっています。

Gorilla Toolkit での所感

  • 標準 Package を踏襲しつつ、扱いやすくなっている。
  • Go 1.6 以下だと、 context.Context を持ち運べない。
  • Custom Error を返却したい場合 data を書き込めないなど、すこし手の届かないところがある。

オススメの Package

結構、いろいろな Package を見て回ったのですが…、ありませんでした。

ないので、 github.com/osamingo/jsonrpc を作りました。

README.md

実装例

上記のように実装することが、出来ます。

各 Method に対応する jsonrpc.Func を満たす関数を定義して行きます。 jsonrpc.RegisterMethod に Method 名と関数を登録し、 Endpoint を設定します。

Gorilla Toolkit との差異

  • reflect を使わず、 Method Repository という形で、 map を利用して Method 名と関数ポインタを紐付けています。
  • Go の Version に関わらず、 context.Context を持ち運ぶようにしています。 Google App Engine の Standerd Environment に対応しています。
  • Endpoint が任意で決めた Path のみとなり Swagger や、 API Blueprint 等のツールに対応出来ません。
    なので、 Debug Handler を用意し、登録してある Method 一覧と各 Method に紐付く Params, Result の JSON Schema を自動生成するようにしました。具体的には、下記のような Response を返却します。
Access to the debug endpoint

まとめ

全体を通して、まとめるとこのような感じになります。

  • JSON-RPC は既存知識の組み合わせなので、シンプル且つ簡単である。
  • Go は、標準 Package で、 JSON-RPC をサポートしている。
  • Gorilla Toolkit は、標準 Package を踏襲しつつ、JSON-RPC 2.0 の仕様を実装してくれている。
  • osamingo/jsonrpc は、JSON-RPC 2.0 の仕様を満たし、よりシンプルに、より Debug しやすくなっている。また、 context.Context をサポートしているので、 Google App Engine でも使える。

Go で始める JSON-RPC 入門は、いかがだったでしょうか。
仕様自体もとてもシンプルで、 RPC を学ぶ上では分かりやすい例だったと思います。この記事が、お役に立てれれば幸いです。

明日の Go Advent Calendar 2016 は、 @yuin さんです。

osamingo

Written by

osamingo

A ʕ◔ϖ◔ʔ engineer at Souzoh, Inc. (affiliated by Mercari, Inc.) My GitHub is https://git.io/osamingo

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade