Хайлоад что это: введение в highload — ITSource

Что такое highload? — Хабр Q&A

Highload обычно употребляется в смысле — «умение горизонтально масштабировать веб-проект до любого теоретически достижимого числа клиентов».

По численным именам по мне лучше использовать более конкретные имена, к примеру устоявшееся C10K problem, или «как работать с 10000 одновременные коннектами пользователей» на комп. При работе с торрент-анонсером, такая проблема, к примеру, возникала.

Ответ написан

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

Highload — это когда традиционных подходов и стандартных решений уже не хватает.

Ответ написан

Нет ни методики ни чисел. Highload — это название состояния инфраструктуры, которая требует того, чтобы ее оптимизировали и масштабировали. Т.е. это просто описание состояния. Например, что такое уставший человек? Один может пробежать 10 км и будет уставшим. Другой уже после 500 метров и станет уставшим. Они оба уставшие, а параметры разные. Так и для ресурсов. Советую почитать — Что такое highload?

Ответ написан

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

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

ее нет. Но слово и в правду модное. Таким образом каждый разработчик сам для себя решает что для него есть хайлод.

Ответ написан

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

НУ если у вас есть миллион клиентов то вас смело можно звать хайлоадом 8)

Ответ написан

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

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

Но в реальности означает немного другое и конкретные цифры сказать трудно, все относительно.

Ответ написан

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

По мне хайлоад это когда не хватает одного физического сервера для обслуживания клиентов. 9 запросов в секунду – вот такую цифру я выписал из википедии. Хватит ли нам столько – непонятно, но это у нас средний CPU сейчас столько делает.

Если подходить более реалистично, то надо определиться с цифрами. Например, один запрос в секунду – это нагрузка явно не highload, любой сервер, вроде бы, справится. Но, например, если он перекодирует видеоролики, то тут может наступить highload.

Соответственно, я определяю высокую нагрузку как нагрузку, с которой железо не справляется по какой-то причине.

Когда у нас происходит высокая нагрузка, начинают вести речь о highload-е – когда мы достигаем каких-то технических ограничений, т.е. у нас кончается что-нибудь – CPU, память… Я еще вынесу хранилище отдельным пунктом, потому что для веб-серверов хранилище обычно – это какой-то внешний элемент.

Дополнительно мы сталкиваемся еще с такими трудностями – сейчас уже менеджеры перестали, но лет 5-7 назад, когда они покупали новый сервер, а вы через некоторое время говорили «нам этого сервера не хватает, нам надо больше», они удивлялись: «мы вам купили самый крутой компьютер на свете, а вы умудрились его тормознуть?». Сейчас они уже не удивляются, но вопрос недоиспользования «железа» так и остается самым основным. Т.е., если вернуться к тому, что средний процессор сейчас способен обработать 53 млрд. операций в сек., то объяснить людям, почему тормозит, очень сложно. Ну и трудности масштабирования, все эти проблемы, которые происходят с высокой нагрузкой, они сводятся к одному термину – архитектурные проблемы в вашем проекте.

Цикл выполнения одного запроса

Для иллюстрации рассмотрим типичный веб-сервер, написанный неважно на чем – на Perl, Python, Ruby… Берем стандартный framework, делаем веб-сервер, пишем форум, доску объявлений и т.д. Задачи одного цикла этого сервера сводятся к следующим пунктам:

  • запросы сети читаются;
  • парсятся;
  • отправляются запросы в БД;
  • формируются ответы;
  • отправляются клиентам.

Т.е. если говорить о традиционной реализации (apache, например), то все это сводится к тому, что на одну сессию выделяется один процесс или один тред. Ну, или если вернуться к определению «highload» как к нагрузке, с которой не справляется железо, то что они в этой архитектуре могут сделать?

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

