Каков наилучший способ сделать веб-сайт максимально масштабируемым?

35

Для веб-сайтов, которые должны быть хорошо масштабируемыми, таких как социальные сети, такие как Facebook, каков наилучший способ дизайна сайта?

  1. Должен ли я иметь веб-сервис, который запрашивает сайт для получения необходимых данных?

    или

  2. Должен ли сайт запрашивать базы данных напрямую? (может быть сделано с использованием встроенных языковых конструкций для автоматического заполнения таблиц и т. д.).

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

Даниил
источник
Там также вопрос о том, какую архитектуру использовать (например, MVC или тому подобное).
Иван
Не зная больше о том, что именно вы собираетесь запустить, очень трудно дать ответ, но имейте в виду «облачные сервисы», возможно, ваше приложение вписывается в своего рода SaaS-приложение. (Централизовано).
Deepcell
Вообще говоря, я бы сказал, ничего особенного в виду ..
Даниил
1
Постройте его в «облаке» и проведите много времени за чтением HighScalability.com.
Эван Плейс

Ответы:

37

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

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

Я бы порекомендовал вам прочитать о работе и инструментах, созданных Брэдом Фитцпатриком (основателем LiveJournal, а теперь и в Google). Когда я работал с ним в Six Apart, вот несколько вещей, которые я узнал от него, и об архитектуре LiveJournal, которая сделала его настолько масштабируемым.

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

    Допустим, вы хотите загрузить последние 10 записей журнала в блог человека, и, скажем, каждая запись журнала имеет десять свойств. В классической широкой компоновке таблицы каждое свойство будет соответствовать столбцу таблицы. Затем пользователь будет запрашивать таблицу один раз, чтобы получить все необходимые ему данные. Запрос будет возвращать 10 строк, и каждая строка будет содержать все необходимые данные (например, SELECT * FROM записей ORDER BY date LIMIT 10). Однако в узкой таблице все немного по-другому. В этом примере фактически есть две таблицы: первая таблица (таблица A) хранит простые критерии, по которым можно было бы искать, например, идентификатор записи, идентификатор автора, дату записи и т. Д. Вторая таблица (таблица B) затем сохраняет все свойства, связанные с записью. Эта вторая таблица имеет три столбца: entry_id, ключ и значение. Для каждой строки в таблице A будет 10 строк в таблице B (одна строка для каждого свойства). Поэтому, чтобы получить и отобразить последние десять записей, вам потребуется 11 запросов. Первый запрос выдает список идентификаторов записей, а затем следующие десять запросов извлекают свойства, связанные с каждой из записей, возвращаемых в первом запросе.

    "Святой моли!" Вы говорите: «Как, черт возьми, это может быть более масштабируемым ?!» Это совершенно нелогичное право? В первом сценарии у нас был только один запрос к базе данных, но во втором «более масштабируемом» решении мы имеем 11 запросов к базе данных. Это бессмысленно. Ответ на этот вопрос полностью зависит от следующего пункта.

  2. Используйте memcache свободно. В случае, если вы не знали, memcache - это распределенная система кэширования с низкой задержкой и сетевой задержкой. Он используется Facebook, Google, Yahoo и практически всеми популярными и масштабируемыми веб-сайтами на планете. Он был изобретен Брэдом Фитцпатриком частично, чтобы помочь компенсировать издержки базы данных, присущие дизайну базы данных с узкими таблицами. Давайте посмотрим на тот же пример, который обсуждался в # 1 выше, но на этот раз давайте представим memcache.

    Давайте начнем, когда пользователь впервые заходит на страницу, а в кеше ничего нет. Вы начинаете с запроса таблицы A, которая возвращает идентификаторы 10 записей, которые вы хотите отобразить на странице. Для каждой из этих записей вы затем запрашиваете базу данных, чтобы получить свойства, связанные с этой записью, и затем используете эти свойства, образуя объект, с которым ваш код может взаимодействовать (например, объект). Затем вы прячете этот объект (или сериализованную форму этого объекта) в memcache.

    Во второй раз, когда кто-то загружает ту же страницу, вы начинаете так же: запрашивая у таблицы A список идентификаторов записей, которые вы будете отображать. Для каждой записи вы сначала заходите в memcache и говорите: «У вас есть запись #X в кэше?» Если да, то memcache возвращает вам объект ввода. Если нет, то вам нужно снова запросить базу данных, чтобы получить ее свойства, создать объект и спрятать его в memcache. В большинстве случаев, когда кто-то посещает одну и ту же страницу, только один запрос к базе данных, все остальные данные извлекаются прямо из memcache.

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

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

  3. Затем рассмотрите возможность разделения вашей базы данных. Модель, рассмотренная выше, обнаруживает еще одну проблему, а именно ваши узкие таблицы будут иметь тенденцию быть очень большими / длинными. И чем больше строк в этих таблицах, тем сложнее становятся другие административные задачи. Чтобы компенсировать это, может иметь смысл управлять размером ваших таблиц путем некоторого разбиения таблиц таким образом, чтобы кластеры пользователей обслуживались одной базой данных, а другой кластер пользователей обслуживался отдельной базой данных. Это распределяет нагрузку на базу данных и поддерживает эффективность запросов.

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

«Спасибо вам за все эти замечательные знания, но, черт возьми, это большой код, который мне придется написать».

