Tomorrow Will Be A Better Day

Published

- 5 min read

uWSGIの統計情報をfluentd経由でNorikraに格納するまでのメモ

img of uWSGIの統計情報をfluentd経由でNorikraに格納するまでのメモ

検証背景

uWSGIには、統計情報を取得できるオプション設定がある。
The uWSGI Stats Server

  • uwsgitopで人間が見ながらチューニングするのは何だかんだで大変
  • uWSGIのJSONはネスト構造で複雑
  • Kibana化を見越して、InfluxDBでもよいかなと思ったけど、返ってくるJSONが複雑すぎた。
  • Norikraは複雑なJSONでもクエリを投げられるので、そこまで格納できれば監視&可視化に使うのはユーザが自由に行える

想定連携図

uWSGI_Norikra連携 各種ミドルウェアの連携は上記のイメージ。
なお、今回は全てローカル環境に構築した。

各ミドルウェアインストール

uwsgiインストール

   pip install uwsgi

td-agentインストール

Overview of Streaming Import by Treasure Agent (td-agent)【リンク切れ】を参照のこと。
今回はUbuntuで試したけど、おそらくCentOSなどでも連携可能な筈

Norikraインストール

Norikraのインストールは、JRubyの環境を整えるのが面倒くさかったので、
下記サイトのdockerイメージで準備した(doker環境の準備方法は割愛)
Fluentd と Norikra をもっとカジュアルに使おう

各種設定情報

uWSGI

uWSGI起動方法

   uwsgi --ini uwsgi_test.ini

こんな感じでuWSGIは起動できる。iniファイルの中身は以下の通り。

   [uwsgi]
http=0.0.0.0:8080
stats=/tmp/stat.sock
chmod-socket=666
max-requests=100
vacuum=true

本番運用時は、リバースプロキシにnginxなどを配置する方がよさげ。
fluentdのin_execでローカルから統計情報を取得するため、stats用の設定を入れてある。
ちなみに、uWSGIの統計情報は、以下の様なJSONで返ってくる。

  • uWSGIの統計情報JSON
   {
	"version": "2.0.11",
	"listen_queue": 0,
	"listen_queue_errors": 0,
	"signal_queue": 0,
	"load": 0,
	"pid": 4364,
	"uid": 0,
	"gid": 0,
	"cwd": "/root",
	"locks": [
		{
			"user 0": 0
		},
		{
			"signal": 0
		},
		{
			"filemon": 0
		},
		{
			"timer": 0
		},
		{
			"rbtimer": 0
		},
		{
			"cron": 0
		},
		{
			"rpc": 0
		},
		{
			"snmp": 0
		}
	],
	"sockets": [
		{
			"name": "127.0.0.1:49294",
			"proto": "uwsgi",
			"queue": 0,
			"max_queue": 100,
			"shared": 0,
			"can_offload": 0
		}
	],
	"workers": [
		{
			"id": 1,
			"pid": 5284,
			"accepting": 1,
			"requests": 5304,
			"delta_requests": 121,
			"exceptions": 0,
			"harakiri_count": 0,
			"signals": 0,
			"signal_queue": 0,
			"status": "idle",
			"rss": 0,
			"vsz": 0,
			"running_time": 1578271,
			"last_spawn": 1438499807,
			"respawn_count": 19,
			"tx": 551616,
			"avg_rt": 266,
			"apps": [],
			"cores": [
				{
					"id": 0,
					"requests": 5304,
					"static_requests": 0,
					"routed_requests": 0,
					"offloaded_requests": 0,
					"write_errors": 0,
					"read_errors": 0,
					"in_request": 0,
					"vars": []
				}
			]
		}
	]
}

td-agent

  • td-agent.conf
   <source>
    type exec
    format json
    command    python /etc/td-agent/uwsgi_stat.py
    run_interval 1s
    tag hoge
</source>
<match hoge>
    type    norikra
    norikra localhost:26571
    target_map_tag    true
</match>

今回、norikraはローカルに準備したので、この設定になっている。

  • in_execで実行するpythonスクリプト
   #!/usr/bin/env python
import subprocess
import json
cmd = '/usr/local/bin/uwsgi --connect-and-read /tmp/stat.sock'
try:
    result = subprocess.Popen(cmd, stderr=subprocess.PIPE, shell=True)
    return_json = result.communicate()[1]
    #JSON DATA Validation
    json.loads(return_json)
    #JSON DATA to fluent
    print return_json
except Exception as e:
    print '{"uwsgistat_errmsg":"' + str(e) + '"}'

Norikraで投げるクエリ例

これは運用しながら、適宜クエリ内容を見直すことになるかと。
harakiri_countやexceptionsとかも登録しておいた方がよさそう。

  • listen_queue状況の確認例
   select
  avg(listen_queue) as listen_queue_avg,
  avg(listen_queue_errors) as listen_queue_errors_avg
from
 hoge.win:time_batch(1 min)
  • 平均リクエスト時間の確認例
   select
  avg(workers.$0.avg_rt) as workers_avg_rt
from
 hoge.win:time_batch(1 min)
  • 物理メモリ消費量の確認例
   select
  avg(workers.$0.rss) as workers_rss
from
 hoge.win:time_batch(1 min)

結果

Norikraに格納された結果は、こんな感じ

Norikra画面

今回は、Norikraにデータを格納するまでに絞っているが、
あとはnorikra-clientを使って、ゴニョゴニョすれば色んなところで可視化できるかと。

まとめ

uWSGIの統計情報をfluentd経由でNorikraまで送信して、データを集計させることができた。
統計情報はfluentd経由で送信しているので、今後BigQueryやS3などに入れるといった要件にも対応できる筈