マイクロサービスアーキテクチャは、小さなAPIの組み合わせにより構築されます。一つのリクエスト対して複数のAPIが呼ばれるため、どのAPIにて障害が発生したか切り分けが複雑になりがちです。

そこで、今回はAPIの見える化を取り扱います。複雑に絡み合うAPI群をどのように簡単に扱えば良いかについて紹介します。

障害の切り分けと見える化技術の必要性

Windowsの標準ブラウザであるIEの開発者ツールに「UIの応答」という機能があります。HTMLのレンダリングやサーバへのリクエストが記録されます。とても便利なツールなのですが、あくまで収集できるのは「クライアントから見える情報」であり、サーバ側の情報は読み取れません。

サーバ側の動きの把握のために、例えばWeb3層モデルであれば、Webサーバ(Apache等)のアクセスログや、アプリケーションサーバ(Tomcat等)のサーバログ、業務ログを見て動きを把握します。実はシステムのスローダウンの8割はデータベースサーバのSQLクエリ部分であると言われることもあり、SQLの実行時間をOracleのAWR(Automatic Workload Repository)などを用いて確認するケースが多いです。

少し話が逸れましたが、これまでのWeb3層モデルの時代が過ぎ去り、APIエコノミーやクラウドの時代においては、システムを小さなサービスの組み合わせで構成するマイクロサービスアーキテクチャをベースにしていることが多く、さまざまな情報が「分散」します。そのため、クライアント・WebAP・DBの3層より更にシステムが多層化していきます。連続するAPIコールの中で複数の企業のAPIを経由していくことも珍しくありません。

そういったケースにおいては、「システムのスローダウンは誰の責任なのか?」という切り分けから入る必要が出てきます。KKD(勘と経験と度胸)でログの「あたり」をつけるのには限界があるでしょう。(さすがにこれまでも勘や度胸では無理ですが。。)

運用系のツールをシェルスクリプト等で作り込み、複数のアプリケーションサーバのログを集約したり、見やすい形に加工・整形されることもあります。

Zipkinを使った依存関係見える化

まずは、APIコールにおける各層の依存関係の見える化です。

各層の実行時間を一元管理するためのツールがZipkinです。

Zipkinは分散トレーシングシステムと呼ばれ、Twitterにより開発され、オープンソース化されています

インストールは、Dockerを使って以下の通り1コマンドで完了です。

$ docker run -d -p 9411:9411 openzipkin/zipkin

ブラウザから「http://localhost:9411/」にてZipkinサーバにアクセスします。時間や表示ログの上限等を指定し検索することができます。

Zipkinのトップ画面

トレースログが収集された状態で「Find Traces」をクリックすると以下のような形でサービス呼び出し階層が表示されます。「Depth」が「3」であり、赤枠部にてエラーが発生していることが一目瞭然です。

エラー箇所の特定

詳細については、上図の赤枠部をクリックしエラーの状況を確認することができます。

エラー状況の確認

Kibanaを使ったログ見える化

続いてログの見える化です。

Web3層モデルのシステムがスローダウンした場合、アプリケーションサーバとデータベースサーバそれぞれのサーバのログを確認するなど、ボトルネックになっている箇所の切り分けを行います。

一方、APIの組み合わせによるシステムの場合、APIが多層化することにより、Web3層モデルと比較してどうしてもログが散在することになり、障害の切り分けが困難になりがちです。

KibanaGrafanaなどを使ってログを見える化することが、こういった課題への解決のアプローチとなります。ログ収集のためにFluentdを使っても良いでしょう。

今回は、ElasticSearchにログを蓄積し、Kibanaでログを見える化する方法をご紹介しましょう。

「https://www.elastic.co/jp/products/elasticsearch」にアクセスし、「elasticsearch-5.2.0.zip」をダウンロードします。zipを解凍するとElasticSearchのインストール完了です。なお、brewを使ったインストールも可能です。

以下のコマンドにて起動します。9200番ポートをリスンしていることがわかります。

$ ./bin/elasticsearch
<中略>

[2017-02-14T16:17:38,164][INFO ][o.e.h.HttpServer         ] [j0cI0lb] publish_address {127.0.0.1:9200}, bound_addresses {[fe80::1]:9200}, {[::1]:9200}, {127.0.0.1:9200}

ブラウザから「http://localhost:9200/」にアクセスすると、以下の通りJSON形式でElasticSearchの情報が確認できます。

