Go言語の学習がてら Healthcheck Notifier を作ってみた
以前から、Go言語(golang)をちょっとやってみたりしてたんですが、実用的なものを作ってみたいと思い、 Healthcheck Notifier というものを作ってみました。
一つのソースファイルでできているとてもシンプルなものです。
Webアプリケーションに対し、ヘルスチェックのリクエストを投げ、ステータスコード200以外が返答された場合、Alert を HipChat やメールで通知します。
クイックスタート
リリースページからバイナリをダウンロードします。
Windows, macOS, Linux のバイナリがあります。
ダウンロードしたバイナリを以下のように実行するだけで起動します(Linuxの例)。
./healthcheck-notifier-linux-amd64
Webアプリとして起動するので、ヘルスチェックの状態を Webブラウザから確認できます。
以下のURLをWebブラウザで開いてみてください。
http://localhost:18888/
以下は、スクリーンショットです。
仕様
- 監視対象のアプリケーションがヘルスチェックエラーになるとHipChatの設定された Room に通知し、設定されたメールアドレスにメール送信します。連続してエラーになる場合、通知はしません。
- ヘルスチェックエラー後、ヘルスチェック成功を確認するとHipChatの設定された Room に通知し、設定されたメールアドレスにメール送信します。
設定ファイル
Healthcheck Notifier は、起動時に設定ファイルが存在しない場合、自分自身のアプリケーションを監視するような設定ファイルを例として作成します。この設定ファイルを書き換えます。
起動したディレクトリに以下のようなconfig.json
が作成されていると思います。
{ "cron": "*/10 * * * * *", "port": 18888, "hipchat-proxy": "", "hipchat-subdomain": "hipchat-subdomain", "smtp-server": "localhost:25", "mail-address-from": "from@example.com", "apps": [ { "name": "self", "url": "http://localhost:18888/", "proxy": "", "hipchat-room": "1234567", "hipchat-token": "", "mail-address-to-down": ["to1@example.com", "to2@example.com"], "mail-address-to-up": ["to1@example.com", "to2@example.com"] } ] }
設定内容については以下です。
プロパティ | 説明 |
---|---|
cron | ヘルスチェックの周期(クーロン形式) |
port | モニター用のWeb画面が仕様するポート番号 |
hipchat-proxy | HipChat通知で使用するプロキシ |
hipchat-subdomain | 利用しているHipChatのサブドメイン |
stmp-server | メール通知で使用するSMTPサーバ |
mail-address-from | メール通知するときのFROMアドレス |
apps.name | 監視対象のアプリケーション名称 |
apps.url | 監視対象のURL |
apps.proxy | ヘルスチェックのリクエストで使用するプロキシ |
apps.hipchat-room | 通知する HipChat Room の ID |
apps.hipchat-token | HipChat のトークン |
apps.mail-address-to-down | ヘルスチェックエラーになった場合に送るメールアドレス |
apps[].mail-address-to-up | ヘルスチェックエラー状態からヘルスチェック成功した場合に送るメールアドレス |
golang について
golang について覚えたことや感じたことを整理してみます。
最近の言語にある色々なものをバッサリ削った感じで、
プログラミング言語に理想や夢を求める人にはあまり受け入れられない現実指向な言語かと思います。
初めて学ぶプログラミング言語として、 golang というのはアリかもしれないと思った。
標準ライブラリが充実している
今回作成したソースファイルは一つだけですが、以下の事を行っています。
- HTTPクライアント
- HTTPサーバ
- JSONパース
- 並行処理
- ファイル出力
- ファイル入力
- タスクスケジューリング
タスクスケジュール以外は、標準ライブラリでできてしまうところが凄い。
Javaだとサードパーティーのライブラリに頼っていたところが標準でできる感じです。
型宣言は、後置
まー最近の言語は型推論とかあるので型宣言は後置の方が自然ですよね。他の言語にあるようなコロンは不要。
var httpServer http.Server
型推論
ローカル変数の型推論。初回代入はコロンが必要
port := os.Getenv("PORT")
再代入は、コロンが不要。
port = "18888"
メソッド(メンバ関数)みたいなもの
以下のような感じで関数名の前に構造体のポインタを宣言することでメソッドように使えるようになる。
func (a *App) healthcheck() { // ... }
複数行文字列リテラル
ヒアドキュメントというか複数行文字列リテラル。
対象部分をバッククォートで括る。
` { "cron": "*/10 * * * * *", "port": 18888 } `
戻り値を複数返せる
送り側
func foo() (int, string) { return 1, "bar" }
受け取り側
num, str := foo()
アンスコで戻り値の一部を無視
_, err := os.Stat(filename)
JSONパース
JSONに対応する構造体を作る。
type App struct { Name string `json:"name"` URL string `json:"url"` }
json:"XXX"
がJSONのパース処理への注釈のようなものになっているらしい。
変数Name
はJSONプロパティのname
と対応するようになる。Javaだとアノテーションでやっているような事だと思う。
import (json "encoding/json")
json.Unmarshal(バイト配列, 格納する構造体)
スコープ管理?
大文字で始まる関数・変数は、public(export)扱いになって、小文字で始まると private 的な扱いになる。
この命名規則による仕様は、正直ビミョーだなーと思うところ。。
Goroutine
golang の一番の特徴かもしれない goroutine
並行処理が軽量スレッドで簡単に実行できます。
以下が例です。
var wg sync.WaitGroup for i := 0; i < len(hn.Apps); i++ { go func(i int) { wg.Add(1) hn.Apps[i].healthcheck() wg.Done() }(i) } wg.Wait()
go
を付けた部分が並行で処理されます。
wg.Wait()
ですべての処理が終了するのを待っています。
クロスコンパイル
これも golang の一番の特徴かもしれない。
Windows で macOS, Linux のバイナリをコンパイルしたりできます。
$ GOOS=windows GOARCH=amd64 go build
$ GOOS=linux GOARCH=amd64 go build
$ GOOS=darwin GOARCH=amd64 go build
シングルバイナリで実行でき、ポータビリティが高いのが特徴だと思った。
サードパーティーのライブラリ
JSでいう npm , Java でいう Maven レポジトリみたいなものは存在せず、github とかのソースを直接引っ張ってくるみたい。
以下のような感じで import
する。
import ("github.com/robfig/cron")
github から直接もってくると、そのライブラリの信頼性はどうなんだろうと少し不安になる。
ライブラリの依存管理
dep というコマンドをインストールして管理する。
dep をインストール
$ go get -u github.com/golang/dep/cmd/dep
設定ファイル(Gopkg.toml, Gopkg.lock)を生成
$ dep init
依存をvendor
ディレクトリ配下にインストール
$ dep ensure
今まで、色んなツールがあったみたいですが、dep が標準になるっぽい。
エラーハンドリング
golang には他の言語にあるような Exception がありません。
グローバルにエラーをハンドリングできず、細かくちゃんとエラーハンドリングしないとちょっとしたバグでプロセスが落ちてしまいそうです。
他の言語だと警告レベルのものがコンパイルエラーになって後回しにできない。未使用変数とか。
ないもの
GitHub について
今回、初めてリリースページを作ってみてコンパイル済みのバイナリをホスティングしてみた。
みんなのGo言語 現場で使える実践テクニック [ 松木雅幸 ] |