html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Планирование нагрузки на сервер


Нагрузочное тестирование показало, что сервер может обработать 10 запросов в секунду. Значит ли это, что на практике сервер выдержит такую нагрузку в Интернете?

В большинстве случаев ответ на этот вопрос — отрицательный. Давайте подробно разберемся почему.

Простая на первый взгляд задачка

Дан сервер, синхронно обрабатывающий запросы из Интернет в одном потоке. Т.е. в каждый момент времени сервер может либо обрабатывать один запрос, либо ожидать новые запросы. Запросы становятся в очередь ожидания, если в данный момент сервер занят обработкой другого запроса. Время обработки одного запроса равно 100 мс.

Вопрос: каково будет среднее время ожидания запроса в очереди при средней нагрузке на сервер в 10 запросов в секунду? Правильный ответ — время ожидания будет стремиться к бесконечности.

Как же так? Ведь очевидно, что за одну секунду сервер может последовательно обработать 10 запросов. Откуда тогда берется бесконечность? Дело в том, что средняя и равномерная нагрузка — это «две большие разницы». Средняя нагрузка на сервер может быть представлена в виде процесса Пуассона. Это означает, что в начале первой секунды может сразу прийти 100 запросов, а за последующие 9 секунд — ни одного.

В итоге выходит 10 запросов в секунду за интервал в 10 секунд со средним временем ожидания sum(1..99)/100 * 100 мс = 4.95 секунды. С увеличением рассматриваемого интервала увеличивается и среднее время ожидания. Если рассматривать среднее время ожидания на бесконечном интервале времени, то оно тоже устремится в бесконечность.

Рассмотрим другие варианты. Очевидно, что при средней нагрузке, превышающей 10 запросов в секунду, сервер не сможет обрабатывать лишние запросы, что приведет к бесконечному увеличению очереди ожидания запросов.

А что будет, если нагрузка будет ниже максимально допустимой? Например, каково будет среднее время ожидания при 95% нагрузке, т.е. для нашего случая 9.5 запросов в секунду? Думаете, 0 мс или что-то близкое к этому? Ведь при такой нагрузке сервер должен простаивать в ожидании запросов 5% своего времени.

Спешу вас снова огорчить — среднее время ожидания в этом случае будет равно 950 мс , т.е. в 9.5 раз больше времени, необходимого на обработку самого запроса! Идем дальше. Давайте попробуем предположить время ожидания при 90% нагрузке. Нет, вовсе не 900 мс, а 450 мс. Интересно...

А при какой нагрузке среднее время ожидания будет равно времени, необходимому для обработки запроса? Иными словами, при какой средней нагрузке среднее время ответа от сервера будет равно 200 мс (100 мс ожидание + 100 мс обработка)? Правильный ответ — 66.666...%! Даже при одном запросе в секунду среднее время ожидания будет равно не нулю, а где-то 5.56 мс.

Мы тебе не верим. Откуда такие странные числа?

Числа получены экспериментальным путем, после чего была выведена формула.

Вот очень простая функция, написанная на python, которая была использована для моделирования нагрузки на сервер и вычисления среднего времени ожидания.

def NormalizedAvgWaitTime(load_factor, requests_count):
 """
Calculates normalized average wait time for the given 
load factor.
 
Models requests to a synchronous single-threaded server 
using Poisson process and calculates an average wait time 
per request for the given load factor.
 
  Args:
load_factor: a floating point value in the range [0..1).
The value 0 means the server isn't loaded with requests 
at all, the value 1 means the average qps load on the 
server is equivalent to its' maximum capacity.
requests_count: an integer representing the number of 
requests to model. Higher values mean higher precision 
for the returned result.
 
  Returns:
a floating point number representing normalized average 
wait time per request for the given load factor. The 
value 0 means requests are processed immediately, while 
any number W means requests stay in the queue for an 
average W*T seconds, where T is a time required for 
processing a single request on the idle server.
  """
  if not load_factor:
    return 0
  points = sorted(random.random() for i in range(requests_count))
  request_time = load_factor / requests_count
  total_wait_time = 0
  x = points[0]
  for i in range(1, requests_count):
    y = points[i]
    wait_time = request_time - y + x
    if wait_time > 0:
      total_wait_time += wait_time
      y += wait_time
    x = y
  return total_wait_time / load_factor

А вот тут вы можете удостовериться в подлинности вышеприведенных чисел и посмотреть, как requests_count влияет на точность вычислений. Заодно в python попрактикуетесь.

После того, как были получены экспериментальные данные, осталось подогнать под них формулу.

При load_factor = 1  наша функция стремится к бесконечности. Значит, у нас должна быть дробь, в знаменателе которой присутствует множитель, стремящийся к нулю при load_factor = 1 . На эту роль хорошо подходит (1 — load_factor) . Идем дальше. При load_factor = 0  наша функция равна нулю. Значит, в числителе дроби должен быть множитель, равный нулю при load_factor = 0 . Очевидно, что это и есть load_factor.

Дальше — при load_factor = 0.5 наша функция должна равняться тоже 0.5 . Значит, C*0.5/(1-0.5) = 0.5 .

Откуда C = 0.5 . В итоге формула принимает вид:NormalizedAvgWaitTime(load_factor) = 0.5*load_factor / (1-load_factor)

