初めて執筆させていただきます。
現在、サイバーエージェント新子会社の株式会社トルテでサーバーサイドエンジニアをしています。
ゆきちと申します。
トルテではいま現在絶賛カップリングサービスの新規開発中なのですが、言語選定の際にgolangを採用しました。
go経験はまだ2,3ヶ月程度で浅いですが、原則シンプルでいい言語楽しいです。
golang.tokyo#3の抽選会に運良く当たったので、今回はそのレポートを書きたいと思います。今回のテーマは「パフォーマンス」。
Accelerating real applications in Go
https://talks.godoc.org/github.com/cubicdaiya/talks/2017/01/golang-tokyo.slide
久保達彦@cubicdaiya – 株式会社メルカリ
goアプリケーションに対する速度改善の実例とテクニックの話です。
実際のケースとし二つのレポジトリが紹介されました。
上記どちらもプロキシサーバーとして動作します。すでにメルカリで本番投入されていて実際に稼動中、パフォーマンス的にも改善したとのこと。
プロキシサーバーとはサーバーであると同時にクライアントでもあるので、クライアントとしても最適化する必要がある。 その一例として、golang純正のnet/httpの紹介。
http.Clientに使われるhttp.Transportをカスタマイズする際とくに重要なもの。 ネットワークのレイテンシを下げるために適切に設定する。
// MaxIdleConns controls the maximum number of idle (keep-alive)
// connections across all hosts. Zero means no limit.
MaxIdleConns int
総コネクション数
// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
// (keep-alive) connections to keep per-host. If zero,
// DefaultMaxIdleConnsPerHost is used.
MaxIdleConnsPerHost int
同一ホストに対するコネクション数
// IdleConnTimeout is the maximum amount of time an idle
// (keep-alive) connection will remain idle before closing
// itself.
// Zero means no limit.
IdleConnTimeout time.Duration
コネクションの寿命
なお、http.Clientとhttp.Transportはどちらもグローバルで使いまわすのがベターだそうです。
後半は、実例を基にいかにレイテンシ下げたかというお話に続きます。
- 異なるリージョン間のレイテンシを下げるためのプロキシサーバー
- メルカリは複数のリージョン(JP, US, UK)にホストされている
- GCPの各地域のロードバランサーと接続する。マルチリーションのロードバランシング
- GCLBによるコネクションの集約
- リクエスト送信時にHOSTのヘッダーをみて流す
Host: HTTP hoge.com
Host: HTTPS hoge-secure.com
- とにかくたくさん処理できるPUSH通知プロキシ
- concurrency (goroutine, channel)
- PUSH通知
- Push Notification Provider (for Smart phone)
- APNSやGCMにリクエストをプロキシ
- 日本からアメリカにPUSHを送ると遅かったりするのを解決する
- 30分以内に大量に遅れとのビジネス要件の指令 -> 高い平行性 = go
- POST
- クライアントには先に200出す
- channel based cueにenque push
- Workerがひたすらdecue
- pusher poolにたまったものが順に処理されていく
- 起動時にchannel作成
- ブロッキングのために、サイズ(capで)や使用量(lenで)を計測。グラフに出してモニタリング
- 秒間数千push送れる
まとめ
goでプロキシサーバー作るのいいよ性能でるよってお話でした。
goは標準パッケージが充実しているので、net/http使うだけでも十分にパフォーマンス発揮できます。
がしかし、クライアントとして使うにはもう少し考慮が必要とのことでした。
せっかくgoやってるのでgoroutineとかchannel駆使してgaurunみたいなプロジェクトやってみたいです。
#
第2部のkaneshinさんは風邪のためお休みでした。
トルテの開発が始まる前に一度飲み会でお会いして、いろいろ教えてくださったので楽しみにしていたのですが残念。
PERFORMANCE OPTIMIZATIONS
資料: http://slides.com/cafxx/perf-opts-devops
Carlo Alberto Ferraris@cafxx – 楽天パートナーズサービス
こちらは、English Speakerのカルロさんでした。
theory != practice
- 理論的には、理論と実践に違いはない。しかし、実践的にはそこに違いがある
- 理論から実践するのはそれほど単純なことではない
- 理論で人を説得するのは難しい
SHARE VALUES
- プロジェクトの間でもっとも大事なもの
- チーム全体でなにを大事にするか。セキュリティ or 機能。短期的安定 or 長期的安定
- みんなが納得して合意することが大切
- youtube.com/watch?v=n4Wf14e2jxQ-
コスト
- サーバより人員のほうが金かかっている
SCALE-OUT
- 12factor.net。従えば従うほど、スケールアウトだけでなく、携帯でき、うまく失敗できる
KISS
- 「Keep it Simple, Stupid.」
- codingは読む時間の方が多い。reading:writing = 10:1
- めっちゃ性能あげるために可読性悪くするか、可読性あげた結果性能が多少劣るかの選択。カルロさんは後者を推奨する
- making code easy to read makes it easier to write
その他
- Single Purpose
- 循環参照はしちゃだめ
- 分離せよ
- 可視性あげよ
- ログ、指標。動くものは計測せよ。
まとめ
- keep things simple
- measure everything
- optimize what matters
LTの部
以下さくさくっと。
Streamの扱い方
資料: https://slides.com/jun06t/deck
辻純平 – 株式会社CyberAgent AWA株式会社
内容
- できるだけStream使おうよ
- 画像をDLしていじりたい
- byte変換ではなく Stream
- ioutil.ReadAllですべて[]byteに変換するとそのぶんメモリを消費する
- 推測するな、計測せよ
- json.Unmarshalではなく、json.NewDecoder(Streamを使う)を使おう
- io.Copyを使おう
- bytes.Buffrerより、io.Pipeを使おう
- io.Reader, io.Writerを引数としているものは、Streamのまま扱う 対応している標準パッケージも多いので。
git-schemlextとddl-makerを使ったDB migrationの紹介
資料: https://speakerdeck.com/konboi/git-schemalex-and-ddl-maker-migration-number-golangtokyo
Ryosuke Yabuki@Konboi – 面白法人KAYAC高橋
内容
- rails方式が多い。
- 有名なgooseもそう
- migrationのたびファイル作成
- up/downでロールバック
- DSL
- コンフリクトしがちなので並行プロジェクトがあると困る
- soh335/git-schemalex
- バージョン管理にgit commit hashを使用
- ファイルの差分からSQLを発行してくれる
- DSL書かなくていい
- up/downはgitが担う
- schemaファイルすら勝手につくってほしい…
- ということでkayac/ddl-makerを作りました
database/sqlとコネクション
@Talos208 – 株式会社スプラウト
内容
- DBをクローズすることはほぼない
- Open/Closeのたび、コネクションコストが発生する
- Openは起動時のみ、Closeは終了時のみ
- 使いまわすことを前提にしよう
- 現場で問題発生
- sql.Open()はできる
- DB.Ping()も成功する
- DB.Query()を実行するとコネクションエラー
- 問題の原因調査と解決
- DBとの間にMaxscaleというMySQL用のロードバランサを置いていた
- サーバーとMaxscaleはつながっていてpingが成功
- MaxscaleとDBの接続がタイムアウト
- ゆえにサーバーにタイムアウトが通知されない問題
- Go1.6からの新API
SetConnMaxLifetime()
を導入することで解決
まとめ
私はあまり勉強会などに参加したことがないので、上から順に内容説明するレポートになってしまいました。
が、これからgolangに親しむにつれて、あーだこーだ発信する側のデベロッパーになっていきたいとおもいます。
いい刺激でした。またぜひ参加させていただきたいと思います。