Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rewrite in Finagle

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for iwagami iwagami
August 01, 2015
1.4k

Rewrite in Finagle

Avatar for iwagami

iwagami

August 01, 2015
Tweet

Transcript

  1. 歴史 • 2007年 twitter 開始 ◦ Rails のモノリシックなアプリ • 2009年

    クジラでまくり期 • 2011年 Ruby から Scala または Java に移行している ◦ https://blog.twitter.com/2011/finagle-a-protocol-agnostic-rpc- system ◦ http://readwrite.com/2011/07/06/twitter-java-scala ◦ ちなみにこのときは Scala 2.9.X
  2. finagle は何でないか? • Web Application Framework ではない ◦ Play Framework

    とは違う ◦ ネットワーク・分散システムのフレームワーク ◦ Play にはあるのにな〜が多々ある • ただの Netty のラッパではない ◦ netty.io ▪ あらゆるところで使われる非同期ネットワークライブラリ ◦ 豊富な謎機能 ▪ loadbalancer, serversets, stats,
  3. finagle とはなにか • Future, Service, Filter という中心教義 • それらを使ったスタック群 ◦

    finagle-core ◦ finagle-httpx ◦ finagle-thrift ◦ finagle-mysql ◦ finagle-redis ◦ finagle-memcached ◦ finagle-stats ◦ finagle-serversets
  4. Future • Future は将来手に入る値を持つオブジェクト〜 ◦ Scala 界では常識なので省略 • finagle で使うのは

    scala.concurrent.Future ではなく com. twitter.util.Future • scala.*.Future と同じ機能と考えてよい http://docs.scala- lang.org/ja/overviews/core/futures.html ◦ 同じものが2つあるがどうするつもりなのだろうか…
  5. Service Req 型をうけてFuture[Rep] を返す関数を持つクラス abstract class Service[Req, Rep] { def

    apply(req: Req): Future[Rep] // apply() はリクエストが来 た時に呼ばれる }
  6. 一番簡単なサーバ class Hello extends Service[Request, Response] { override def apply(request:

    Request): Future[Response] = { val resp = Response() resp.contentString = "Hello" Future(resp) } } object Foo extends App { def main = { Await.all( Httpx.serve("0.0.0.0:8080", new Hello)) }
  7. テスト class HelloTest in Specification { "Hellooooo" should { "reply

    hello" in { val res = Await.result(service(Request())) res.contentString must_== "Hello" } } }
  8. Filter abstract class Filter[RepI, RepO, ReqO, ReqI] { def apply(r:ReqI,

    next:Service[ReqO, RepI]): Future[RepO] } abstract class SimpleFilter[Rep, Rep] { def apply(r:Req, next:Service[Req, Rep]): Future[Rep] }
  9. Service と Filter の組み合わせ • andThen で Service と Filter

    とまとめられる val httpStatsFilter = new HttpxStatsFilter[HttpRequest](stats) val statsFilter = new StatsFilter[HttpRequest, HttpResponse](stats) val logging = new QueryLoggingFilter() val retry = new RetryingFilter[HttpRequest, HttpResponse](RetryPolicy.tries(3), new NullTimer) val httpServiceWithFilter: Service[HttpRequest, HttpResponse] = statsFilter andThen httpStatsFilter andThen retry andThen logging andThen mux
  10. もっと知りたい方は • ドキュメント ◦ http://twitter.github.io/finagle/guide/ • はじめに(自分のqiita記事) ◦ http://www.qiita. com/iwag@github/items/7d03292749d78c145112

    • SmartNews での事例と紹介 ◦ http://www.slideshare.net/ShigekazuTakei/jissenscala- 20150221-smartnews • 詳解 twitter のシステム ◦ http://www.slideshare.net/maruyama97/twitter-49709690
  11. 構成 elasticsearch cluster MySQL cluster zookeeper RPC (zeromq, msgpack) LB

    http 分散フ レーム ワークの ノード クエリ生成 部 (Scala)
  12. 元のシステム • 使ってるミドルウェア ◦ RPC:zeromq, msgpack, 一部 thrift ◦ 名前解決:zookeeper

    ◦ リクエストから内部クエリに変換部:Scala ◦ 検索:elasticsearch ◦ データストア:MySQL • 詳しい話は「ドワンゴ elasticsearch」で検索 • 代替 RPCフレームワークを探した
  13. 余談:libchan • 有力だったの docker/libchan ◦ 説明 http://yugui.jp/articles/881 • go の

    ネットワーク越しに使えるgoroutine • spdy, msgpack • きかなくなっちゃいましたね… ◦ 開発止まっている
  14. finagle 選択の理由 • zookeeper, thrift, Scala ◦ finagle が想定しているシステムに近い •

    内部クエリ生成部(Scala)を発展させてアプリにする • 真の理由: 社内がPlayだらけだったので違うのが使いた かった
  15. パフォーマンスアップ • QPS 20% up • JVM最高 • 教訓:C++ だからといって速いわけではない

    ◦ 本システムはレイテンシよりはスループットを重視しており、レイテン シを重視するアプリがだったら別の結果になったと思います
  16. おまけ:使っているライブラリ • finagle 6.24.0 ◦ 2015/08/01時点の最新は 6.25.0 ◦ finagle-httpx ◦

    finagle-mysql ◦ finagle-stats • twitter-server 1.10.0 • elasticsearch 1.4 • play-json 2.3.8 • specs 2 2.4.1 ◦ ちなみにfinagle推奨はscalatestなのでscalatest使ったほうがよい
  17. Scala最高 • C++比でいいところ ◦ IDE がある ▪ IntelliJ を使用 ◦

    コンパイルが速い ◦ デバッガがある ◦ ライブラリがたくさんある ◦ Scala書けるエンジニアはたくさんいる ▪ もちろんC++を書けるエンジニアもいます
  18. 例:リクエストID val service = … andThen appendId andThen …. andThen

    logging andThen render andThen search • HttpRequestのヘッダに X-Request-Id を追加 • search まではHttpRequest • logging と render ではヘッダからX-Request-Id フィールドから値を取得して • いい方法あったら教えて下さい
  19. DDD的な視点 • Service = ドメインサービス ◦ ドメインサービス多用には批判が多い ◦ aka ドメインモデル貧血症

    • 今回のシステムは”””検索”””しか提供していない ◦ ビジネスロジックは利用側に持ってもらっている • なのでDDDやるぞってところとは合わないかも…
  20. finagle-stats • 各種メトリクスを自動で採集 • twitter-server をいれていると /admin/metrics.json でメトリ クスが見れる •

    よさ ◦ 調査がやりやすい ◦ 障害の検知 ◦ レイテンシが見えるのでSLAの監視に用いる予定
  21. finatra twitter/finatra • sinatra ライクな finagle クローン • finagle にないものがある

    ◦ router ◦ mustache template ◦ logging ◦ twitter-server • finatra 2.0.0のリリース前で使わなかったけど今だったら 使ってもいいと思う(というか使った方がいい) • https://twitter.github.io/finatra/assets/FinatraSFScala.pdf
  22. Validation and mapping • Validationとモデルへのマッピングに Play の Forms が使い たい

    ◦ ほんとうに欲しかった… ◦ play-jsonみたいに独立して使うことができない • 結局機能の一部しか使わないだろうということで自作したが よくなかった
  23. メトリクスを観察 • /admin/metrics.json のメトリクスを観察 • MySQLクライアントのpool_waiterが増えるとロードが爆発 していた "clnt/192.168.122.184:3306/failure_accrual/revivals" : 0,

    "clnt/192.168.122.184:3306/load" : 8.0, "clnt/192.168.122.184:3306/loadbalancer/adds" : 1, "clnt/192.168.122.184:3306/loadbalancer/available" : 1.0, "clnt/192.168.122.184:3306/loadbalancer/load" : 91.0, "clnt/192.168.122.184:3306/loadbalancer/removes" : 0, "clnt/192.168.122.184:3306/loadbalancer/size" : 1.0, "clnt/192.168.122.184:3306/pending" : 7.0, "clnt/192.168.122.184:3306/pool_num_too_many_waiters" : 0, "clnt/192.168.122.184:3306/pool_num_waited" : 6410914, "clnt/192.168.122.184:3306/pool_size" : 64.0, "clnt/192.168.122.184:3306/pool_waiters" : 83.0, "clnt/192.168.122.184:3306/received_bytes" : 16468576884,
  24. 解決 • MySQL コネクションプールのコネクション数が少なかった ◦ 32 ⇒ 256 にして解決 ◦

    解決? ◦ 今はさばけているがこの負荷を超えても大丈夫なん?? ▪ 機材の関係で詳しく調べられず ▪ https://github.com/twitter/finagle/blob/develop/finagle- core/src/main/scala/com/twitter/finagle/pool/WatermarkPool .scala
  25. まとめ • finagle について紹介した ◦ 重要なのは Servie と Filter ◦

    finagle モナモナしてなくてわかりやすい • 検索システムの書き直しをした ◦ Scala は最高(C++ 比で) ◦ パフォーマンスも上がったしよかった • 不安はないわけではない ◦ ドキュメント ◦ 高負荷時の動作