Microservice で実現するココナラ新プロフィールページ機能

こんにちは。開発グループ・エンジニアの阿部です。
社内では abemotion って呼ばれたりもします。

前回の記事で紹介したのですが、

yomoyamablog.coconala.co.jp

提案していたマイクロサービスの構成を初めて利用した

「新プロフィールページ機能」をついにリリースしました!!

f:id:coconalainc:20181030183148p:plain

設計期間も含めると約5ヶ月、、

長い戦いでした...

今回はそんな「新プロフィールページ機能」のシステム部分について、お話をさせて頂けたらと思います。

  • システム構成
  • 設計方針
  • レイヤ設計
  • gRPC

システム構成

言語・フレームワーク
フロントエンド Nuxt.js
apigateway golang
サーバーサイド Rails
通信 gRPC

私は apigateway(golang)の構築と profile Service の Rails 実装を担当しました。

マイクロサービス構成としてもそうですが、apigateway に至っては、本当に一から構築でした。

今回は golang での apigateway に焦点をあてたいと思います。

設計方針

まずは設計方針からなのですが、

男は黙って標準パッケージ

フレームワーク(以下、WAF)を用いず、Goの標準パッケージを使って開発しました。

まだデファクトスタンダードのWAFがなく、
その段階でWAFを使うのは、今後負債化する恐れがあるためです。
※ もちろん使っている会社もある

ただ仕方なしの選定ではないです。

Goには機能豊富なパッケージが多く、
WAFの中には、標準パッケージをラッパーしているだけ的なのもあります。

標準パッケージ選定理由

  • そもそも apigateway の機能仕様が限られてる(O/Rマッパーもいらないぐらい)
  • パフォーマンス良
  • 細かいチューニングができる(WAF仕様に縛られない)
  • 外部ライブラリは使ってますよ!

パッケージ構成

次はパッケージ構成について、 Webアプリ内のレイヤ(ディレクトリ)構造をどうするかという話です。

そもそもGoでは、相互参照するとエラーになるので、
フレームワークを使わない以上、設計が重要になってきます。

他社さんの記事なども参考にさせて頂き、Lightweight DDDを採用しました。
(DDDライクなライトなパッケージ構成。レイヤアーキテクチャ)

レイヤ設計

  • interfaces:リクエストハンドラ
  • application:domain層を扱うビジネスロジック
  • domain:モデル。構造体定義(値と振る舞い)他構造体に付随する共通処理
    • repository:infrastructure のインターフェース定義
    • service:application のインターフェース定義
  • infrastructure:技術的機能
    • persistence:domainで定義したデータアクセスの実装

「依存関係逆転の法則」を意識し、依存の方向や詳細ではなく抽象へ依存するよう考慮しました。

参考記事
Webアプリケーションにおける Go 言語のパッケージ構成〜メルカリ カウル編〜
Goのパッケージ構成の失敗遍歴と現状確認
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える

gRPC

フロントエンド(Express)→ apigateway → Profile Service 間は、gRPCで通信しています。

前回の記事で、gRPCの概要・メリットは説明したので、ここでは使い方や運用方法について記します。

使い方

  • .proto ファイルの定義
  • ソースコードの自動生成
  • サーバ、クライアントの実装
  • 実行

まずインターフェースの仕様となる .proto ファイルを Protocol Buffers 形式で記述し、
ファイル自体は専用のリポジトリを1つ用意し一元管理しています。

リポジトリからソースを取得し、 protoc コマンドを使うことで言語毎のモデルファイルが生成できます。

実装はサーバ/クライアント共に生成されたファイルを使って開発を行います。

gRPC では、エラーコードが独自に用意されており、 HTTP ステータスコードとのマッピングもコメント内に書かれています。

gRPCエラーコード

エラー名 code HTTP Status Code
OK 0 200
UNKNOWN 2 500
INVALID_ARGUMENT 3 400
DEADLINE_EXCEEDED 4 504
NOT_FOUND 5 404
ALREADY_EXISTS 6 409
PERMISSION_DENIED 7 403
RESOURCE_EXHAUSTED 8 429
FAILED_PRECONDITION 9 429
ABORTED 10 409
OUT_OF_RANGE 11 400
UNIMPLEMENTED 12 501
INTERNAL 13 500
UNAVAILABLE 14 503
DATA_LOSS 15 500
UNAUTHENTICATED 16 401

通信エラーなどは上記コードが返ってきますし、
gRPC上でのリトライ処理等も、このエラーコードで判定されて行われるので慣れる必要があります。
詳細はこちら

最後に

今回 apigateway をフレームワークを用いずに一から構築することで、
以下、システムの構成要素全てを設計・検討する良い機会となりました。

システム構成要素

  • 基本設計
  • レイヤ設計
  • 抽象(inteface)への依存
  • パッケージ管理
  • エラーハンドリング
  • ログ出力
  • アラート設定

挑戦させてくれた会社と開発チームにはホント感謝です!


ココナラでは新技術にチャレンジングな仲間もお待ちしています!

www.wantedly.com

yomoyamablog.coconala.co.jp


お知らせメール登録
よもやまブログの更新時にメールでお知らせします。