 | Уровень сложности: средний Шон Волберг, старший сетевой инженер, P.Eng
24.12.2007 Используйте Web-сервер Apache в качестве примера, для того чтобы увидеть, как анализировать распространенные конфигурации на предмет их производительности. При трассировке отслеживаются системные вызовы, сделанные приложением во время работы. Считая вызовы и время, которое они заняли, вы можете легко увидеть влияние изменений на производительность.
Вы также можете использовать трассировку в приложениях для того, чтобы узнать почему они зависают или не работают вообще. Вы также можете использовать те же приемы, чтобы узнать больше о приложении и понять как производительность зависит от конкретной конфигурации. В этой статье Apache используется в качестве примера потому, что он популярен и большинство читателей знакомы с ним. Каждый системный вызов, который делает Apache, приводит к задержке в обработкие Web-страницы, и трассируя Web-сервер в различных конфигурациях, вы можете определить влияние конфигураций на производительность.
Введение в трассирование приложений
Во время выполнения приложения оно совершает системные вызовы к лежащей в основе операционной системе, вне зависимости от того, что этому приложению нужно сделать - открыть файл, послать пакет или использовать системные ресурсы. Трассировка приложения подразумевает, что вы наблюдаете системные вызовы, как только они были совершены, что позволяет вам заглянуть в поведение приложения. Для операционных систем Solaris и IBM AIX® трассировка выполняется командой truss, для Linux® командой strace. В примере 1 показан пример трассировки команды pwd.
Пример 1. Трассировка команды pwd
-bash-3.00$ truss pwd
...
getcwd("/export/home/sean", 1025) = 0
/export/home/sean
write(1, " / e x p o r t / h o m e".., 18) = 18
_exit(0)
|
После удаления выводимой информации, относящейся к загрузке приложения, вы можете видеть, что сделаны три системных вызова:
-
getcwd возвращает текущую рабочую директорию. В выводе видно, что строка "/export/home/sean" была записана в буфер.
-
write отображает заданную строку. Из-за того, что системный вызов отображается после того, как он был осуществлен, вывод данных происходит в предыдущей строке. Также заметьте, что результатом системного вызова write является число выведенных символов, в нашем случае - 17 плюс один символ возврата каретки.
-
_exit выходит из программы с кодом ошибки 0, что традиционно ассоциируется с успешным выполнением.
В этом примере также показан уровеь прозрачности приложения при использовании трассировки. Для большего количества информации о всестороннем рассмотрении трассировки ознакомьтесь с разделом Дополнительные материалы.
Беглый взгляд на конфигурацию Apache-сервера
Веб-сервер Apache конфигурируется через файл с именем httpd.conf. В примере 2 показана часть простой конфигурации.
Пример 2. Элементарный образец httpd.conf
DocumentRoot "/var/apache/htdocs"
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory "/var/apache/htdocs">
Options Indexes FollowSymLinks MultiViews
</Directory>
|
Первая строка определяет, где могут быть найдены HTML-файлы. Запросы отправляются к этому каталогу. Если запрос сделан для /project/charter.html, используется содержимое /var/apache/htdocs/project/charter.html. Остальная часть httpd.conf состоит из двух элементов Directory. Все между <Directory ...> и </Directory> относится к выбранной директории и всем поддиректориям. В этом случае первый элемент остальной части httpd.conf применяет две настройки к корневой директории, а второй элемент ссылается на /var/apache/htdocs.
Если многократные элементы применяются к одному запросу к директории, превосходящей по важности все прочие, команды, определенные в них, объединяются. Например, запрос на /project/charter.html будет отдан /var/apache/htdocs/project/charter.html. /var/apache/htdocs вляется поддиректорией /, поэтому Options Indexes FollowSymLinks MultiViews взяты из второго элемента остальной части httpd.conf AllowOverride None из первого.
Можно сконфигурировать множество параметров, и каждый из них имеет значение для работы программы. Остальная часть статьи посвящена исследованию воздействия на производительность этих изменений.
Определение признаков
Прежде чем вы начнете отлаживать систему, необходимо получить представление о том, как система работает сейчас. Запустите Apache с параметром -X , который принудит его работать в однопроцессном режиме отладки. Сделав так, мы получим уверенность в том, что запрос постоянно будет приходить в процесс, который трассируется и устраним издержки, связанные с взаимодействием между процессами.
После того как программа начала свое выполнение, определите ID процесса с помощью команды ps -ef и в ее результатах найдите демона httpd. Как только вы его найдете, подключитесь к процессу следующим образом: truss -c -p PID
. Опция -c считывает системные вызовы и отображает их один за другим, а -p показывает, что трассировщик должен присоединиться к работающему процессу.
Сделайте запрос к документу, используя Web-браузер. После того как страница загрузится, вернитесь к приложению truss и нажмите Ctrl-C, чтобы остановить подсчет. Для статической HTML-страницы вы должны увидеть что-то вроде того, что показано в примере 3 (чтобы сделать числа более интересными, этот пример делает один и тот же запрос 100 раз).
Пример 3.Признаки системного вызова
sunbox# truss -c -p 15026
(make the Web request 100 times)
^C
syscall seconds calls errors
read .009 200
write .020 200
close .020 200
time .004 300
alarm .018 1100
fcntl .009 300
sigaction .007 400
munmap .007 100
llseek .001 100
pollsys .005 100
mmap64 .008 100
stat64 .007 100
open64 .006 100
accept .019 100
getsockname .002 100
setsockopt .002 100
-------- ------ ----
sys totals: .149 3600 0
usr time: .120
elapsed: 8.960
|
truss возвращает список системных вызовов, время, потраченное на один вызов, число вызовов и ошибок, если они были найдены. В конце отчета возвращается общее время, затраченное на системные вызовы, вместе с временем выполнения приложения вместе со временем, потраченным на выполнение приложения. Общее затрачиваемое время неважно для исследуемых целей, потому что оно указывает на время, когда trussбыл запущен и когда прекратил свою работу, и не имеет отношения к Web-запросу.
В примере 3 показан самый простой случай. После получения запроса на соединение от Web-браузера, системный вызов accept открывает соединение. Веб-сервер использует вызов read, чтобы получить все содержимое запроса, который перенаправляется к файлу на диске. Сначала Web-сервер проверяет, что файл существует stat64, открывает файл для чтения с помощью команды open64 и переписывает данные файла в память mmap64. Потом этот файл отправляется назад клиенту с системным вызовом write,а системный журнал генерируется другим системным вызовом write, и сервер выполняет последный вызов read от браузера. Все другие вызовы являются ненужными и не изменятся значительно при изменении конфигурации.
Обрабатываем результаты
Следует заметить, что 100 запросов занимают по времени 0,269 секунды (0,149 + 0,120) и что сервер должен быть способен обрабатывать около 370 страниц в секунду (100/0,269). Эти числа надо воспринимать с изрядной долей скептицизма, потому что они представляют только время, которое процесс тратит на выполнение в CPU, но не реальное время, котрое требуется ему на выполнение. Множество других факторов вносит свой вклад, например, скорость жесткого диска и сети, другие процессы, запущенные на компьютере, и хотя бы тот факт, что исследуемый процесс был запущен в отладочном режиме. Вы также должны учитывать ненужные процессы из общего списка процессов, полученного при трассировке.
Технические приемы, используемые в этой статье направлены на то, чтобы показать относительность измерения времени выполнения операций, и использовании трассировки приложений для удаления ненужных операций. Если вам нужно знать число страниц, которое ваш Web-сервер может обработать за секунду, раздел дополнительные материалы содержит ссылки на программное обеспечение, которое поможет вам в этом.
Трассировка области действия AllowOverride
Apache дает администратору возможность предавать полномочия конфигурирования отдельным пользователям через механизм .htaccess. Этот файл, содержащий дополнительные инструкции для конфигурирования, используемые сервером, если запрошенная директория была сконфигурирована с AllowOverride внутри httpd.conf. В примере 4 показана предыдущая конфигурация, построенная с учетом AllowOverride Limit, который позволяет запрашивать у пользователей логин и пароль для доступа к Web-странице.
Пример 4. Простейший вариант файла httpd.conf с сконфигурированным AllowOverride
DocumentRoot "/var/apache/htdocs"
<Directory />
Options FollowSymLinks
AllowOverride Limit
</Directory>
<Directory "/var/apache/htdocs">
Options Indexes FollowSymLinks MultiViews
</Directory>
|
Перезапуск процесса httpd и тестов дает результаты, показанные в примере 5.
Пример 5. Результат 100 запросов с активированным ограничением AllowOverride Limit
sunbox# truss -c -t write,read,open64,stat64,mmap64 -p 21136
^C
syscall seconds calls errors
read .012 200
write .021 200
mmap64 .007 100
stat64 .007 100
open64 .022 500 400
-------- ------ ----
sys totals: .072 1100 400
usr time: .141
elapsed: 16.660
|
На первый взгляд, время системных вызовов упало, но это только потому, что проводилась трассировка только для интересующих вызовов с помощью опции -t. Большинство системных вызовов остались теми же, но теперь присутствуют 500 вызовов к open64, 400 из которых возвращают ошибку. Время, потраченное на выполнение open64, также возросло (от 0,006с до 0,22с), как и время со стороны пользователя (от 0.12с до 0.141с).
Время возросло, потому что Apache должен делать дополнительную работу для обработки запросов, хотя мы не сконфигурировали никаких обнулений. Конфигурация AllowOverride Limit добавила заметную нагрузку. Остается вопрос: что вызвало все эти ошибки? Чтобы ответить на него, протрассируем один Web-запрос как показано в примере 6.
Пример 6. Определение причины ошибок системного вызова open64
sunbox# truss -t open64 -p 21136
open64("/.htaccess", O_RDONLY) Err#2 ENOENT
open64("/var/.htaccess", O_RDONLY) Err#2 ENOENT
open64("/var/apache/.htaccess", O_RDONLY) Err#2 ENOENT
open64("/var/apache/htdocs/.htaccess", O_RDONLY) Err#2 ENOENT
open64("/var/apache/htdocs/test.html", O_RDONLY) = 5
|
В примере 6 показано, что, когда приходит запрос, Apache проверяет каждую директорию на пути к /var/apache/htdocs и пытается открыть файл .htaccess, который не существует, потому что AllowOverride был сконфигурирован в корневой директории. Apache проверяет каждую директорию на предмет override'ов в .htaccess и выполняет их. Это добавляет времени ожидания из-за избыточного количества системных вызовов, больше ненужной активности со строны пользователя, без упоминания дополнительной дисковой деятельности. Пара десятков секунд на 100 запросов может выглядеть незначительно, но на загруженном сервере это дает о себе знать.
Теперь, с учетом того, что вы уже понимаете смысл просмотра override'ов, идеальное решение - это использовать повсеместно override'ы и не вмешиваться во все, что может быть сконфигурировано в httpd.conf. Подводя итог, ограничьте возможности конфигурации по отношению к каталогам, которые нуждаются в ней. В изученном примере перемещение AllowOverride Limit во второй элемент Directory добавит один дополнительный open64 для поиска .htaccess в /var/apache/htdocs. Поиск во всех родительских директориях - напрасная трата времени, потому что согласно текущей конфигурации никакие файлы из них не будут выданы.
Изучение HostnameLookups
Когда Web-сервер получает запрос, он знает о клиенте только одно - IP-адрес, такой как 129.42.42.212 для IBM.com. Однако Web-сервер не знает, что этот IP-адрес является адресом IBM.com. Для этого он должен выполнить обратный поиск DNS. Это занимает время, и если имя необходимо прежде чем может быть послан запрос, откладывает ответ клиенту. В прошлом Apache выполнял эти обратные поиски по умолчанию, но его поведение изменилось.
Существует другой случай, когда требуется обратный поиск DNS. Когда конфигурируется ограничение в доступе, основанное на имени хоста (вместо IP-адреса), Apache должен сначала преобразовать IP-адрес в имя хоста и затем назад имя хоста в IP-адрес, чтобы быть уверенным, что они совпадают. Потому что имя домена, полученное в результате обратного поиска, может иметь любое значение по желанию хозяина IP-адреса, и второе соединение произодится для того, чтобы убедится, что не происходит получение доступа путем обмана. Может ли трассирование приложения определить влияние разрешающей способности DNS?
Чтобы проверить это, удалите AllowOverride Limit из предыдущего примера и добавьте Allow from ibm.com вместо кода, что по умолчанию Allow from all. Затем сделайте так, чтобы DNS сервер возвращал something.ibm.com для вашей рабочей станции для уверенности в том, что начальная обратная проверка и последующая будут идти через Интернет. При обычном запуске запрос на защищенный Web-сервер занимает 15 секунд. С другой стороны, использование IP-адреса вместо ibm.com займет меньше чем полсекунды. В примере 7 показан подсчет некоторых системных вызовов при использовании DNS для обспечения безопасности.
Пример 7. truss-вывод Web-запроса, который был запрещен из-за недопустимого имени хоста
bash-3.00# truss -c -p 26089
^C
syscall seconds calls errors
read .000 5
write .000 3
open .000 2
close .001 10
time .000 3
stat .000 5
alarm .000 8
fcntl .000 7 2
sigaction .000 3
sysconfig .000 5
pollsys .001 5
door_info .000 2
stat64 .000 1
open64 .000 2
so_socket .001 5
accept .000 1
connect .002 5
recvfrom .000 2
send .001 5
getsockname .000 1
setsockopt .000 1
-------- ------ ----
sys totals: .011 81 2
usr time: .004
|
truss сообщает что процесс работает гораздо меньше времени чем, чем показала проверка со стороны клиента (0,015 с против 15 с). Это потому, что большинство операций с сокетами выполняется асинхронно, то есть сокет опрашивается чтобы узнать присутствуют ли данные, в то время как приложение ждет ответа. Таким образом приложение не потребляет ресурсы центрального процессора, пока ждет результатов. Это объясняет расхождение во времени, возвращенным truss и временем со стороны клиента.
truss не чувствителен к изменению: 0,015 секунды - величина на порядок выше, чем первый простой случай, расмотренный в этой статье. Появилось несколько новых системных вызовов к read, write, close и stat. Вместе с send, connect, so_socket и pollsys эти системные вызовы используются для создания запросов имени. Потому что разрешение имени могло исходить от разнообразных источников, включая локальную файловую систему, несколько мест должно быть проверено. В последующих вызовах время запроса было около секунды, потому что информация DNS была кэширована.
В итоге большая часть задержки исходила из отдаленного блока преобразования имен и разрешения доступа. Этот факт подчеркивает нужду в кэшировании DNS и быстрых DNS-серверах, если вы надеетесь на поиски по имени. Однако лучшее решение состоит в том, чтобы взглянуть с альтернативной точки зрения на проблему. Достаточно простым решением является идея определить группы IP-адресов(например так Allow from 10.0.0.0/8). Такой подход гораздо быстрее чем DNS поиск. Потому что результаты обоих – обратного и прямого – поисков должны совпадать; есть большая возможность, что если вы сможете сделать это с именем, то сможете и с сегментом сети. Другой вариант: Apache может интегрироваться с множеством аутентификационных систем, поэтому аутентификация со стороны пользователя – другая возможность.
Сравнение системных вызовов с библиотечными
Если вы знакомы с программированием сокетов, вы могли бы искать gethostbyname и другие подобные вызовы, которые выполняются для выполнения функции поиска хоста. Эти вызовы из библиотек обеспечены системными библиотеками, такими как libc и libsocket, расположенными в /usr/lib. Вызовы из библиотек заключают в оболочку один или несколько системных вызовов всесте с дополнительной логикой. Вы можете рассматривать их как удобные для программиста интерфейсы для системных вызовов. Например, gethostbyname вызов из библиотеки проходит много шагов, в число которых входит проверка /etc/hosts или поиск в Network Information System (NIS) или DNS, чтобы найти название, основанное на конфигурации сервера. Эти шаги содержат в себе меньшие строительные блоки – системные вызовы, которые предоставляет ядро. В большинстве случаев до этого пункта различие было маленьким. truss может также проверять вызовы из библиотек, но не обеспечивает тот же уровень детальности, что и для системных вызовов.
Заключение
Возможность наблюдать и считать системные вызовы полезна не в только в случае отыскания неисправностей, но также для понимания того, как конфигурация приложения влияет на производительность. Каждое взаимодействие с остальной частью системы приводит к одному или нескольким системным вызовам и каждый запрос добавляет ненужные расходы.Это не говорит о том, что системные вызовы это плохо: программа, которая не взаимодействует с остальным миром - не очень интересна! В любом случае, можно наблюдать использование обращений к системе в измененном приложении, чтобы иметь возможность подумать о том, как добиться максимальной производительности от сделанных изменений.
Ресурсы Научиться
-
Оригинал статьи (EN)
-
Solve application problems with tracing (EN) (developerWorks, март 2006): статья сфокусирована на использовании трассировки как инструмента для поиска неисправностей.(EN)
-
Performance tuning: Web-сервер Apache поставляется с документом относительно настройки его работы. Эта статья рассматривает два значительных элемента, важных для настройки, но те, кто работал с Apache указывают на ряд других важных моментов.(EN)
-
AIX и UNIX: хотите больше? Сообщество developerWorks предлагает сотни информативных статей и обучающих курсов различной стпепени сложности по AIX и UNIX.
-
developerWorks
technical events and webcasts: оставайтесь в курсе технический событий и Web-обзоров сообщества developerWorks.
(EN)
-
Podcasts: оставайтесь на связи с техническими экспертами IBM.(EN)
Получить продукты и технологии
-
IBM trial software: создайте ваше новое приложение с помощью программного обеспечения IBM, которое можете загрузить прямо со страницы сообщества developerWorks.(EN)
-
Siege: этот инструмент моделирует загрузку на вашем Web-сервере и помогает определить, сколько он может обработать.(EN)
Обсудить
Об авторе  | |  | В академической, корпоративной средах, среде поставщиков интернет-услуг Шон Волберг (Sean Walberg) работает с системами Linux и UNIX с 1994 года. За последнюю пару лет он очень много написал о системном администрировании. Вы можете написать ему на
sean@ertw.com. |
Выскажите мнение об этой странице
|  |