Вот, к примеру, рассмотрели одну страничку одного проблемного сервера в реальных измерениях. У нас получилось следующее: примерно на 100 запросах в секунду возник highload. Первое, что сделали, – это увеличили число процессов в работе, т.е. было 8 процессов, сделали 20, потом 30 и т.д. Временно помогло, но на 150 запросов в секунду опять начались проблемы. Что делать? В этот момент прибегают менеджеры и говорят, что сходили на конференцию «Highload», где им рассказали про всякие мега крутые технологии, которые они сейчас купят и все перепишут… Тут их останавливают люди, которые говорят, что они 3 года над этим работали и переписывать это надо тоже 3 года… Что делать? Добавлять второй сервер тоже не всегда просто. ..

Лечение любой болезни начинается с постановки диагноза, т.е. для начала измерим хотя бы температуру, а потом будем делать выводы…

Мы взяли одну страничку веб-сервера, которая тормозит и которая была довольно популярна, провели измерения и получили следующие RPS:

  • чтение запроса из сети – 15К RPS
  • парсинг запроса, контроллер – 150К RPS/CPU
  • запросы к хранилищу – 60К RPS
  • формирование ответа – 100К RPS/CPU
  • отправка ответа клиенту – 15К RPS

Если мы все эти цифры начинаем друг с другом складывать, то получается расчетная производительность нашего сервера 6000 RPS.

Но менеджеры продолжают бегать – проблемы-то при 150, что делать?

Начинаем смотреть на все бенчмарки, которые мы сделали. И видим – если хранилище придвинуть к серверу максимально близко, а еще клиента посадить прямо за сервер, то, вроде бы, становится хорошо.

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

Профайлинг

Стоить начать смотреть уже не на бенчмарки, а на профайл, т.е. на то, сколько времени какой процесс занимает.

В IT-мире все идут по такому пути, на котором открывают какие-то IT-закономерности и этим закономерностям в реальной жизни есть какая-то аналогия. Я предлагаю аналогию с обувным магазином – когда вы приходите в обувной магазин, то на вас сразу набрасывается менеджер, который с вами бегает туда-сюда, вы ходите, смотрите – вот эта обувь мне подходит/не подходит, он вам может сбегать на склад, принести и т.д.

Если сравнить списки слева и справа, то они очень похожи:

Если вернуться к серверу и перейти от бенчмарков к профайлу, выписать время каждого пункта, то у нас получатся следующие цифры:

Это реальные цифры, они просто округлены.

В итоге у нас после просмотра результатов профайлинга получится, что код наш выполнялся 17 мкс, а чего-то ждали – например, ответа от БД, сети и т.п. – 156 мкс. Возникает какой-то дисбаланс – наш код выполняется всего 10% времени, и при этом все тормозит, нагрузка – 30. .. что делать?

Когда все это проходили, написали вот такую потрясающую программу, которая имитирует высокую нагрузку:

Эта программа ничего не делает, кроме sleep-ов, т.е. на месте каждого действия у нас sleep на такое же количество мкс, как было замерено. Если, кстати, говорить о реализации usleep, то в linux, начиная с ядра 2.6, usleep реализован реальным усыплением процесса, т.е. до этой версии еще можно было предъявить претензии к реализации, то сейчас это реальная модель вашего веб-сервера.

Что же получилось? Эта замечательная программа спокойно очень грузит процессор где-то на 15%, при этом ничего не делает. Когда же мы запускаем таких «воркеров» примерно столько же, сколько в apache, то получаем ту же самую нагрузку на хосте, те же 20-30 единиц «out average».

Если вернуться к нашему серверу, то каждая отдельная часть имеет хорошую производительность, но что же нам делать? Раз каждый «кирпичик» удовлетворяет нас по скорости, то нам просто надо взять и пересобрать эти «кирпичики» в каком-то другом порядке, т. е. просто взять и реорганизовать код.

Событийно-ориентированное программирование

Переходим к событийно-ориентированному программированию, т.е. начинаем читать, что у нас происходит в мире, что люди думали по этому поводу и натыкаемся вот на такие вещи:

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

