初めて執筆させていただきます。

現在、サイバーエージェント新子会社の株式会社トルテでサーバーサイドエンジニアをしています。

ゆきちと申します。

トルテではいま現在絶賛カップリングサービスの新規開発中なのですが、言語選定の際に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アプリケーションに対する速度改善の実例とテクニックの話です。

実際のケースとし二つのレポジトリが紹介されました。

  • chocon – 複数のregion間の通信を高速化
  • gaurun – 高性能のプッシュ通知

上記どちらもプロキシサーバーとして動作します。すでにメルカリで本番投入されていて実際に稼動中、パフォーマンス的にも改善したとのこと。

プロキシサーバーとはサーバーであると同時にクライアントでもあるので、クライアントとしても最適化する必要がある。 その一例として、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はどちらもグローバルで使いまわすのがベターだそうです。

後半は、実例を基にいかにレイテンシ下げたかというお話に続きます。

chocon

  • 異なるリージョン間のレイテンシを下げるためのプロキシサーバー
  • メルカリは複数のリージョン(JP, US, UK)にホストされている
  • GCPの各地域のロードバランサーと接続する。マルチリーションのロードバランシング
  • GCLBによるコネクションの集約
  • リクエスト送信時にHOSTのヘッダーをみて流す
    • Host: HTTP hoge.com
    • Host: HTTPS hoge-secure.com

gaurun

  • とにかくたくさん処理できる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ファイルすら勝手につくってほしい…

database/sqlとコネクション

資料: http://www.slideshare.net/ssuser939b6b/database-sql-71406069?ref=https://golangtokyo.connpass.com/event/47328/presentation/

@Talos208 – 株式会社スプラウト

内容

  • DBをクローズすることはほぼない
  • Open/Closeのたび、コネクションコストが発生する
  • Openは起動時のみ、Closeは終了時のみ
  • 使いまわすことを前提にしよう
  • 現場で問題発生
    • sql.Open()はできる
    • DB.Ping()も成功する
    • DB.Query()を実行するとコネクションエラー
  • 問題の原因調査と解決
    • DBとの間にMaxscaleというMySQL用のロードバランサを置いていた
    • サーバーとMaxscaleはつながっていてpingが成功
    • MaxscaleとDBの接続がタイムアウト
    • ゆえにサーバーにタイムアウトが通知されない問題
    • Go1.6からの新API SetConnMaxLifetime() を導入することで解決

まとめ

私はあまり勉強会などに参加したことがないので、上から順に内容説明するレポートになってしまいました。

が、これからgolangに親しむにつれて、あーだこーだ発信する側のデベロッパーになっていきたいとおもいます。

いい刺激でした。またぜひ参加させていただきたいと思います。