{
  "name" : "j0cI0lb",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "0Bf-C8faS4KMCx53DyPu-w",
  "version" : {
    "number" : "5.2.0",
    "build_hash" : "24e05b9",
    "build_date" : "2017-01-24T19:52:35.800Z",
    "build_snapshot" : false,
    "lucene_version" : "6.4.0"
  },
  "tagline" : "You Know, for Search"
}

ElasticSearchにデータをロードします。

「https://www.elastic.co/guide/en/kibana/current/tutorial-load-dataset.html」に記載の「shakespeare.json」「accounts.zip」「logs.jsonl.gz」をダウンロード・解凍し、マッピング定義を作成します。

以下はshakespeareの例です。

$curl -XPUT http://localhost:9200/shakespeare -d '
{
 "mappings" : {
  "_default_" : {
   "properties" : {
    "speaker" : {"type": "string", "index" : "not_analyzed" },
    "play_name" : {"type": "string", "index" : "not_analyzed" },
    "line_id" : { "type" : "integer" },
    "speech_number" : { "type" : "integer" }
   }
  }
 }
}
';

以下のコマンドにてインポートします。

$curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json
$curl -XPOST 'localhost:9200/shakespeare/_bulk?pretty' --data-binary @shakespeare.json
$curl -XPOST 'localhost:9200/_bulk?pretty' --data-binary @logs.jsonl

次に、「https://www.elastic.co/jp/products/kibana」にアクセスし、「kibana-5.2.0-darwin-x86_64.tar.gz」をダウンロードし、tar.gzを解凍します。

ElasticSearchとの連携を設定します。

「config/kibana.yml」を開き、「elasticsearch.url」の部分のコメントを外します。参考として、以下に該当箇所を「cat」コマンドで示します。これでインストールおよび設定完了です。

$ cat config/kibana.yml |grep elasticsearch.url
elasticsearch.url: "http://localhost:9200"

以下のコマンドにより、Kibanaを起動します。5601番ポートをリスンしていることがわかります。

$ ./bin/kibana
<中略>
 log   [07:41:53.118] [info][listening] Server running at http://localhost:5601

ブラウザから「http://localhost:5601/」にアクセスします。

以下の通りに入力し、「Create」ボタンをクリックすることで、Elasticsearchのインデックスを作成します。

logstash-*インデックスの作成

「logstash-*」のインデックスが作成されました。

logstash-*インデックス

次に、「shakes*」インデックスを追加します。上と同じ画面から、「Index conteins time-based events」チェックボックスをオフにし、「Index name or pattern」に「shakes*」を入力し、「Create」ボタンをクリックします。

shakes*インデックスの作成

「Visualize」メニューにて「Pie chart」を選択し、円グラフを作成します。

円グラフの作成

「Name」の下の「ba*」インデックスを選択します。

インデックスの選択

円グラフのベースが作成されました。「Split Slices」をクリックし、円グラフを構成する要素を選択します。

円グラフのベース

以下の通り入力し、「Add Range」をクリックします。

Rangeの設定

入力されたレンジに従って、円グラフが作成されました。

レンジ分割した円グラフ

複数のレンジを設定することもできます。以下の例では、「age」を2つめのレンジとして設定しています。

複数レンジ設定

*  *  *

今回は、ZipkinによるAPI依存関係の見える化と、Kibanaによるログの見える化を紹介しました。

個別のAPIの開発に注力していると、そもそも全体でどういったものを作っているのかを見渡せる有識者は少なくなりがちです。実運用になってから困ることのないよう、開発中から自担当APIのみならず、全体を見渡すよう意識していくと良いでしょう。

つまり、日々の業務でOutlook(メーラー)を立ち上げるのと同様、出社したら必ずZipkinやKibanaをブラウザから確認し、何か気になる点があれば、Teratermにて個別のサーバにログインしてログを確認するといった形です。こういった日々の積み重ねがトラブル時の勘所を醸成する基本となります。

次回は、Prometheusを使ったAPIの監視と、Swaggerを使ったAPIドキュメンテーションを紹介します。

著者紹介


正野 勇嗣 (SHONO Yuji ) - NTTデータ シニアスペシャリスト

2011年頃まで開発自動化技術のR&Dに従事。その後、開発プロジェクト支援やトラブルシューティング等に主戦場を移す。「ソースコード自動生成」に加えて、JenkinsやMaven等の「ビルド自動化」、JsTestDriverやSelenium等の「テスト自動化」を扱うようになり、多様化する開発自動化技術動向に興味。

最近は第四の自動化であるInfrastructure as Code等の「基盤自動化」の魅力に惹かれている。開発自動化技術に関する雑誌・記事執筆も行う。2児のパパ。