Если мы вернемся к аналогии с магазином, то очевидно, что если в магазин обуви придет сразу 100 покупателей, то никаких менеджеров не хватит, и надо будет что-то реорганизовывать. И в реальной жизни люди давно справились с задачей высокой нагрузки в магазинах, например, продуктовый магазин устроен совсем по-другому, чем обувной. Т.е., всех клиентов ставим в очереди, и продавец обслуживает всех без простоя. Надеюсь, эта аналогия всем понятна.

В IT-мире этот «продуктовый магазин» представляет собой так называемую машину событий – исполнитель заявляет о готовности выполнить задачу (как в McDonald’s – «Свободная касса!»), как только «покупатель» подходит, его сразу обслуживают, а если ему нужно подождать, его ставят в другую очередь ожидающих чего-нибудь, например, со склада. В IT-мире реализация продуктового магазина сводится к тому, что исполнитель подписывается на то, что он выполнит задачу, т.е. регистрирует callback, а выполнение задачи – это, собственно, вызов callback-а и ожидание – это возврат машине событий управления путем возврата из callback-а.

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

Проблемы, которые приходится решать, поскольку мы меняем парадигму программирования:

  • сохранение контекста между callback
  • ветвление
  • обработка исключительных ситуаций

Самое критичное – это то, что во всех проектах обычно бизнес-логику строят около БД, т.е. выбрали данные, что-то посчитали или внутри БД или рядом с выборками и поэтому все эти условия типа «если клиент предпочитает зеленый цвет, то его направить туда, а если красный, то сюда» – они все около БД находятся и поэтому переписывать все запросы в БД на callback-е это практически приводит к тому, что 90% проекта будет переписано.

Но нам это не подходит и поэтому нужно попытаться объединить плюсы обувного магазина с плюсами продуктового. А в продуктовом магазине менеджер не простаивает. В нашем случае менеджер – это процессор.

Green threads

Если вы смотрели на ту потрясающую программу со sleep-ами, то я не коснулся того, почему она тормозила, но сейчас расскажу. Планировщик процессов в ОС – это вещь очень тяжелая. Во-первых, при каждом переключении процессора происходит переключение контекста очень тяжелого – процессы изолируются друг от друга, во-вторых, планировщик пытается синхронизировать эти переключения с частотой 1000Гц. И здесь проблемы есть по скорости. Соответственно, если мы возьмем плюсы планировщика и объединим их с плюсами event-машины, то мы как бы объединим обувной магазин с продуктовым. И для этого пишем свой планировщик. Эти планировщики люди часто называют fiber-ами или green tred-ами – во многих языках есть, я коснусь этого позже.

Основной API сводится к тому, что процесс можно создать и из процесса можно передать управление планировщику, а прервать процесс нельзя, потому что невытесняющая многозадачность. Т.е. мы отказываемся от всех «плюшек» процессов ОС в угоду быстродействию.

Теперь, если мы интегрируем планировщик с машиной событий, то получим примерно такую структуру кода на каждое событие:

т.е. мы подписываемся на событие и «усыпляем» текущий процесс, а событие будет – и процесс продолжается, т. о. программа становится такого же линейного вида, как она и была, т.е. запросили БД, сравнили результаты с каким-то эталоном и пошли по веткам влево или вправо – вернулись к почти традиционному виду программы.

Что у нас получается в веб-сервере? В него нам пришлось добавить машину событий, библиотеку fiber-ов, переписать все интерфейсы, на которых возникало ожидание чего-то – это, как правило, интерфейсы с веб-сервером, с БД и с сетью, если она есть.

Ну, и получается, что переписывание в такой парадигме сводится к тому, что мы пишем враппер над БД, враппер над веб-сервером и над сетевыми обращениями. В общем проекте получается, что переписывается всего около 5% кода.

Языки и технологии

Если говорить о библиотеках на языках, то на Perl просто прекрасная библиотека Coro – она реализует концепцию fiber-ов – легкого планировщика – плюс машина AnyEvent. На Python – fibers и twisted, а на PHP5.5 появился, наконец, оператор yield, fiber. Т.е. все эти парадигмы становятся доступны и php-программистам, но я пока в opensource-проектов, реализующих fiber-ы, не нашел.

Как только мы открыли для себя эту технологию, то сразу бросились все, что у нас тормозило, переписывать в такой парадигме. Доходило до смешного – люди простые циклы for i от 1 до 10 стали переписывать в асинхронной форме, т.е. в каждом цикле передавать управление планировщику – т.е. ничего, что мы 1 запрос от пользователя обрабатываем 5 секунд, но зато мы можем 10000 пользователей в секунду обработать!

Существуют framework-и, которые под эту парадигму программирования написаны. Например, Node JS – изначально асинхронный веб-framework, т.е. разработчики изначально думали об утилизации одного процессора по максимуму, но они отказались от парадигмы fiber-ов. Хотя, возможно, скоро они к ним придут.

Ну и, наш Tarantool. Он представляет собой сейчас полноценный application-сервер, который полностью реализует и предоставляет пользователю эту парадигму программирования, т.е. fiber-ы и event-машину. + «на борту» имеет неплохую БД в 2х ипостасях – БД в памяти и на диске. Кроме этого, серия библиотек, которая реализует неблокирующие сокеты, http-серверы, очереди и можно самим писать все, что хочется.

Общие недостатки этого подхода выясняются при попытке его повсеместного внедрения – на традиционных языках программирования этот подход позволяет утилизировать только один процессор, а нагрузка растет, и рано или поздно приходим к масштабированию – и по CPU и по хостам…

Уже давно существует язык Erlang, который позволяет все эти проблемы решить, однако имеет очень высокий порог вхождения, т.е. очень трудно объяснить программистам, что в языке программирования нет понятия «переменная», например.

Недавно появился Go – у него более низкий порог вхождения, потому что у него более традиционная парадигма программирования.

В свое время мы на этой парадигме программирования написали в свое время крупнейший бэкенд для Яндекс.Такси. У него сейчас примерно такая нагрузка – более 20000 водителей постоянно шлют свои координаты, более 1 млн. заявок в месяц, т.е. общее количество информации и трафика – большое. Проект реализован просто на Perl-овых скриптах (Coro+AnyEvent) и множество очередей (клиентов перед менеджерами) стоят на Tarantool-е, т. е. с помощью Tarantool-а реализуем очереди. И большое дисковое хранилище на PostgreSQL. Этот проект реализует у нас мобильное приложение клиента, водителя, диспетчера и т.д. и все это размещается всего на 2х серверах Hetzner-а, при этом один из них резервный.

Когда мы эту технологию освоили, все поняли, что мы очень крутые программисты.

← Вступительная статья

Что такое проект с высокой загрузкой?

Высокая нагрузка. Лет 5-6 назад это было для меня главным модным словечком. С тех пор, как вышел фильм «Социальная сеть», я захотел разработать такое программное обеспечение.

Зона домена для меня тогда не имела значения: службы знакомств для основателей служб знакомств, нелегальные онлайн-казино или сайты, транслирующие сомнительный видеоконтент — все было бы в порядке. Я хотел быть частью команды, которая решает сложные инженерные задачи в масштабе и поставляет продукт в многие тысячи и миллионы пользователей одновременно .

Я прочитал десятки определений в Интернете из разных источников. Но я не понял, что значит highload. И теперь, после многих лет разработки различных проектов highload, я создал свое собственное определение highload .


Что Интернет говорит о Highload

Позвольте мне поделиться с вами агрегированием моих выводов из разных источников:

Highload начинается, когда один физический сервер становится не в состоянии обрабатывать данные.

Звучит разумно, не правда ли? Но я не могу согласиться с определением, потому что оно не учитывает программное обеспечение для систем, которые вообще не могут масштабироваться. Как встроенные.

Если один инстанс обслуживает 10 000 подключений одновременно — это высокая нагрузка.

Утверждение интересное и относится к проблеме C10K. Но я думаю, что это неправомерно исключает системы, которые обрабатывают меньше соединений.

Ваш проект является высоконагруженным, если он обрабатывает более 100 динамических запросов в секунду.

Это не звучит достаточно серьезно , если мы подумаем об обычных HTTP-запросах, когда приложение немного переключается в базе данных. Но если обработка на бэкенде требует много работы процессора — почему бы и нет? В любом случае, давайте пропустим это, потому что оно не универсально.

Highload позволяет одновременно обслуживать тысячи и миллионы пользователей.

Это мнение распространено. Не так много проектов могут похвастаться такими цифрами. Я думаю, что наличие тонны клиентов не обязательно, чтобы быть высоконагруженной системой. Но точно хватит.

Highload начинается тогда, когда обычные и очевидные решения перестают работать и приходится придумывать какие-то хитрости, чтобы справиться с трафиком.

Мне нравится этот! Типа согласен с этим. Нашел это слишком поздно :).

Если ваша инфраструктура не может потреблять входящие потоки данных и требует горизонтального масштабирования — добро пожаловать в клуб Highload.

Горизонтальное масштабирование и высокая нагрузка очень часто идут рука об руку. Но это не правило для меня.

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

Дело не только в сайтах. И вам не нужно иметь большую аудиторию . С другой стороны идея хорошая.

Если вы используете одну очень толстую машину, ваш проект является довольно высоконагруженным.

Да, это может быть правдой. И это тоже не обязательная функция.

Использование Lambda Architecture и Kafka увеличивает нагрузку на систему.

Мы можем перефразировать это в более общем виде: Использование технологии X или архитектурного шаблона Y делает ваш проект высоконагруженным . Я категорически не согласен с этим. Учащийся может сделать личный проект, который никогда не попадет в реальную производственную среду, за исключением тестирования его/ее друзьями с образцами данных, не относящимися к реальному миру. Нам нужно немного нагрузить систему реальными клиентами/набором данных, чтобы назвать ее highload .

Если вы развернуты на AWS, IBM Bluemix, Azure или Google Cloud Platform, вы поддерживаете высоконагруженный сервис.

Это определение не имеет для меня особого смысла. Как насчет локальных решений? Значит ли это, что они не могут быть в клубе Highload? Неа. Кстати, облачные вычисления предлагают множество сервисов для ускорения разработки и облегчения масштабирования.

Ну, Вяч, что такое Highload?

Как вы, наверное, заметили, все перечисленные определения и куча других меня не полностью удовлетворили. Я представил весь опыт, который у меня был, чтобы сделать это заявление.

Что такое высоконагруженный проект?

Проект, в котором неэффективное решение или крошечная ошибка оказывают огромное влияние на ваш бизнес. Ошибка приводит к увеличению стоимости

$$$ или потере репутации компании.

С инженерной точки зрения нехватка ресурсов приводит к снижению производительности.

Это определение мне нравится больше других, потому что:

  • В числах нет ничего: серверы, соединения, запросы, пользователи. Функции могут варьироваться от проекта к проекту.
  • Мы не указываем технологии, поставщиков и шаблоны.
  • Инженеру легко определить, является ли проект высоконагруженным на данном этапе. Если вы уже не можете позволить себе принимать грубые решения, которые не повлияют на ваш бизнес, вы в безопасности. Пока что. В противном случае — будьте ответственны и осторожны.
  • Это обеспечивает лучшее объяснение заинтересованным сторонам бизнеса, почему ваша команда должна создавать одно решение вместо другого. Или получить бай-ин для предоставления некоторых дополнительных ресурсов. Помните, что все мы создаем программное обеспечение для решения какой-то реальной проблемы.

Подходит ли это определение для любого случая в мире? Я не уверен. Но это помогает мне определить, когда нам нужно потратить больше времени на оптимизацию, а когда этого следует избегать.

Вполне вероятно, что бэкэнд-программа, которую вы сделаете в 2017 году, будет состоять из нескольких компонентов. Некоторые части системы могут потребовать более целенаправленных усилий из-за высокой нагрузки, о которой я упоминал. Другая часть может быть в порядке с использованием тривиальных решений, скопированных из учебника.

Ваша цель как инженера состоит в том, чтобы найти компромисс и решить это наилучшим образом для вашего бизнеса. Неважно, определяете ли вы проект как highload или нет ;).

Вы работаете над высоконагруженным проектом?

Как вы понимаете highload?


П.С. Некоторое время назад я сделал несколько докладов о highload , проверьте их, если вам интересно узнать больше по теме:

  • PyCon Ukraine 2016: Ведение высоконагруженного проекта Python для новичков
  • PyCon Poland 2016: Ведение высоконагруженного проекта Python: типичные ошибки

В вашем браузере отключен JavaScript, поэтому вы не видите комментарии под этим постом.

Разработка высоконагруженных систем — что это значит?

Высоконагруженные системы уже давно стали неотъемлемым трендом в ИТ-сфере. Термину почти десять лет, но четкого значения для него нет. Высокая нагрузка означает устойчивость интернет-проекта к высоким нагрузкам. При разработке часто возникают трудности, которые связаны с высокой нагрузкой на аппаратную и программную части. Как правило, к высоконагруженным проектам относятся социальные сети, API и платежные системы. Высоконагруженные системы разработки отвечают длинному списку требований и могут одновременно обслуживать несколько запросов.

Несколько отличительных особенностей высоконагруженных систем

Highload — это когда традиционных подходов к работе ИТ-инфраструктуры уже недостаточно. Чтобы система работала стабильно, нужно четко понимать, с какой базой данных она будет работать. В процессе проектирования архитектуры крупного приложения учитываются программные компоненты, оборудование, технические и законодательные ограничения, сроки реализации.

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

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

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

Критерии высоконагруженного проекта

С увеличением мощности сервера значения критериев меняются. Например, сейчас высоконагруженными проектами можно считать такие, которые должны выдерживать постоянную нагрузку без дополнительных манипуляций со стороны DevOps-инженеров. Стандартные критерии включают:

  • количество одновременных запросов, пиковых, асинхронных инкрементных запросов по сетевым протоколам http, https, tcp/ip, udp и socket;
  • объем обрабатываемых данных в базах данных;
  • количество информации, передаваемой в запросе.
  • защита данных пользователя от записи, кражи. Безопасность веб-сервиса требует максимального уровня защиты от утечки данных в открытый доступ.

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

PNN Soft создает свои решения уже 20 лет. Мы предлагаем качественные услуги по:

  • разработка программного обеспечения;
  • мобильные приложения;
  • аутсорсинг разработки программного обеспечения;
  • морская разработка;
  • Услуги DevOps;
  • создание дизайна UX/UI;
  • Обеспечение качества и тестирование.

Специалисты ПНН Софт не только разрабатывают информационные решения для предприятий, но и предлагают поддержку и сопровождение программных продуктов. Компания специализируется на сопровождении и сопровождении корпоративных и программных решений, десктопных, веб и мобильных приложений для Android и IOS. Также заказчику предоставляется возможность заказать цикл услуг по разработке высоконагруженных систем для различных сфер. Ведущие специалисты PNN Soft имеют большой опыт работы с высоконагруженными решениями. Мы разрабатываем устойчивые приложения, которые обслуживают большое количество пользователей. Кроме того, мы разрабатываем приложения, предполагающие одновременную обработку больших объемов данных.

This entry was posted in Популярное