背景
AWSのALB(Application Load Balancer)を使いたかったんですけど、アプリがヘルスチェックにうまく反応しない。。
(ALBは正常のHTTPステータスコードとして、200 ~ 499の範囲で指定可能ですが、アプリが500を正常で応答する仕様 orz)
そしてアプリ側の改修して頂ける雰囲気はないので、ヘルスチェックを書きました。
サマリ
最終的に出来たコード
・ net/httpでヘルスチェック用webを起動
・ health check requestを受けたら、net.Listen でサービスが稼働しているポート20000番のポートをListenを試みる
・ Listen出来た場合(サービス停止) → 404を応答
or
・ Listen出来なかった場合(サービス稼働) → 200を応答
handler作成
ヘルスチェックのリクエスト受けた時に、特定ポート(今回は20000port)の Listen を試みる handler です。
listen出来たら、404 NotFoundで、Listen出来なかったら、200OKを応答する。
var (
svcProtocol = "tcp4"
svcPort = ":20000"
okMsg = "healthy"
ngMsg = "unhealthy..."
)
func checker(writer http.ResponseWriter, request *http.Request) {
// Try to listen on svcProtocol and svcPort.
listenchecker, err := net.Listen(svcProtocol, svcPort)
if err == nil {
// able to listen it... Which means, the service has stopped...ng
writer.WriteHeader(http.StatusNotFound)
fmt.Fprint(writer, ngMsg)
defer listenchecker.Close()
return
}
// not able to listen it. Which means, the service is working...ok!!!
fmt.Fprint(writer, okMsg)
return
}
handler登録してヘルスチェック応答web起動
ヘルスチェックのパスとポートを決めて、 handler を登録して web を起動
var (
healthPath = "/health"
healthPort = ":80"
)
func main() {
http.HandleFunc(healthPath, checker)
http.ListenAndServe(healthPort, nil)
}
windows 用にコンパイル
-ldflags="-H windowsgui"
はプロンプト起動させない様にするとか。
GOOS=windows GOARCH=386 go build -ldflags="-H windowsgui" health.go
AWS側
リスナー設定
ヘルスチェック設定
次にヘルスチェックの指定
ポイントはヘルスチェックのポートを トラフィックポート
ではなく、 上書き
を指定しヘルスチェック専用ポートを指定すること。
実験開始
まずは、windowsサーバでコンパイルした自作ヘルスチェックを起動
c:\>health.exe
ヘルスチェック(80)と、サービス(20000)共に起動(LISTEN)している
c:\>netstat -aon | find "80"
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 3552
c:\>netstat -aon | find "20000"
TCP 0.0.0.0:20000 0.0.0.0:0 LISTENING 3636
curlでヘルスチェック先を叩くと200が返ってくる。
~ ❯❯❯ curl -i http://ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com/health
HTTP/1.1 200 OK
Date: Sat, 30 Mar 2019 03:33:21 GMT
Content-Length: 7
Content-Type: text/plain; charset=utf-8
healthy
サービスを停止し、再度curlで確認するとちゃんと連動してるのが確認できた。
~ ❯❯❯ curl -i http://ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com/health
HTTP/1.1 404 Not Found
Date: Sat, 30 Mar 2019 03:34:17 GMT
Content-Length: 12
Content-Type: text/plain; charset=utf-8
unhealthy...