Help us understand the problem. What is going on with this article?

【Nginx】サーバ状況監視ツール

More than 3 years have passed since last update.

こんにちは。

nginxのサーバー監視ツール。
リソースを継続に調べるツールがないくて、探しましたが、古い情報と、各種のソースファイルの場所に四苦八苦したので、
まとめます。

今回はバージョン固定なので、コピペすればOKかもしれません。

1.リソースを調べる

1.1 TOPコマンド

有名ですが、topコマンド習熟必要です。

$ top
top - 02:22:36 up  3:19,  2 users,  load average: 8.03, 6.75, 6.15
Tasks: 351 total,   4 running, 339 sleeping,   0 stopped,   8 zombie
Cpu(s): 23.9%us,  6.6%sy,  0.6%ni, 53.4%id, 15.4%wa,  0.0%hi,  0.1%si,  0.1%st
Mem:   5967892k total,  5337344k used,   630548k free,    21132k buffers
Swap:  2064380k total,  1304292k used,   760088k free,   528380k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
23978 aaa       20   0  402m  74m  49m R 49.0  1.3   0:03.18 php-cgi
23897 bbb       20   0  288m 104m  10m R 37.8  1.8   0:13.51 php-cgi
23869 cccc      20   0  250m  76m 8584 S 21.5  1.3   0:02.41 php-cgi
23976 dddd      20   0  274m  90m  10m S 20.2  1.6   0:02.01 php-cgi
23917 eeee      20   0  246m  72m 8308 S 18.9  1.2   0:02.44 php-cgi
23911 eeee      20   0  238m  63m 8140 D  5.6  1.1   0:00.59 php-cgi
23913 bbb       20   0  246m  71m 8144 D  5.6  1.2   0:00.66 php-cgi
23914 aaa       20   0  238m  63m 8140 D  5.6  1.1   0:00.60 php-cgi

1.2 vmstatコマンド

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 2  0      0 534592  44512 134928    0    0     5     1   32  132  1  0 99  0
 0  0      0 534568  44520 134920    0    0     0    12   32   75  0  0 100  0
 0  0      0 534568  44520 134928    0    0     0     0   27   58  0  1 99  0

1.3 dstatコマンド

$ dstat -Tclmdrn
--epoch--- ----total-cpu-usage---- ---load-avg--- ------memory-usage----- -dsk/total- --io/total- -net/total-
  epoch   |usr sys idl wai hiq siq| 1m   5m  15m | used  buff  cach  free| read  writ| read  writ| recv  send
1393744402|  1   0  99   0   0   0|   0 0.01 0.05| 295M 43.5M  132M  518M|4782B  912B|0.24  0.09 |   0     0
1393744403|  0   0 100   0   0   0|   0 0.01 0.05| 295M 43.5M  132M  518M|   0     0 |   0     0 | 396B 1708B
1393744404|  0   0 100   0   0   0|   0 0.01 0.05| 295M 43.5M  132M  518M|   0     0 |   0     0 | 132B  580B
1393744405|  0   0 100   0   0   0|   0 0.01 0.05| 295M 43.5M  132M  518M|   0     0 |   0     0 | 132B  580B
1393744406|  0   0 100   0   0   0|   0 0.01 0.05| 295M 43.5M  132M  518M|   0     0 |   0     0 | 132B  580B

2. Nginxの接続状況確認

2.1 stub_statusが利用できるか確認。

"HttpStubStatusModule"モジュールを有効にします。
有効化されているかの確認をします。

$ nginx -V
nginx version: nginx/1.2.1
TLS SNI support enabled
configure arguments:・・・ --with-http_stub_status_module ・・・

2.2 Configファイルを作ります。

以下のファイルは、http{ }の中にserver{}が入っていることがポイントです。

