Производительность GridFS

// Сентябрь 23rd, 2011 // NoSQL, Веб-разработка, Виртуализация

В этой заметке я хочу разместить свой перевод замечательной статьи про GridFS. Задача хранения и раздачи файлов в кластерной среде сегодня с развитием облачных вычислений приобретает всё большую актуальность.

Задача

Хранить и раздавать статические файлы (картинки, стили и скрипты) на кластере из нескольких серверов.

Возможные решения

NFS, Lustre, SMB (Samba), Hadoop, DRBD (сетевой RAID). Из всего множества решений раньше мне больше всего импонировал Hadoop, однако попробовать его руки так и не дошли. А тут на глаза недавно попался бенчмарк про GridFS, о котором я рассказывал в предыдущем посте.

Что такое GridFS?

GridFS — это GridFS это маленькая но очень полезная возможность в MongoDB, которая позволяет хранить файлы любых видов и размеров в самой БД, используя при этом преимущества шардинга и репликации. Однако, раз файлы в БД, а не в ФС, как же получить доступ к ним, как раздавать файлы клиентам? Есть несколько вариантов и ниже мы их рассмотрим.

На данный момент есть 3 возможности:

  • Использовать «низкоуровневый» скрипт-обработчик, как Rack скрипт или Rails Metal handler для раздачи файлов из БД.
  • Подмонтировать файлы из БД к ФС с помощью, например,  gridfs-fuse, и читать файлы из ФС напрямую.
  • Использовать модуль для веб-сервера, например nginx-gridfs, который при получении запроса будет обращаться напрямую к MongoDB.

Второй вариант я рассмотрел в предыдущей статье, теперь займёмся третьим :-)

ФС через Apache

[chris@polaris conf]# ab -n 50000 -c 10 http://advice/images/embed/alliance-60.png

Server Software:        Apache/2.2.13
Server Hostname:        advice
Server Port:            80

Document Path:          /images/embed/normal_alliance-60.png
Document Length:        31596 bytes

Concurrency Level:      10
Time taken for tests:   1.904 seconds
Complete requests:      5000
Failed requests:        0
Write errors:           0
Total transferred:      159463760 bytes
HTML transferred:       158043192 bytes
Requests per second:    2625.37 [#/sec] (mean)
Time per request:       3.809 [ms] (mean)
Time per request:       0.381 [ms] (mean, across all concurrent requests)
Transfer rate:          81767.87 [Kbytes/sec] received

Connection Times (ms)
 min  mean[+/-sd] median   max
Connect:        0    1   0.4      1       4
Processing:     1    3   0.5      3       6
Waiting:        0    1   0.4      1       4
Total:          2    4   0.4      4       8

Percentage of the requests served within a certain time (ms)
 50%      4
 66%      4
 75%      4
 80%      4
 90%      4
 95%      4
 98%      5
 99%      5
 100%      8 (longest request)

Довольно быстро, как мы и ожидали. Теперь попробуем с nginx.

ФС через nginx

[chris@polaris conf]# ab -n 50000 -c 10 http://advice:81/images/embed/normal_alliance-60.png

Server Software:        nginx/0.8.33
Server Hostname:        advice
Server Port:            81

Document Path:          /images/embed/normal_alliance-60.png
Document Length:        31596 bytes

Concurrency Level:      10
Time taken for tests:   7.623 seconds
Complete requests:      50000
Failed requests:        0
Write errors:           0
Total transferred:      1590513618 bytes
HTML transferred:       1579863192 bytes
Requests per second:    6559.31 [#/sec] (mean)
Time per request:       1.525 [ms] (mean)
Time per request:       0.152 [ms] (mean, across all concurrent requests)
Transfer rate:          203763.10 [Kbytes/sec] received

Connection Times (ms)
 min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       9
Processing:     1    1   0.4      1      11
Waiting:        0    0   0.1      0       9
Total:          1    1   0.5      1      12

Percentage of the requests served within a certain time (ms)
 50%      1
 66%      1
 75%      1
 80%      2
 90%      2
 95%      2
 98%      3
 99%      3
 100%     12 (longest request)

Nginx рулит, 6500 запросов в секунду.

GridFS через nginx-gridfs

[chris@polaris conf]# ab -n 5000 -c 10 http://advice:81/images/gfs/uploads/user/avatar/4b7b2c0e98db7475fc000003/normal_alliance-60.png

Server Software:        nginx/0.8.33
Server Hostname:        advice
Server Port:            81

Document Path:          /images/gfs/uploads/user/avatar/4b7b2c0e98db7475fc000003/normal_alliance-60.png
Document Length:        31596 bytes

Concurrency Level:      10
Time taken for tests:   4.613 seconds
Complete requests:      5000
Failed requests:        0
Write errors:           0
Total transferred:      158580000 bytes
HTML transferred:       157980000 bytes
Requests per second:    1083.88 [#/sec] (mean)
Time per request:       9.226 [ms] (mean)
Time per request:       0.923 [ms] (mean, across all concurrent requests)
Transfer rate:          33570.65 [Kbytes/sec] received

Connection Times (ms)
 min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       1
Processing:     1    9   4.7      9     103
Waiting:        1    9   4.7      9     102
Total:          2    9   4.7      9     103

Percentage of the requests served within a certain time (ms)
 50%      9
 66%      9
 75%      9
 80%      9
 90%      9
 95%      9
 98%      9
 99%     11
 100%    103 (longest request)

Определённо ниже, однако всё ещё внушающие. 1051 запросов в секунду это более чем достаточно для большинства целей, особенно, с фасадом в виде CDN :-)

Rails Metal handler

Основное преимущество Rails metal handler в том, что о простой. Не надо ничего перекомпилировать, просто добавьте его в свой проект. Вот его результаты:

[chris@polaris nginx-gridfs]$ ab -n 250 -c 4  http://advice/images/gfs/uploads/user/avatar/4b7b2c0e98db7475fc000003/normal_alliance-60.png

Server Software:        Apache/2.2.13
Server Hostname:        advice
Server Port:            80

Document Path:          /images/gfs/uploads/user/avatar/4b7b2c0e98db7475fc000003/normal_alliance-60.png
Document Length:        31596 bytes

Concurrency Level:      4
Time taken for tests:   4.646 seconds
Complete requests:      250
Failed requests:        0
Write errors:           0
Total transferred:      7960000 bytes
HTML transferred:       7899000 bytes
Requests per second:    53.81 [#/sec] (mean)
Time per request:       74.338 [ms] (mean)
Time per request:       18.585 [ms] (mean, across all concurrent requests)
Transfer rate:          1673.10 [Kbytes/sec] received

Connection Times (ms)
 min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       1
Processing:    15   74  75.6     34     287
Waiting:        0   72  75.8     30     276
Total:         15   74  75.6     34     288

Percentage of the requests served within a certain time (ms)
 50%     34
 66%     39
 75%    139
 80%    192
 90%    201
 95%    210
 98%    239
 99%    245
 100%    288 (longest request)

К сожалению 53 запроса в секунду — не самый привлекательный результат.

Сравнение решений

Решение Requests/second % Apache FS % Nginx FS % Nginx GridFS % Apache Ruby
Filesystem через Apache 2625.37 40.03% 242.22% 4,878.96%
Filesystem через Nginx 6559.31 249.84% 605.17% 12,189.76%
GridFS через nginx module 1083.88 41.28% 16.52% 2014.27%
Rails metal handler через Passenger 53.81

Если вы хотите перейти от хранения файлов в локальной ФС, то GridFS это приемлемое решение. Причина использования GridFS состоит в том, что вы получаете потрясающую гибкость и масштабируемость из коробки в авто-реплицируемой шардируемой отказоустойчивой (сколько прилагательных :) ) среде. Но естественно расплачиваетесь производительностью на отдельно-взятом узле, при этом однако есть возможность довольно просто увеличивать производительность всего кластера.

Ссылки

http://www.coffeepowered.net/2010/02/17/serving-files-out-of-gridfs/

http://www.slideshare.net/chrisjpowers/grid-fs

Share

Спасибо!


Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:


3 Responses to “Производительность GridFS”

  1. unic:

    Мне больше всего оказалась полезным информация про apache benchmark tool :-) Сам по себе ab не дает нагрузку на сервер? Можете поделиться способами тестирования производительности веб-приложений? С достоинствами/недостатками было бы вообще замечательно.

    • google.com Андрей Токарчук:

      Ну если он запускается с другого сервера то точно нет :-)
      Да, думаю отдельным постом сделаю. А в общем скажу так, есть siege и ab. Мне нравится ab, т.к. он очень простой с одной стороны, а с другой — очень гибкий. Можно на баше или руби написать скрипт, который будет вызывать ab с разными параметрами и эмулировать таким образом целевую аудиторию с необходимыми действиями.

  2. IAD:

    Спасибо, очень содержательно о GridFS. Сомнения разбились напрочь.

Комментировать