HerokuでMicroservicesを実装するときに役立つ便利機能

Microservices Advent Calendar 2018 23日目、本日はかしゆかの誕生日です、ゆかちゃん誕生日おめでとうございます、三十路だね。ということで、本日は記念して、Heroku のお便利機能についてご紹介します。

きっかけはどうであれ、「さぁMicroservicesへ移行するぞ!!」というよりも「Microservices化しないとあかんやつや...」みたいになって、アプリケーションアーキテクチャの一切合財を、根底から覆すような自体に陥ってから始まることはよくあることです。そのときは、アプリケーションアーキテクチャの変更を、インフラ・プラットフォームが障壁となって、実現を困難にするのはよろしくないのは想像に難くないでしょう。

実際には、`Microservices`の原典通り、モノリシックアプリケーションを少しずつ引っ剥がしながら、`Microservies`化を進めていくことが多いと考えています。もし、Heroku だったら、そのときの障壁をどれだけ少なくすることができるだろうか、という問いに対して[Private Space DNS Service Discovery](https://devcenter.heroku.com/articles/dyno-dns-service-discovery)を紹介できます。

# [Private Space DNS Service Discovery](https://devcenter.heroku.com/articles/dyno-dns-service-discovery)

Herokuは、アプリケーションの動作するコンテナを`Dyno`と呼んでいます。[Heroku Private Spaces](https://jp.heroku.com/private-spaces) サービスの中で実行されるすべての`Dyno`に対して内部的にホスト名が割り当てられる仕様になっています。FQDN は次の通りの命名規則になっています。

内部アドレスのFQDN: **[Dyno番号].<プロセスタイプ>.< Herokuアプリ名>.app.localspace**

## Dyno番号

`Dyno番号` とは、起動しているコンテナの通し番号です。標準では 1つの`Dyno`で起動するようになっていますが、スケールさせることによって、これを10個、100個と簡単に増やすことができます。起動した順番によって、この番号が割り振られる仕様となっています。たとえば、20個の`Dyno`を動かした場合には、1〜20の通し番号が振られる、ということです。

## プロセスタイプ

`Dyno`は役割を持って起動させることが可能です。

一つのアプリケーションソースコードで、複数のプロセス・アプリケーションを起動したいということはよくあることでしょう。外部からのアクセスを受け付けるWebアプリケーションの役割をもつもの、バックエンドで非同期処理を行うもの、時限的にバッチ処理を行うもの。他にも様々な役割を持つものがあるでしょう。これらは、一般的に起動するコマンド自体が異なっているものです。たとえば、Node.jsの`Express`フレームワークでアプリケーションを作った場合、Webアプリケーションは `npm start` で起動されるでしょうし、バックエンドアプリケーションは `npm run worker` などのように別の起動コマンドを指定しているはずです。異なるプロセスとして個別に動かしたい場合は、このように起動コマンドを分離して利用します。

Heroku では、これらを「`プロセスタイプ`」として定義を行います。具体的には、ソースコードのあるルートディレクトリに[Procfile](https://devcenter.heroku.com/articles/procfile)を準備して定義します。先程の Node.jsの例を記述するとするならば、次のとおりになります。

```
web: npm start
worker: npm run worker
```

このようにして、起動タイプを変えることで、個別に`Dyno`を制御できるのが特徴です。`web`プロセスは、スペックの低い`Dyno`を、アクセスをできるだけ処理したいから５個動かす。バックエンドの`worker`プロセスは、重めの処理を行い、メモリも使うのでスペックの高い`Dyno`に。処理依頼自体は多くないので、２子で動かす。などのように個別に定義できるのがお便利なところです。

また、この`web`プロセスタイプは外部に必ずサービスを公開するURLをもつことになりますが、`web`プロセスタイプを持たないHerokuアプリケーションを作成することで、Private Space内だけでアクセスできる、内部専用のアプリケーションを提供することもできます。外部からはアクセスされたくない、隠蔽されたサービスの開発も容易にできてしまうんですね。

## Herokuアプリ

Herokuでアプリケーションを実行する場合に、一つのURLが割り振られる単位、または一つのソースコードツリーで表現されるアプリケーションの単位を、Herokuへデプロイする単位となります。Herokuアプリケーションには、一つのGitリポジトリが割り当てられています。このリポジトリにソースコードをpushすることで、一つのアプリケーションがデプロイされます。

サービスの内容、実現したい機能によって、この単位は分割されるでしょうが、この一つの管理単位のことをHerokuアプリケーションで分割するようになっています。

このHerokuアプリケーションでは、「環境変数」「アドオン」をセットする単位ともなりますので、共有して利用したい機能をまとめるには、それらを共有したい単位にして一つのアプリケーションとすることも検討できます。ただし、アドオンについては、複数のHerokuアプリケーションで共有できるものもあります。例えばHerokuの提供する`Heorku Postgres`は、複数のHerokuアプリケーションで共有できるものです。

## DNSサービスディスカバリの使い方

例えば、test-private-space という名前の Herokuアプリケーション上に、webとworker Dynoが２つずつ稼働していて、この中の worker の１つ目の Dynoへアクセスしたい場合であれば、1.worker.test-private-space.app.localspace というホスト名へアクセスすれば、該当のアプリケーションへダイレクトに接続することができます。

実際に稼働中のDynoを指定してアクセスできるのはありがた嬉しいのですが、スケールしていて複数のDynoが動いているような場合、わざわざ特定のDynoをアプリケーションで指定するには荷が重すぎます。

なんと、FQDNのうち`[Dyno番号]`は省略することができます。`[Dyno番号]`を省略してホスト名解決を行うと、稼働中のプロセスタイプのDynoのうち、ランダムで対象のDynoの３つのIPアドレスが返ってくる仕様です。もちろん３台稼働していなければ、１つや２つしか返ってこないケースもあります。この取得したIPアドレスを元にアクセスすれば、自動的に負荷分散の機能も享受されるという仕組みにもなっています。

# まとめ

`Microservices`でサービスメッシュ構造となるときに、具体的にそのサービスをポイントする方法が明確になっていなければ、使いにくいことこの上ないでしょう。自動的に割り振られるホスト名の場合、そのサービスが実現するものと名前が紐づけされていなければサービスとホスト名を紐付ける別の何かをジュビしなければなりません。

Heroku Private Spaceをご利用であれば、サービスを特定できるHerokuアプリケーション名とプロセスタイプを名付けることが自由にできます。そして、その名前がそのままホスト名として利用できることは、機能的価値が高いのではと考えられます。

Microservices の実現のお供にHeroku、ぜひご検討くださいませ。