$ cd /etc/nginx/
$ cat nginx.conf
・・・
http {
    include       mime.types;
    default_type  application/octet-stream;
・・・
    include /etc/nginx/conf.d/*.conf;
}

$ cd conf.d
$ cat nginx_status.conf
server {
    listen 80;
    server_name ap7;

    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

allow 127.0.0.1 とすることで,サーバ内部からしか見れないようにします

127.0.0.1のローカルサーバーが見えるようにします。

$ cat /etc/hosts
127.0.0.1 localserver

2.3 サーバーのステータスを取得する方法

$ curl http://localserver/nginx_status
Active connections: 25 
server accepts handled requests
 6261 6261 9336 
Reading: 0 Writing: 6 Waiting: 19 

見ての通り、縦型に表示です。これはvmstatみたいな1行タイプがいいので、ツールで変更します。

$ ./nginxstats.py http://localserver/nginx_status
Conn     Conn/s     Request/s  Read  Write Wait 
-------- ---------- ---------- ----- ----- -----
      33       1.33       2.93     0     6    27
      19       2.00       3.73     0     5    14

2.4 監視ツールの取得

場所に困りましたが、googleにありました。

$ wget https://code.google.com/p/timoseven/source/browse/trunk/python/nginxstats.py?r=717
・・・
$ chmod +x nginxstatus.py
$ cat nginxstatus.py
#!/usr/bin/env python

import re
import sys
import time
import urllib

TIME_SLEEP = 30


def get_data(url):
    data = urllib.urlopen(url)
    data = data.read()
    result = {}

    match1 = re.search(r'Active connections:\s+(\d+)', data)
    match2 = re.search(r'\s*(\d+)\s+(\d+)\s+(\d+)', data)
    match3 = re.search(r'Reading:\s*(\d+)\s*Writing:\s*(\d+)\s*'
        'Waiting:\s*(\d+)', data)
    if not match1 or not match2 or not match3:
        raise Exception('Unable to parse %s' % url)

    result['connections'] = int(match1.group(1))

    result['accepted'] = int(match2.group(1))
    result['handled'] = int(match2.group(2))
    result['requests'] = int(match2.group(3))

    result['reading'] = int(match3.group(1))
    result['writing'] = int(match3.group(2))
    result['waiting'] = int(match3.group(3))

    return result


def main():
    url = sys.argv[1]
    prev = None
    next = time.time() + TIME_SLEEP
    total = None
    count = 0
    try:
        while True:
            data = get_data(url)
            if prev:
                result = print_stat(prev, data)
                if total is None:
                    total = list(result)
                else:
                    for i, v in enumerate(result):
                        total[i] += v
                count += 1
            else:
                print_head()
            prev = data
            time.sleep(next - time.time())
            next += TIME_SLEEP
    except KeyboardInterrupt:
        if total:
            print_foot(total, count)


def print_foot(total, count):
    total = [v / count for v in total]
    print '-------- ---------- ---------- ----- ----- -----'
    print '%8d %10.2f %10.2f %5d %5d %5d' % tuple(total)


def print_head():
    print '%-8s %-10s %-10s %-5s %-5s %-5s' % (
        'Conn', 'Conn/s', 'Request/s', 'Read', 'Write', 'Wait')
    print '-------- ---------- ---------- ----- ----- -----'


def print_stat(prev, data):
    result = (
        data['connections'],
        float(data['accepted'] - prev['accepted']) / TIME_SLEEP,
        float(data['requests'] - prev['requests']) / TIME_SLEEP,
        data['reading'],
        data['writing'],
        data['waiting'])

    print '%8d %10.2f %10.2f %5d %5d %5d' % result
    return result


if __name__ == '__main__':
    main()

コピペしてもOKです。

envのパスを確認します。

$ ls /usr/bin/env
/usr/bin/env

pythonのパスが張れているか確認します。

$ which python
/usr/bin/python

3. リクエスト制限!

細かい設定の項目の説明はこちらを参照
http://server-setting.info/centos/nginx-limit_rate.html

limit_req_zone、limit_req を設定します。

ポイントは、毎秒いくつのリクエスト数、待ち行列の場合に、制限をかけるかです。

3.1 limit_req_zone

limit_req_zone $binary_remote_addr  zone=[name]:[size] rate=[rate];

# $binary_remote_addr - 公式でこの変数名
# [name] - ゾーン名(公式では"one"という名称を使っている)
# [size] - ゾーンの最大サイズ
# [rate] - 毎秒/分/時 の最大リクエスト数。この数を超えると503を返す

# httpディレクティブ

3.2 limit_req

limit_req zone=[name] burst=[burst];

# [name] - limit_req_zone で設定したnameを設定
# [burst] - limit_req_zoneの[rate]で設定した上限を超えた場合の待ち行列数。ここを設定しないと、[rate]を超えた瞬間すぐに503になってしまう。
# ※ この数値を超えたら503になる

# http、server、locationディレクティブ

3.3 実際に設定

大元のトップファイルに追記です。

# limit_req_zoneはhttpディレクティブに設定

http {
    limit_req_zone $binary_remote_addr  zone=one:10m rate=50r/s;
    # 毎秒50リクエスト

    server {
        listen 80;
        server_name hogehoge.com;
        limit_req zone=one burst=100;
    }
}

4. まとめ

dstatでリソース/IO状況を見て、nginxstats.pyで同時接続数を見ながら、nginxのリソース管理をしてみてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした