Push Provider Server with HTTP/2
Push Provider Server with HTTP/2
Yokohama\.(pm6?|go) #14
Takuya Yoshimura (takyoshi)
Takuya Yoshimura (takyoshi)
Lobi - Chat & Game Community
同じアカウントでログイン
APNS
おっ、届いた
1. 通知が飛ぶイベント
4. デバイストークンに対応する端末に通知を送信
2. Bさんのアカウントに紐づく
全端末のデバイストークンを取得
3. Bさんアカウントに紐づくすべての
デバイストークンに対して通知を送信
Aさん
Bさん
LobiのiOSへのPush Notification
LobiのiOSへのPush Notification
Push Notification
同じアカウントでログイン
APNS
おっ、届いた
1. Bさんに通知が飛ぶイベント
4. デバイストークンに対応する端末に通知を送信
2. Bさんのアカウントに紐づく
全端末のデバイストークンを取得
3. Bさんアカウントに紐づくすべての
デバイストークンに対して通知を送信
Aさん
Bさん
APNsについて
APNsについて
LobiのProviderの実装
レガシーAPNsの悩み
New APNs
New APNs
WWDC-2015 (8/26) 「What's New in Notifications」で発表
HTTP/2の通信
フィードバックサービスが不要になる
ちょうどその頃…
Go 1.6からhttp/2がはいる
Go 1.6が2月に出るらしい...
Gunfishへ
Gunfish
GunfishのArchitechture
server
supervisor
worker
sender
APNS
Lobi
Gunfish
: chan
: goroutine
: write
: read
①
②
③
④
⑤
⑥
⑦
WorkerとSender
Worker
Sender
Gunfishの起動
$ gunfish -c /etc/gunfish/config.toml
config.tomlの例
[provider]
port = 38003
worker_num = 4 # http/2クライアント接続を持つworkerの数
queue_size = 2000 # 最大同時リクエスト数
max_request_size = 1000 # POSTされるJSON配列の最大長
max_connections = 1000 # Gunfishが受け付ける最大コネクション数
[apns]
cert_file = "/path/to/cert_file.pem"
key_file = "/path/to/key_file.pem"
request_per_sec = 2000 # 1秒間にpushが送信される流量を設定
sender_num = 30 # http/2クライアントの送信の多重度
error_hook = "your_hook_cmd.sh" # errorレスポンス時のhook
Gunfishを使ったPush Notification
$ curl -X POST -H "Content-type: application/json" \
-d '[{"token":"83fa0eb8a743c118fca80b0136bfee0", \
"payload": {"aps": {"alert": "hoge", "sound": "default", "badge": 1}}}]' \
http://localhost:38103/apns/push
{"result": "ok"}
// POSTするjson配列の構造
[
{
"token": "apnsから発行されるデバイストークン",
"payload": "APNsが指定するPayload"
}
]
// Payloadの構造
{
"aps": {
"alert": {
"title": "foo",
"body": "bar"
},
"sound": "default",
"badge": 1
},
"option1": "任意のプロパティ"
}
Custom Error Response Handler
// ResponseHandlerインターフェース
type ResponseHandler interface {
OnResponse(*Request, *Response, error)
HookCmd() string
}
InitErrorResponseHandler(YourCustomErrorHandler{})
Graceful Restart
$ start_server --port 38003 --interval 5 -- gunfish -c /etc/gunfish/config.toml
Go言語でGraceful Restartをする
http://shogo82148.github.io/blog/2015/05/03/golang-graceful-restart/
Go言語でGraceful Restartをするときに取りこぼしを少なくする
http://shogo82148.github.io/blog/2015/11/23/golang-graceful-restart-2nd/
パフォーマンスチューニング
問題設定
設定項目
パフォーマンスチューニング
$ h2o -c conf/h2o/h2o.conf
$ wrk2 -t2 -c20 -d10 -s bench/scripts/err_and_success.lua -L -R25 http://localhost:38103
$ gunfish -c /etc/gunfish/config.toml -E test 2> gunfish.log
パフォーマンスチューニング
# wrk2の結果
#[Mean = 23.171, StdDeviation = 22.064]
#[Max = 160.384, Total count = 240]
#[Buckets = 27, SubBuckets = 2048]
----------------------------------------------------------
242 requests in 10.01s, 31.43KB read
Requests/sec: 24.18
Transfer/sec: 3.14KB
# logの中身を確認
38542 msg:"Succeeded to send a notification", type:worker # 送信成功
9067 msg:"Response queue is full.", type:sender # 処理が追いついていない場合のメッセージ
968 msg:"Catch error response.", type:"http/2-client" # エラーレスポンスを受け取る
506 msg:MissingTopic, type:worker
190 msg:BadDeviceToken, type:worker
95 msg:Unregistered, type:worker
8 msg:"Worker Queue size: 2083", type:
8 msg:"Succeeded to establish new connection.", type:worker
8 msg:"Response queue size: 2083", type:
1 msg:, type:
242リクエスト * 10 * 200 = 48400 を送信
38542 + 9067 + 506 + 190 + 95 = 48400
リリース
リリース
{
"pid": 19184,
"debug_port": 17889,
"uptime": 14,
"start_at": 1458276491,
"su_at": 0,
"period": 1,
"retry_after": 10,
"workers": 8,
"senders": 400,
"queue_size": 0,
"retry_queue_size": 0,
"workers_queue_size": 0,
"cmdq_queue_size": 0,
"retry_count": 0,
"req_count": 0,
"sent_count": 0,
"err_count": 0
}
{
"time": 1458276536967232300,
"go_version": "go1.6",
"go_os": "linux",
"go_arch": "amd64",
"cpu_num": 4,
"goroutine_num": 424,
"gomaxprocs": 4,
"cgo_call_num": 5,
"memory_alloc": 7276200,
"memory_total_alloc": 9109144,
"memory_sys": 13641976,
"memory_lookups": 104,
"memory_mallocs": 41548,
"memory_frees": 24228,
"memory_stack": 2228224,
"heap_alloc": 7276200,
"heap_sys": 8257536,
"heap_idle": 352256,
"heap_inuse": 7905280,
"heap_released": 0,
"heap_objects": 17320,
"gc_next": 8999555,
"gc_last": 1458276491942982000,
"gc_num": 2,
"gc_per_second": 0,
"gc_pause_per_second": 0,
"gc_pause": []
}
メモリが増え続ける問題
メモリが増え続ける問題
$ go tool pprof gunfish http://localhost:2412/debug/pprof/profile
(pprof) > top
(pprof) > list
メモリが増え続ける問題
net/http: http2 Transport retains Request.Body after request is complete, not GCed #14084
メモリが増え続ける問題
問題が解決されたので無事全台に投入
まとめ
まとめ