limit_req_zone - неправильно ограничивается скорость

cronfy cronfy на gmail.com
Сб Сен 25 11:56:43 MSD 2010


Здравствуйте.

Пытаюсь настроить ограничение запросов c IP в секунду с помощью
limit_req_zone, но почему-то реальная скорость запросов получается
гораздо ниже, чем указано в конфиге. Пример:

    limit_req_zone  $binary_remote_addr  zone=test_limit:30m   rate=5r/s;

    server {
        listen 127.0.0.1:80;
        server_name  testconn.loc;
        recursive_error_pages on;

        error_page 402 = @backend;
        location / {
                return 402;
        }

        location @backend {
            limit_req   zone=test_limit  burst=100;
            limit_req_log_level error;
            proxy_set_header   Host             $host;
            proxy_pass         http://127.0.0.1:31023$request_uri;
        }
    }

Тест 1.
Комментируем limit_req:
# ab -n 1000 http://testconn.loc/helloworld.php
Requests per second:    889.42 [#/sec] (mean)

Тест 2.
Возвращаем limit_req в @backend (сейчас rate=5r/s):
# ab -n 10 http://testconn.loc/helloworld.php
Requests per second:    2.01 [#/sec] (mean)

В error.log 5 записей:

2010/09/25 11:36:32 [warn] 63999#0: *75741 delaying request, excess:
0.990, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:36:33 [warn] 63999#0: *75765 delaying request, excess:
0.990, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:36:34 [warn] 63999#0: *75780 delaying request, excess:
0.990, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:36:35 [warn] 63999#0: *75792 delaying request, excess:
0.995, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:36:36 [warn] 63999#0: *75807 delaying request, excess:
0.995, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"


По идее уже неправильно: при 5r/s должен задерживать на 0.2, а
почему-то сразу выставляется 0.9

Тест 3.
Ставим rate=100r/s, количество запросов 50
# ab -n 50 http://testconn.loc/helloworld.php
Requests per second:    2.34 [#/sec] (mean)

Cитуация почти не меняется :(
в логе 25 записей вида

2010/09/25 11:41:53 [warn] 71858#0: *79943 delaying request, excess:
0.800, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:41:54 [warn] 71858#0: *79958 delaying request, excess:
0.700, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:41:55 [warn] 71858#0: *79979 delaying request, excess:
0.900, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:41:55 [warn] 71858#0: *80002 delaying request, excess:
0.800, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:41:56 [warn] 71858#0: *80023 delaying request, excess:
0.900, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"


Тест 4:
Ставим rate=500r/s
# ab -n 50 http://testconn.loc/helloworld.php
Requests per second:    4.73 [#/sec] (mean)

В логе 21 запись:

2010/09/25 11:44:31 [warn] 75535#0: *82655 delaying request, excess:
0.500, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:44:31 [warn] 75535#0: *82665 delaying request, excess:
0.500, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:44:32 [warn] 75535#0: *82676 delaying request, excess:
0.500, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"

Тест 5:
Ставим rate=1000r/s, увеличиваем количество запросов до 200
# ab -n 200 http://testconn.loc/helloworld.php
Requests per second:    88.61 [#/sec] (mean)

В логе 2 записи:
2010/09/25 11:50:50 [warn] 83559#0: *2038 delaying request, excess:
1.000, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"
2010/09/25 11:50:51 [warn] 83559#0: *2141 delaying request, excess:
1.000, by zone "test_limit", client: 127.0.0.1, server: testconn.loc,
request: "GET /helloworld.php HTTP/1.0", host: "testconn.loc"



С чем может быть связано такое поведение? Заметил проблему на
nginx/0.8.50, тестировал на nginx/0.8.34. FreeBSD 7.3.


-- 
// cronfy



Подробная информация о списке рассылки nginx-ru