Schooアプリを支えるGolangサーバーの構成について


はじめに

本投稿は、Schooの年末特別企画「Schoo advent calendar 2016」への投稿記事になります。

14日目の今回は、先日公開したSchooアプリver2系のバックエンド構成について、個人的なピックアップポイントと共にお届けします。

それでは、どぞー

サーバー構成と概要

まずは、簡単な構成図です。クライアントに近い方から紹介していきます。

ELB/TCP

最前面にELBを配置しています。
こちらはロードバランサーとして利用しているのではなく、2個あるサーバーグループへのアクセスをリリース毎に切り替える目的で利用しています。
(TCPモードにしているのは、HTTP/2を扱うため)

Pickup!

ELBに登録するEC2インスタンスを動的に入れ替えてトラフィックの切り替えを実現しているんですが、それを自動でやってくれるのはSchoo開発チームのお友達「すくすけ」ですよ!

nghttpx

HTTP/2対応のリバースプロキシー/L7ロードバランサーです。
パスベースの振り分けで利用していて、前面/背面共にHTTP/2での通信になっています。(TLSは前面のみ)
当初はALBでやろうとしたんですが、背面側がまだHTTP/2に対応していなかったため、今回の構成になりました。
ALBが対応したら置き換えを検討しようかと思います。

Pickup!

ALBはもちろんnginxなども検討したんですが、背面側でのHTTP/2対応がなかなかのハードルで、現状nghttpx一択ではないかと思います。
ちなみに、nghttpxのコンテナについてはこちらを参考にさせていただきました。

Golangアプリケーションサーバー

gRPC実装のGolangサーバー複数台で構成されています。
サーバーが機能ごとに別れているのとgRPCがHTTP/2を利用するため、nghttpxを利用したパスベースの振り分けが必要だったということになります。
将来的に、機能単位でのスケールアウトを想定しての構成となっています。

Pickup!

GolangサーバーのDockerコンテナはAlpine Linuxイメージをベースにしています。そのためイメージサイズが非常に小さいです。

Dockerfile
FROM alpine

RUN apk --update add ca-certificates
RUN apk --update add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata && \
    rm -rf /var/cache/apk/*

上記のようなDockerfileでビルドしたものを利用していますが、イメージサイズは驚きの6MBです!

また、Alpine Linuxで動かすGolangバイナリは、ビルド時にstatic link化する必要があるようでした。利用される方は、ご注意ください。

Blue/Greenデプロイ構成

Dockerホストを利用した再利用型のBlue/Greenデプロイ構成になっています。
なので同じサーバーグループが2個ありますが、docker swarmなどを利用したクラスタ構成ではなくて、動的に入れ替われるProductionStagingのような独立した関係になります。

Pickup!

本番公開されていない方をStagingとして利用し十分な確認の後、StagingProductionに昇格、ProductionStagingに降格という切り替えを行っています。

ProductionStagingが固定されている環境よりも、確認タスクや公開タスクを少なくできて便利です。
デメリットとしては構成スケールが常に同じである必要がある点でしょうか。(大規模サービスには向かないですね)

ちなみに、各環境へのデプロイも「すくすけ」がやってくれます!

まとめ

いかがでしたでしょうか。
どこかに関心のある部分はあったでしょうか。
構成要素は他にもたくさんありますが、ボリューム的に省略させて頂いた部分も多いです。

まだまだ手探り感がありますが、ゼロからサービスを構築する醍醐味は十分にあると思います。
少しでも興味を持たれた方は、SchooのWantedlyページを是非チェックしてみて下さい!

何卒、なにとぞー