Я использовал JMeter для генерации нагрузки на свой производственный сервер для тестирования моего приложения. План тестирования имеет 13+ HTTP-сэмплеров для выполнения другого запроса и один экстрактор регулярных выражений для извлечения некоторого значения из ответа. Это значение использовалось в последовательном HTTP Sampler. Этот тестовый пример прост и понятен. Первоначально я использовал 200 потоков JMeter для имитации 200 пользователей. Сервер мог легко обрабатывать эти многочисленные запросы, но когда количество потоков увеличивалось, он не мог обрабатывать их и ждал бесконечно. Конечно, что-то происходило. Потоки JMeter ждали соединения и не могли его так ждать бесконечно. Чтобы избежать этой ситуации, я ввел «HTTP-запрос по умолчанию», чтобы добавить некоторое время ожидания соединения и ответа. Одна проблема была решена, теперь потоки не зависают там бесконечно, но они истекают со следующим исключением.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:129) at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) at java.io.BufferedInputStream.read(BufferedInputStream.java:237) at org.apache.commons.httpclient.HttpParser.readRawLine(HttpParser.java:78) at org.apache.commons.httpclient.HttpParser.readLine(HttpParser.java:106) at org.apache.commons.httpclient.HttpConnection.readLine(HttpConnection.java:1116) at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(HttpMethodBase.java:1973) at org.apache.commons.httpclient.HttpMethodBase.readResponse(HttpMethodBase.java:1735) at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1098) at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398) at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323) at org.apache.jmeter.protocol.http.sampler.HTTPHC3Impl.sample(HTTPHC3Impl.java:258) at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:62) at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1088) at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1077) at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:428) at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:256) at java.lang.Thread.run(Thread.java:662) |
Определенно какая-то часть сервера (Apache 2.2.14 + Apache-tomcat-7.0.11) скрипела, но не была уверена, какая часть. Конечно, в настройке было узкое место. В текущей настройке сервер Apache переадресовывал запросы на движок Tomcat. Конечно, ни один из них не смог обработать более 200 запросов одновременно. Я немного изменил настройку, чтобы перенаправить все запросы непосредственно на движок Tomcat. Это было в состоянии справиться с этим, это означает, что Apache ослабевал. Я быстро проверил файл Apache error.log, присутствующий в /var/log/apache2/error.log и обнаружил следующие строки.
|
1
2
3
4
|
[Wed Jun 26 16:46:19 2013] [error] server is within MinSpareThreads of MaxClients, consider raising the MaxClients setting[Wed Jun 26 16:46:20 2013] [error] server reached MaxClients setting, consider raising the MaxClients setting[Wed Jun 26 17:24:42 2013] [error] server is within MinSpareThreads of MaxClients, consider raising the MaxClients setting[Wed Jun 26 17:24:43 2013] [error] server reached MaxClients setting, consider raising the MaxClients setting |
Это ясно указывает на то, что число MaxClients должно быть увеличено, что, в свою очередь, увеличит количество потоков Apache. Я быстро отредактировал файл apache2.conf, чтобы увеличить число MaxClients, добавив следующую конфигурацию и выполнив "apache2ctl -t" чтобы убедиться, что изменения, внесенные в файлы конфигурации, были правильными.
|
1
2
3
4
5
6
7
8
9
|
<IfModule mpm_worker_module> StartServers 2 MinSpareThreads 25 MaxSpareThreads 100 ThreadLimit 800 ThreadsPerChild 800 MaxClients 2400 MaxRequestsPerChild 0 </IfModule> |
Я был немного расслаблен, думая, что теперь Apache определенно справится с нагрузкой. Но, к моему удивлению, это не могло произойти, и то же самое исключение снова ударило по JMeter. На данный момент я хотел проверить производительность Apache, включив состояние сервера. Эта функция может дать вам четкое представление о состояниях соединения. Я поместил следующие строки в /etc/apache2/mods-available/status.conf
|
1
2
3
4
5
6
|
<Location /server-status> SetHandler server-status Order deny,allow Deny from all Allow from .your.domain.here.com localhost</Location> |
Я перезапустил Apache и сервер, выполнив следующую команду
|
1
|
/> sudo service apache2 restart; sudo service tomcat restart; |
После перезапуска Apache я нажал следующий URL, чтобы получить статус сервера.
После запуска JMeter для 200+ потоков я заметил это на странице состояния.
На странице состояния указано, что в состоянии "W" (отправка ответа) было много соединений. Это может быть вызвано другими причинами. Я пытался гуглить, но не смог найти какое-то определенное решение. Но одна вещь была уверена, что Apache не вызывает проблем. Должно быть между Apache и tomcat. Я понял, что план тестирования JMeter отлично работает для 200 потоков, и даже Tomcat по умолчанию имеет 200 потоков. Я просто рискнул и увеличил количество потоков до 400, отредактировав файл "<APACHE_TOMCAT_HOME>/conf/server.xml" .
|
1
2
|
<!-- Define an AJP 1.3 Connector on port 8009 --><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" maxThreads="400" minSpareThreads="20" /> |
Теперь сервер может легко справиться с нагрузкой JMeter, а соединения Apache находятся в хорошем состоянии даже после завершения плана тестирования.
Хотя проблема была решена, я не мог понять, почему Tomcat смог обработать нагрузку, когда JMeter был настроен на отправку всех запросов напрямую в Tomcat, но не смог обработать нагрузку, когда Apache переадресовал запрос в Tomcat. Если у вас есть какие-либо объяснения относительно этого поведения, пожалуйста, поделитесь ниже в разделе комментариев.
