バイナリひとつで動く郵便番号検索サーバーを作った話
1年以上前ですが、作ってました。
何を作ったの?
郵便番号から住所を検索するだけのAPIサーバーです。 zippia と名付けました。
データベースを内包したバイナリファイルひとつだけで動きます。
マイクロサービスに組み込んで使われることを想定していて、エンドポイントは /
のひとつだけ。
立ち上げたサーバーの API 仕様書は以下を見てください。
郵便番号は毎月更新されますが、内包データベースを更新した新しいバイナリを毎月リリースしてます。
なぜ作ったの?
郵便番号マスタの管理が手間 (KEN_ALL.CSV) で、二度とやりたくないと思ったから。
無償で一般公開されてるサービスを使うのもありだけどレート制限あったりして、趣味で使うには良いけど商用で使うのは微妙。有償サービス使えば良いのだけど、スタートアップのサービス作るときにいきなりコストかけたくない。
ということで、
- 自動で郵便番号更新してくれて
- 無償で使えて
- 自分のところでホストするのでレート制限とかもない
- 別途 DB 立ち上げなくて良い
そんな OSS があったらいいな、と思って作りました。
使い方は?
-
go install
してzippia
コマンド叩く - docker で起動
- Releases からバイナリをダウンロード
お好きな方法でどうぞ。
詳しくは README をご覧ください。
dockerhub にもアップしているので、 ECS なり Kubernetes なりに組み込んで使うことも簡単にできると思います。
ユースケースは?
マイクロサービスのひとつとして使われることを想定してます。
サーバーレスなら ECS や Kubernetes に組み込むもよし
サーバーにインストールしてメインのアプリケーションサーバーとは別プロセスで立ち上げて、 nginx/Apache なりのフロントサーバーからリバースプロキシの設定するもよし
設定ファイル等なくバイナリファイルひとつだけで動くので、いろいろと使い勝手良いと思ってます。
どうやって作ったの?
データベース内包
SQLite3 のインメモリデータベースと、 go:embed を組み合わせて実現しています。
-
SQLite3
- サーバーではなくアプリケーションに組み込んで利用される RDBMS
- データ保管に単一ファイルのみを使用することが特徴
- ファイルを使わない揮発性のインメモリデータベースとしても利用可能
-
go:embed
- 外部ファイルをプログラムに埋め込むための機能
- Go プログラムの実行に必要な設定ファイルや外部ファイルをバイナリファイルに組み込むことができる
サーバー起動時に
- go:embed で KEN_ALL.CSV をパースした json を読み込む
- SQLite3 のインメモリデータベースへ json の中身をインポートする
- APIサーバー起動、リクエスト受付
のような処理をしています。
サーバー起動の度にインポートするのがネックかなと思ってましたが、案外 2秒ほどでインポート処理完了します。
↓サーバー起動時のログ
2024/01/15 19:38:07 initializing database...
2024/01/15 19:38:09 database initialization is completed!
2024/01/15 19:38:09 start the Japanese zip code search API server.
_ _
___(_)_ __ _ __ (_) __ _
|_ / | '_ \| '_ \| |/ _` |
/ /| | |_) | |_) | | (_| |
/___|_| .__/| .__/|_|\__,_|
|_| |_|
version v0.3.31
Zip code was last modified on "Thu, 28 Dec 2023 07:59:01 GMT"
2024/01/15 19:38:09 http server started on http://127.0.0.1:5000
自動更新
GitHub Actions を使って定期的に KEN_ALL.CSV の更新があるかチェックして、更新があればそれをダウンロード・加工して go:embed で組み込んでビルドしています。
ここら辺は shellscript で対応してます。
↓例
謝辞
KEN_ALL.CSV の加工に inouet/ken-all を使っています。
このソフトウェアがなければ、 zippia は作れませんでした。
inouet さんありがとうございました!
Discussion