Help us understand the problem. What is going on with this article?

Go言語で REST API + マイクロサービス

More than 5 years have passed since last update.

Go その2 Advent Calendar 2015 2日目です。

今日書くこと

  • APIを提供するためのコード
  • APIを利用するためのコード
  • マイクロサービス (・∀・)ィィイイ!! かもしれない
  • やれなかった / この記事には書いていないこと

以下サンプルで利用するコードは こちら
お手元で起動する1 ための手順は READMEをご覧ください。

APIを提供するためのコード

Go言語には APIのためのよさげなフレームワークはありますが、
今回はそれらを使わずともかんたんに APIサーバが作れることをお伝えしたく。

ベースとなっている元ネタは A RESTful Micro-Framework in Go これなのですが
ここから、やりたいことができるように変えていった結果をサンプルに、
どうすれば APIサーバが書けるのかを記します。
 

  1. まず、APIのエンドポイントが実装すべきインターフェイスを定義します
    https://github.com/pottava/golang-microservices/blob/master/app-dbio/app/http/restapi.go#L32

  2. すべて StatusMethodNotAllowed エラーとなるデフォルト実装をした構造を定義します
    https://github.com/pottava/golang-microservices/blob/master/app-dbio/app/http/restapi.go#L51

  3. 各 APIエンドポイントは、2の構造を埋め込んだ構造を定義して
    https://github.com/pottava/golang-microservices/blob/master/app-dbio/app/controllers/user.go#L18

  4. API実装したい HTTPメソッドだけ、ロジックを書きます
    https://github.com/pottava/golang-microservices/blob/master/app-dbio/app/controllers/user.go#L22

かんたんですね!

RESTful風 APIにしたければ、こんな感じでリソース IDをベースに分岐することもできますし
https://github.com/pottava/golang-microservices/blob/master/app-dbio/app/controllers/user.go#L24
POSTや PUTのように、bodyから JSONを取り出したければこんな感じで実装できます。
https://github.com/pottava/golang-microservices/blob/master/app-dbio/app/controllers/user.go#L41
サンプルにはないですが、クエリ文字列から引数を受け取りたければ
queries.Get("limit") などと書けます。

メソッド名が変だとか、そもそも APIサーバなんだから
パッケージ名は controllers じゃなくて resources だろ
といった暖かいメッセージは受け付けていません。赦してください。

APIを利用するためのコード

RESTな APIであれば返り値は JSON2 だと思うのですが、
https://github.com/pottava/golang-microservices/blob/master/app-webui/app/models/api.go#L40
引数 resJSON に構造体のポインタを渡してあげます。
JSONではなく文字列がよければ nil を渡し、関数の返り値として受け取れます。

例えばデータ取得 APIからユーザ情報を受け取るときはこんな感じです。
https://github.com/pottava/golang-microservices/blob/master/app-webui/app/models/user.go#L29

ちなみに細かいことですが、サーバサイドが対応しているなら
圧縮解凍ロジックがあっていいのではと思う私です。
https://github.com/pottava/golang-microservices/blob/master/app-webui/app/models/api.go#L43

余談ですが、このサンプルでは API結果に「エンベロープ」がありますが
なければもっとシンプルでいいのかもしれません。
このへんは完全に好みですね!

マイクロサービス (・∀・)ィィイイ!! かもしれない

docker-compose3 を使い、ひとつのアプリケーションを
複数の小さなサービスで構成するのが趣味なのですが
ほんとにとてもいいのです。

  • コンパイルがより高速: Goとはいえ、モノリシックにつくるとコンパイルに数秒かかるように..
  • APIを RESTfulにしやすい: セッションの分離 & サーバ間のみにアクセス制限するのがかんたん
  • 一部サービスの更新、引き継ぎ、モック化、エンドポイント変更、開発言語の変更などが容易
  • サービスが依存する引数・環境変数が明確になって管理がらくになる

などなど..

ちなみに、今回ユーザ認証も単独のサービスにした影響で
CORSと Ajaxの設定にあまり使わないものをセットしたので書き残します。

https://github.com/pottava/golang-microservices/blob/master/app-authentication/app/http/http.go#L133
https://github.com/pottava/golang-microservices/blob/master/app-webui/app/assets/js/app/index.jsx#L7

両方書かないと Cookie渡せないんですね!(小並感)

やれなかった / この記事には書いていないこと

スロットリング

API提供側にはスロットリングがあるといいかと思います。
実際にちゃんとコードを書いたら設定値周辺が複雑になってしまったので
今回の例からは全部省きましたが、私はこれ使ってます。
http://gopkg.in/throttled/throttled.v2

Exponential Backoff

API利用側のお話ですが、エラー時のリトライアルゴリズムです。
指数関数的後退と訳されたりもしますがこれ大事。
以下 AWSの記事ですが、知らない方はぜひ。
AWS でのエラーの再試行とエクスポネンシャルバックオフ

で、私はこれを このへん を参考に実装してみています。
テストが不十分なのでこれも今回のサンプルからは外しました。

Swaggger

いずれかをちゃんと使いたいと思いながら。アドカレに実例でるといいなあ
https://github.com/yvasiyarov/swagger
https://github.com/go-swagger/go-swagger
 


  1. dockerの新しいネットワーク機能を使うため、docker-composeは v1.5以降が必要です 

  2. XMLのケースは書いたことないですすみません 

  3. docker-composeなしでマイクロサービスを作るのはつらすぎだと思う 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away