Где-то должен существовать аналитический вывод этой формулы посредством матаппарата процесса Пуассона, но там, скорее всего, слишком много матана, который не очень интересен и не совсем понятен основной аудитории этой статьи. Уверен, в Интернете полно материалов по этой теме, так что желающие могут погуглить самостоятельно. Может оказаться, что моя математическая модель с формулой не совсем корректна, но мои бывшие преподаватели по физмату в любом случае не будут краснеть за меня, потому что суть здесь, уверен, выражена совершенно верно.

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

Многопоточные сервера, серверные кластеры и асинхронная обработка запросов

До сих пор мы рассматривали сферического коня в вакууме aka «однопоточный сервер, последовательно обрабатывающий независимые запросы в синхронном режиме».

На практике такие сервера встречаются достаточно редко (если не считать Python runtime в Google AppEngine). Как же быть с многопоточными серверами, серверными кластерами и прочими асинхронными node.js’ами?

Очень просто — для них тоже действует вышеописанная формула. Нужно лишь забыть о деталях реализации и представить наш сервер или кластер в виде black box’а, после чего определить максимальную нагрузку, которую способен выдержать этот black box, чтобы правильно откалибровать load_factor в формуле. Максимальную нагрузку, выраженную в запросах в секунду, можно определить следующим способом: отправляем нашему black box’у в максимально короткое время (чем меньше, тем точнее результат) фиксированное число real-world запросов (чем больше, тем точнее результат) и засекаем время, когда все они будут корректно обработаны. Затем делим количество обработанных запросов на время.

Это и есть искомая максимальная нагрузка на нашу систему, относительно которой калибруется load_factor .

Теория массового обслуживания

Однако, автора можно здесь справедливо пнуть в незнание основ, с которыми, поверьте, у него всё очень даже неплохо. Поэтому, кто хочет зайти к этой же проблеме с другой, более классической стороны — рекомендую ознакомиться с Теорией массового обслуживания, которая очень плотно используется в сфере больших нагрузок (вот вам готовая методичка по ней на русском), но главный минус в этой теории в том, что там нет формул-выводов для случая многоканальной СМО с бесконечной очередью.

Посему есть существенно усовершенствованная модель, которая может эмулировать несколько серверов (многоканальная СМО) с несколькими режимами отправки запросов из очереди к серверам — least loaded, random и round robin —смотрите код и результаты тута: ideone.com/DXB9n .

Для режима round robin также можно варьировать количество очередей (клиентов). Для остальных режимов количество клиентов не имеет значения.

Вывод — время ожидания в режиме раскидывания запросов случайным образом по имеющимся серверам не зависит от количества серверов и равно времени ожидания для одного сервера. Время ожидания в режиме least loaded резко падает при увеличении количества серверов по сравнению со временем ожидания для одного сервера. Это — самый оптимальный режим раздачи запросов на параллельные сервера и он не зависит от количества клиентов, отправляющих запросы. Время ожидания в режиме round robin при одном клиенте примерно равно времени ожидания в режиме least loaded, но при увеличении числа клиентов время ожидания стремится к режиму random.

Как правильно планировать нагрузку на сервер?

К этому моменту вам должно быть понятно, что результаты типичного нагрузочного тестирования перед выходом в production не совсем корректно отражают объективную реальность. Главная проблема в том, что поток тестовых запросов не является Пуассоновским процессом, с которым суждено встретиться серверу в production. Но это легко поправимо. Достаточно найти максимальную нагрузку, выдерживаемую системой по схеме, описанной в предыдущем параграфе.

load balancing * балансировка нагрузки

После этого по формуле вычисляете допустимую нагрузку в production для заданного среднего времени ожидания запроса. Например, для максимальной нагрузки в 1000 qps и среднего времени ожидания запроса, равного 100% времени обработки запроса: 1 = 0.5*load_factor/(1-load_factor) => load_factor = 1/1.5 = 2/3.

Тогда допустимая нагрузка равна: 1000*2/3 = 666.666... qps .

Многопоточные программы

Можно ли применить только что полученные знания для вычисления среднего времени ожидания доступа к разделяемому ресурсу, защищенного с помощью блокировки в многопоточной программе? Ответ — нет, т.к. процесс доступа к разделяемому ресурсу из небольшого количества потоков (например, меньше тысячи) не может быть аппроксимирован Пуассоновским процессом.

В многопоточных программах всегда известна максимальная нагрузка на доступ к разделяемому ресурсу — она пропорциональна максимальному количеству потоков, которые могут захватить блокировку. Более того, для простейшей реализации блокировок в виде FIFO-очереди заблокированных потоков всегда известно максимальное время ожидания — оно пропорционально максимальному количеству потоков и времени удерживания блокировки.

Выводы

Всегда следите за нагрузкой на системы, обрабатывающие запросы, которые распределены во времени по процессу Пуассона. К таким системам относятся все системы с потенциально большим количеством пользователей. Например, все сервера подключенные к Интернет.

Не допускайте, чтобы средняя нагрузка повышалась более чем на 75% от максимально допустимой, т.к. это ведет к молниеносному увеличению среднего времени ожидания входящих запросов. Грамотно интерпретируйте результаты нагрузочного тестирования и всегда имейте в виду, что реальная производительность системы будет ниже расчетной, это чисто эмпирический факт.

Окончание этой серии — читайте здесь.

Читать дальше
Twitter
Одноклассники
Мой Мир

материал с blogerator.ru

9

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • pleshner
          • домен blogerator.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции