ZipkinのReadme読んでる(その2、残り)(Jugemより移植)

Posted by johtani on Saturday, June 16, 2012

目次

「鉄は熱いうちに打て」ということで、残りも勢いでメモ。 まだ、見直しとかしてない状態なのでおかしいところとかありますが。。。 図とか入れるのはまた今度。

 Transport(転送)


 ZipkinとHadoopに異なるサービスからのトレースを送信するのにScribeを利用します。
 ScribeはFacebookにより開発されました。
 システムの各サーバで実行できるデーモンとして作成されています。
 ログメッセージをListenし、カテゴリごとのcorrectレシーバーに配送します。

 Zipkin collector daemon


 トレースデータがZipkinコレクターデーモンに配送されたらvalidかどうかをチェックしてから保管し、インデックスを作成します。

 Storage


 ストレージにはCassandraを選びました。
 スケーラブルで、柔軟なスキーマをもっており、Twitter内部で大変使われています。
 このコンポーネントをプラガブルにしようと試みましたが、困難なため、ここでは公開しません。

 Zipkin query daemon


 保存、インデックスされたデータを探す方法が必要です。

 クエリーデーモンはユーザに対して簡単なThriftAPIを公開しており、トレースを探すことが可能です。Thrift fileを見て下さい。

 UI


 多くのユーザはUI経由でデータにアクセスします。

 VisualizeにD3を利用したRailsアプリケーションです。  UIの認証は実装していないことに注意してください。

モジュール  Zipkin内部のモジュール関連図

##インストール___  Cassandra


 ZipkinはCassandraをストレージにしています。Cassandraクラスタが必要になります。
 1. Cassandraサイトを参考にしてクラスタを構築してください。
 2. Zipkin Cassandraスキーマを利用します。つぎのコマンドでスキーマが作成できます。

bin/cassandra-cli -host localhost -port 9160 -f zipkin-server/src/schema/cassandra-schema.txt

 Zookeeper


 Zipkinは協調のためにZooKeeperを利用します。
 これは、保存すべきサーバをサンプルレートで決定し、サーバを登録します。?
 1. ZooKeeperのサイトを参考にインストールしてください。

 Scribe


 Scribeはトレースデータを配送するのに利用するロギングフレームワークです。
 ネットワーク保存先としてZipkinコレクターデーモンを指定する必要があります。

 Scribeの設定は次のようにします。

<store&gt;
  category=zipkin
  type=network
  remote_host=zk://zookeeper-hostname:2181/scribe/zipkin
  remote_port=9410
  use_conn_pool=yes
  default_max_msg_before_reconnect=50000
  allowable_delta_before_reconnect=12500
  must_succeed=no