Не обязательно. Было написано много библиотек, которые действительно облегчают взаимодействие с memcache. Еще другие библиотеки кодифицировали весь процесс, описанный выше; Data :: ObjectDriver в Perl как раз такая библиотека. Что касается других языков, вам нужно будет провести собственное исследование.

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

Бирн Риз
источник
3
+1 Мне очень нравится этот Вау, это простой вопрос, на который огромное количество возможных ответов.
Панкадж Упадхяй,
1
Я полностью не согласен с «запросить базу данных напрямую». Вы упоминаете разделение базы данных для повышения производительности, когда было бы проще реализовать архитектуру с одним ведущим и несколькими подчиненными с интерфейсом API. Преимущество отделения базы данных от приложения состоит в том, что уровень API может распределять запросы по вашему желанию. API - это абстракция, которая позволяет вам изменять базовую реализацию и / или повторно использовать данные, не нарушая приложения.
Эван Плейс,
1
(продолжение) Сериализация всегда будет увеличивать накладные расходы, но только на уровне API, который, скорее всего, будет состоять из нескольких экземпляров, работающих одновременно. Если вас беспокоит скорость передачи данных по сети, конвертируйте ее в JSON, и она, скорее всего, будет в любом случае сжата с помощью gzip. Наибольший прирост производительности можно найти, когда работа переносится с сервера на клиент. Важный вопрос, который нужно задать, - вы бы предпочли распределять запросы внутри приложения или на уровне сервера? Что легче дублировать?
Эван Плейс
1
@EvanPlaice - Отличная возможность повторного использования и изменения реализации логики сервисов при использовании сервисов. Кроме того, инфраструктура кеша также может использоваться сервисами вместо прямых вызовов базы данных.
Ашиш Гупта
1
@AshishGupta Точно, единственное отличие в разделении данных на отдельный сервис - это то, что получает пользователь. Вместо этого собираем html + контент на сервере. Пользователь получает данные и HTML отдельно, а клиентский браузер обрабатывает повторную сборку. С данными в качестве отдельной услуги также становится возможным сделать их доступными для мобильных приложений или других клиентов, не использующих веб-интерфейс (например, приложения Smart TV).
Эван Плейс
13

Для веб-сайтов, которые должны быть хорошо масштабируемыми, таких как социальные сети, такие как Facebook, каков наилучший способ дизайна сайта?

Мера.

Я думаю, что ...

Плохая политика

Требуется фактическое измерение.

С. Лотт
источник
Количественные метрики FTW.
Бхагьяс
1
Хорошо ... так что после измерения?
Pacerier
9

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

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

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

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

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

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

Мартин Аткинс
источник
4

Разработайте простой веб-сайт и дайте ему достичь определенного уровня трафика. Кроме того, вы узнаете, как создавать масштабируемые сайты.

Пока вы не столкнетесь с проблемой, вы не сможете придумать решение .

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

Панкадж Упадхяй
источник
Хорошая цитата !!!!!!!!!!
Амир Хоссейн
2

Принято считать, что веб-приложения должны разрабатываться по умолчанию с тремя уровнями - веб-уровень (презентация), уровень приложений и база данных. Это разделение обусловлено различными требованиями на каждом из уровней - как правило, качественным доступом к диску / хранилищем для базы данных, высокой загрузкой ЦП / памяти на уровне приложения и высокой внешней пропускной способностью / памятью / географической дисперсией на веб-уровне. Уровень приложения / базы данных часто объединяется в один до гораздо более позднего периода жизненного цикла приложения, поскольку компьютеры баз данных часто имеют тенденцию быть массивными серверами, которые также могут быть собраны для ранней загрузки приложения.

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

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

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

blueberryfields
источник
2

Любой дополнительный шаг при подключении к базе данных, это просто накладные расходы. Например, между UI -> Business Facade -> Business -> Data Access -> Databaseи UI -> Database, второй подход быстрее. Однако чем больше шагов вы удалите, тем меньше будет обслуживаться ваша система и тем больше будет дублирования. Представьте, что вы пишете необходимый код для получения списка друзей в профиле, на домашней странице, на странице управления друзьями и т. Д.

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

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

  1. Выбор правильной платформы (PHP быстрее из-за своей скриптовой природы, но ASP.NET необходимо скомпилировать запрошенный файл на лету, чтобы обработать его и обработать что-то. Также заявлено, что node.js является более масштабируемым из-за его callback- основанная архитектура )
  2. Использование архитектуры RESTful вместо модели веб-сервиса (SOA)
  3. Использование JSON для передачи данных вместо XML (что приводит к меньшему количеству байтов для передачи)
  4. Следуя рекомендациям по производительности Yahoo
  5. Сетевые и аппаратные темы, такие как балансировка нагрузки или многоуровневая архитектура
Саид Нямати
источник
2
Вы не можете сказать, что PHP быстрее. Правильно написанные приложения ASP.NET могут превзойти PHP во многих случаях. naspinski.net/post/AspNet-vs-php--speed-comparison.aspx
Эндрю Льюис,
+1 На самом деле ваше «простое» решение будет: UI -> Доступ к данным -> База данных. 2 REST «прост», потому что он уже встроен в большинство браузеров. Нет необходимости воссоздавать колесо API команды-ответа. 3 Мало того, что JSON меньше, но он требует меньше шагов для сериализации-десериализации, потому что вам не нужно проверять сущности HTML. Хорошая вещь.
Эван Плейс
1

Существует два основных способа масштабирования: увеличение и уменьшение.

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

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

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

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

Джон Рейнор
источник
0

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

bhagyas
источник