</store&gt;

 注意:上記設定は、カテゴリーにより送信ホストを見つけるためにZooKeeperを利用するサポートのScribeのTwitterバージョンを使用する方法です。
 コレクターのためのDNSエントリーを利用したりもできます。

 Zipkinサーバ  ZipkinサーバはScala 2.9.1SBT 0.11.2そしてJDK6で開発しました。


 1. git clone https://github.com/twitter/zipkin.git
 2. cd zipkin
 3. cp zipkin-scribe/config/collector-dev.scala zipkin-scribe/config/collector-prod.scala
 4. cp zipkin-server/config/query-dev.scala zipkin-server/config/query-prod.scala
 5. Modify the configs above as needed. Pay particular attention to ZooKeeper and Cassandra server entries.
 6. bin/sbt update package-dist (This downloads SBT 0.11.2 if it doesn't already exist)
 7. scp dist/zipkin*.zip [server]
 8. ssh [server]
 9. unzip zipkin*.zip
10. mkdir -p /var/log/zipkin
11. zipkin-scribe/scripts/collector.sh -f zipkin-scribe/config/collector-prod.scala
12. zipkin-server/scripts/query.sh -f zipkin-server/config/query-prod.scala

 SBTでコレクターとクエリサービスを起動します。
 Scribeコレクターサービスの起動方法は次の通り。

bin/sbt 'project zipkin-scribe' 'run -f zipkin-scribe/config/collector-dev.scala'

 クエリサービスは次の通り

bin/sbt 'project zipkin-server' 'run -f zipkin-server/config/query-dev.scala'

 Zipkin UI


 UIはRails3アプリです。
 1. 設定をZooKeeperサーバでアップデートします。これはクエリデーモンを見つけるのに利用します。
 2. Rails3アプリケーションサーバにデプロイします。テストの場合は次のようにすることもできます。

bundle install &amp;&amp; bundle exec rails server.

 zipkin-tracer gem


 zipkin-tracer gemをトレースしたいRailsアプリケーションにRack Handlerで追加します。
 config.ruにつぎの記載をします。

  use ZipkinTracer::RackHandler
  run <YOUR_APPLICATION>

 もし、アプリケーションのstatic assetsがRailsで提供されれば、リクエストがトレースされます。

## Running a Hadoop job



 ScribeからHadoopにログを保存する設定をすることも可能です。
 これをすると、Zipkin自身でオンザフライで簡単に作れないデータから様々なレポートが作成可能です。

 ScalaでHadoopのジョブをかけるScaldingというライブラリを利用します。

```

 1. Hadoopジョブを実行するためのfatなjarを作成します。  2. scald.rbをjarをコピーしたいホスト名とjobを実行するホスト名に書き換えます。  3. 必要なら、scald.rbのjarファイルのバージョンを更新します。  4. scald.rbスクリプトを利用してジョブを実行できます。

./scald.rb –hdfs com.twitter.zipkin.hadoop.[classname] –date yyyy-mm-ddThh:mm yyyy-mm-ddThh:mm –output [dir]


##計測ライブラリの利用方法<hr>

 計測のためのライブラリとプロトコルがちょっとだけあります。  しかし、もっと計測するための役に立つものを望んでいます。  開始する前にトレースデータがどんな構造なのかを知る必要があります。

  ・Annotation - 値、タイムスタンプ、ホストを含みます。   ・Span - 特定のRPCに相当するAnnotationの集合   ・Trace - あるルートSpanにぶら下がるSpanの集合

 Zipkinに送信するトレースデータです。

 これらの詳細な記述は[こちら](https://github.com/twitter/zipkin/blob/master/zipkin-thrift/src/main/thrift/zipkinCore.thrift)を見て下さい。

 その他にトレースデータの重要なものは、トレースされたサービス間でやり取りされる情報である、軽量なヘッダーです。  トレースヘッダは次のものから構成されます。

 ・Trace Id - トレース全体のID  ・Span Id - 個々のリクエストのID  ・Optional Parent Span Id - このリクエストが他のリクエストの一部として生成されたら付与される  ・Sampled boolean - トレースすべきかどうかを表すフラグ

 データタイプについて、理解したので、どのように計測が行われるかを順をおってみてみましょう  例はFinagleのHTTPがどのようにトレースされるかを示しています。  他のライブラリやプロトコルはもちろん、異なりますが、基本的な部分は一緒です。

<b> サーバサイド</b>
 1. 到達したリクエストのトレースヘッダー存在するかどうかを調べます。存在すれば、なら、このリクエストに対して関連するIDとします。トレースヘッダーがなければ、サンプリング対象かどうかを決めて、新しいTrace Id、Span Idを生成します。参考には[HttpSererTracingFilter](https://github.com/twitter/finagle/blob/master/finagle-http/src/main/scala/com/twitter/finagle/http/Codec.scala)を見て下さい。

 2. もし、現在のリクエストがサンプリングされる場合、サービス名、ホスト名、スパン名(例えば、http get/put)、その他のAnnotationのような情報を集めます。
  リクエスト受信時には「server received」というAnnotationを生成し、処理が終了して結果を返すときに「server send」というAnnotationを生成します。
  参考には[HttpServerTracingFilter](https://github.com/twitter/finagle/blob/master/finagle-http/src/main/scala/com/twitter/finagle/http/Codec.scala)を見てください。

 3. 生成されたトレースデータはServerBuilderにより設定されたトレーサーに渡されます。
  デバッグのためのConsoleTracerが例としてありますが、ZipkinTracerになります。
  トレースデータを[ZipkinTracer](https://github.com/twitter/finagle/tree/master/finagle-zipkin)が受け取った時、Span Idにより集約されます。

 4. ZipkinTracerが"end of span"イベント("server received"アノテーションやタイムアウトのような)を受け取ると、Thrift構造としてデータを集約してScribeに送ります。もし、そのようなイベントが発生しない場合、ZipkinTracerはいつかそのデータを送信します???おかしい?。データ送信のための他の方法も追加します。
 ThriftやScribeのようなものですが、JSONやHttpかもしれません?

<b> クライアントサイド</b>
 1. リクエストを送る前にそれがトレースの一部かどうかをチェックします。
  サーバで利用されているとします。 
  サーバは、リクエストを処理してすでに付与されているトレースIDを割り当てます。
  トレースIDを再利用しますが、この新しいリクエストには新しいスパンIDを生成します。
  また、親のスパンIDが存在すれば、前のスパンIDに設定します。
  [ここ(TracingFilter)](https://github.com/twitter/finagle/blob/master/finagle-core/src/main/scala/com/twitter/finagle/tracing/TracingFilter.scala)や[ここ(Trace)](https://github.com/twitter/finagle/blob/master/finagle-core/src/main/scala/com/twitter/finagle/tracing/Trace.scala)が参考になります。

 2. サーバサイドと同様に、送信されるHttpリクエストにトレースヘッダーを追加するための[HttpClientTracingFilter](https://github.com/twitter/finagle/blob/master/finagle-http/src/main/scala/com/twitter/finagle/http/Codec.scala)があります。

 3. リクエスト送信前の「client send」やサーバからの返信を受信した「client receive」のようなアノテーションを生成します。

 4. サーバサイドと同様に、データがZipkinにデータを送るZipkinTracerに到達します。


comments powered by Disqus