По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие наши статьи:
img
Почитайте предыдущую статью из цикла про установление и прекращение соединения в TCP. UDP предоставляет приложениям сервис для обмена сообщениями. В отличие от TCP, UDP не требует установления соединения и не обеспечивает надежности, работы с окнами, переупорядочивания полученных данных и сегментации больших фрагментов данных на нужный размер для передачи. Однако UDP предоставляет некоторые функции TCP, такие как передача данных и мультиплексирование с использованием номеров портов, и делает это с меньшим объемом служебных данных и меньшими затратами на обработку, чем TCP. Передача данных UDP отличается от передачи данных TCP тем, что не выполняется переупорядочевание или восстановление. Приложения, использующие UDP, толерантны к потерянным данным, или у них есть какой-то прикладной механизм для восстановления потерянных данных. Например, VoIP использует UDP, потому что, если голосовой пакет потерян, к тому времени, когда потеря может быть замечена и пакет будет повторно передан, произойдет слишком большая задержка, и голос будет неразборчивым. Кроме того, запросы DNS используют UDP, потому что пользователь будет повторять операцию, если разрешение DNS не удается. В качестве другого примера, сетевая файловая система (NFS), приложение удаленной файловой системы, выполняет восстановление с помощью кода уровня приложения, поэтому функции UDP приемлемы для NFS. На рисунке 10 показан формат заголовка UDP. Самое главное, обратите внимание, что заголовок включает поля порта источника и назначения для той же цели, что и TCP. Однако UDP имеет только 8 байтов по сравнению с 20-байтовым заголовком TCP, показанным на рисунке 1-1. UDP требует более короткого заголовка, чем TCP, просто потому, что у UDP меньше работы. Приложения TCP / IP Вся цель построения корпоративной сети или подключения небольшой домашней или офисной сети к Интернету состоит в использовании таких приложений, как просмотр веб-страниц, обмен текстовыми сообщениями, электронная почта, загрузка файлов, голос и видео. В этом подразделе исследуется одно конкретное приложение - просмотр веб-страниц с использованием протокола передачи гипертекста (HTTP). Всемирная паутина (WWW) состоит из всех подключенных к Интернету веб-серверов в мире, а также всех подключенных к Интернету хостов с веб-браузерами. Веб-серверы, которые состоят из программного обеспечения веб-сервера, запущенного на компьютере, хранят информацию (в виде веб-страниц), которая может быть полезна для разных людей. Веб-браузер, представляющий собой программное обеспечение, установленное на компьютере конечного пользователя, предоставляет средства для подключения к веб-серверу и отображения веб-страниц, хранящихся на веб-сервере. Хотя большинство людей используют термин "веб-браузер" или просто "браузер", веб-браузеры также называются веб-клиентами, потому что они получают услугу с веб-сервера. Чтобы этот процесс работал, необходимо выполнить несколько определенных функций прикладного уровня. Пользователь должен каким-то образом идентифицировать сервер, конкретную веб-страницу и протокол, используемый для получения данных с сервера. Клиент должен найти IP-адрес сервера на основе имени сервера, обычно используя DNS. Клиент должен запросить веб-страницу, которая на самом деле состоит из нескольких отдельных файлов, а сервер должен отправить файлы в веб-браузер. Наконец, для приложений электронной коммерции (электронной коммерции) передача данных, особенно конфиденциальных финансовых данных, должна быть безопасной. В следующих подразделах рассматривается каждая из этих функций. Унифицированные идентификаторы ресурсов Чтобы браузер отображал веб-страницу, он должен идентифицировать сервер, на котором находится эта веб-страница, а также другую информацию, которая идентифицирует конкретную веб-страницу. Большинство веб-серверов имеют множество веб-страниц. Например, если вы используете веб-браузер для просмотра www.cisco.com и щелкаете по этой веб-странице, вы увидите другую веб-страницу. Щелкните еще раз, и вы увидите другую веб-страницу. В каждом случае щелчок идентифицирует IP-адрес сервера, а также конкретную веб-страницу, при этом детали в основном скрыты от вас. (Эти интерактивные элементы на веб-странице, которые, в свою очередь, переводят вас на другую веб-страницу, называются ссылками.) Пользователь браузера может идентифицировать веб-страницу, когда вы щелкаете что-либо на веб-странице или когда вы вводите унифицированный идентификатор ресурса (URI) в адресную область браузера. Оба варианта - щелчок по ссылке и ввод URI - относятся к URI, потому что, когда вы щелкаете ссылку на веб-странице, эта ссылка фактически ссылается на URI. Большинство браузеров поддерживают какой-либо способ просмотра скрытого URI, на который ссылается ссылка. В некоторых браузерах наведите указатель мыши на ссылку, щелкните правой кнопкой мыши и выберите "Свойства". Во всплывающем окне должен отображаться URI, на который будет направлен браузер, если вы нажмете эту ссылку. В просторечии многие люди используют термины веб-адрес или аналогичные связанные термины Universal Resource Locator (или Uniform Resource Locator [URL]) вместо URI, но URI действительно является правильным формальным термином. Фактически, URL-адрес используется чаще, чем URI, уже много лет. Однако IETF (группа, определяющая TCP / IP) вместе с консорциумом W3C (W3.org, консорциум, разрабатывающий веб-стандарты) предприняли согласованные усилия по стандартизации использования URI в качестве общего термина. С практической точки зрения, URI, используемые для подключения к веб-серверу, включают три ключевых компонента, как показано на рисунке 11. На рисунке показаны формальные имена полей URI. Что еще более важно для понимания, обратите внимание, что текст перед :// определяет протокол, используемый для подключения к серверу, текст между // и / идентифицирует сервер по имени, а текст после / идентифицирует веб-страницу. В этом случае используется протокол передачи гипертекста (HTTP), имя хоста - www.certskills.com, а имя веб-страницы - blog. Поиск веб-сервера с помощью DNS Хост может использовать DNS для обнаружения IP-адреса, соответствующего определенному имени хоста. В URI обычно указывается имя сервера - имя, которое можно использовать для динамического изучения IP-адреса, используемого этим же сервером. Веб-браузер не может отправить IP-пакет на имя назначения, но он может отправить пакет на IP-адрес назначения. Итак, прежде чем браузер сможет отправить пакет на веб-сервер, браузеру обычно необходимо преобразовать имя внутри URI в соответствующий IP-адрес этого имени. Чтобы собрать воедино несколько концепций, на рисунке 12 показан процесс DNS, инициированный веб-браузером, а также некоторая другая связанная информация. С базовой точки зрения пользователь вводит URI (в данном случае http://www.exempel.com/go/learningnetwork), преобразует имя www.exempel.com в правильный IP-адрес и начинает отправлять пакеты на веб сервер. Шаги, показанные на рисунке, следующие: Пользователь вводит URI http://www.exempel.com/go/learningnetwork в адресную область браузера. Клиент отправляет DNS-запрос на DNS-сервер. Обычно клиент узнает IP-адрес DNS-сервера через DHCP. Обратите внимание, что запрос DNS использует заголовок UDP с портом назначения 53-го известного порта DNS (см. таблицу 2 ранее в этой лекции, где приведен список популярных хорошо известных портов). DNS-сервер отправляет ответ, в котором IP-адрес 198.133.219.25 указан как IP-адрес www.exemple.com. Также обратите внимание, что ответ показывает IP-адрес назначения 64.100.1.1, IP-адрес клиента. Он также показывает заголовок UDP с портом источника 53; исходный порт - 53, потому что данные получены или отправлены DNS-сервером. Клиент начинает процесс установления нового TCP-соединения с веб-сервером. Обратите внимание, что IP-адрес назначения - это только что изученный IP-адрес веб-сервера. Пакет включает заголовок TCP, потому что HTTP использует TCP. Также обратите внимание, что TCP-порт назначения - 80, хорошо известный порт для HTTP. Наконец, отображается бит SYN, как напоминание о том, что процесс установления TCP-соединения начинается с сегмента TCP с включенным битом SYN (двоичная 1). Пример на рисунке 12 показывает, что происходит, когда клиентский хост не знает IP-адрес, связанный с именем хоста, но предприятие знает адрес. Однако хосты могут кэшировать результаты DNS-запросов, так что какое-то время клиенту не нужно запрашивать DNS для разрешения имени. Также DNS-сервер может кэшировать результаты предыдущих DNS-запросов; например, корпоративный DNS-сервер на рисунке 12 обычно не имеет настроенной информации об именах хостов в доменах за пределами этого предприятия, поэтому в этом примере DNS-сервер кэшировал адрес, связанный с именем хоста www.example.com. Когда локальный DNS не знает адрес, связанный с именем хоста, ему необходимо обратиться за помощью. На рисунке 13 показан пример с тем же клиентом, что и на рисунке 12. В этом случае корпоративный DNS действует как рекурсивный DNS-сервер, отправляя повторяющиеся DNS-сообщения, чтобы идентифицировать авторитетный DNS-сервер. Шаги, показанные на рисунке, следующие: Клиент отправляет DNS-запрос для www.exemple.com на известный ему DNS-сервер, который является корпоративным DNS-сервером. (Рекурсивный) корпоративный DNS-сервер еще не знает ответа, но он не отклоняет DNS-запрос клиента. Вместо этого он следует повторяющемуся (рекурсивному) процессу (показанному как шаги 2, 3 и 4), начиная с DNS-запроса, отправленного на корневой DNS-сервер. Корень также не предоставляет адрес, но он предоставляет IP-адрес другого DNS-сервера, ответственного за домен верхнего уровня .com. Рекурсивный корпоративный DNS-сервер отправляет следующий DNS-запрос DNS-серверу, полученному на предыдущем шаге, - на этот раз DNS-серверу TLD для домена .com. Этот DNS также не знает адреса, но знает DNS-сервер, который должен быть официальным DNS-сервером для домена exemple.com, поэтому он предоставляет адрес этого DNS-сервера. Корпоративный DNS отправляет другой DNS-запрос DNS-серверу, адрес которого был получен на предыдущем шаге, снова запрашивая разрешение имени www.exeple.com. Этот DNS-сервер, официальный сервер exemple.com, предоставляет адрес. Корпоративный DNS-сервер возвращает DNS-ответ клиенту, предоставляя IP-адрес, запрошенный на шаге 1. Передача файлов по HTTP После того, как веб-клиент (браузер) создал TCP-соединение с веб-сервером, клиент может начать запрашивать веб-страницу с сервера. Чаще всего для передачи веб-страницы используется протокол HTTP. Протокол прикладного уровня HTTP, определенный в RFC 7230, определяет, как файлы могут передаваться между двумя компьютерами. HTTP был специально создан для передачи файлов между веб-серверами и веб-клиентами. HTTP определяет несколько команд и ответов, из которых наиболее часто используется запрос HTTP GET. Чтобы получить файл с веб-сервера, клиент отправляет на сервер HTTP-запрос GET с указанием имени файла. Если сервер решает отправить файл, он отправляет ответ HTTP GET с кодом возврата 200 (что означает ОК) вместе с содержимым файла. Для HTTP-запросов существует множество кодов возврата. Например, если на сервере нет запрошенного файла, он выдает код возврата 404, что означает "файл не найден". Большинство веб-браузеров не показывают конкретные числовые коды возврата HTTP, вместо этого отображая ответ, такой как "страница не найдена", в ответ на получение кода возврата 404. Веб-страницы обычно состоят из нескольких файлов, называемых объектами. Большинство веб-страниц содержат текст, а также несколько графических изображений, анимированную рекламу и, возможно, видео и звук. Каждый из этих компонентов хранится как отдельный объект (файл) на веб-сервере. Чтобы получить их все, веб-браузер получает первый файл. Этот файл может (и обычно делает) включать ссылки на другие URI, поэтому браузер затем также запрашивает другие объекты. На рисунке 14 показана общая идея, когда браузер получает первый файл, а затем два других. В этом случае, после того, как веб-браузер получает первый файл - тот, который в URI называется "/go/ccna", браузер читает и интерпретирует этот файл. Помимо частей веб-страницы, файл ссылается на два других файла, поэтому браузер выдает два дополнительных запроса HTTP GET. Обратите внимание, что, даже если это не показано на рисунке, все эти команды проходят через одно (или, возможно, несколько) TCP-соединение между клиентом и сервером. Это означает, что TCP обеспечит исправление ошибок, гарантируя доставку данных. Как принимающий хост определяет правильное принимающее приложение Эта лекция завершается обсуждением процесса, с помощью которого хост при получении любого сообщения по любой сети может решить, какая из множества своих прикладных программ должна обрабатывать полученные данные. В качестве примера рассмотрим хост A, показанный слева на рисунке 15. На хосте открыто три разных окна веб-браузера, каждое из которых использует уникальный TCP-порт. На хосте A также открыт почтовый клиент и окно чата, оба из которых используют TCP. И электронная почта, и чат-приложения используют уникальный номер TCP-порта на хосте A, как показано на рисунке. В этой части лекции показано несколько примеров того, как протоколы транспортного уровня используют поле номера порта назначения в заголовке TCP или UDP для идентификации принимающего приложения. Например, если значение TCP-порта назначения на рисунке 15 равно 49124, хост A будет знать, что данные предназначены для первого из трех окон веб-браузера. Прежде чем принимающий хост сможет проверить заголовок TCP или UDP и найти поле порта назначения, он должен сначала обработать внешние заголовки в сообщении. Если входящее сообщение представляет собой кадр Ethernet, который инкапсулирует пакет IPv4, заголовки выглядят так, как показано на рисунке 16. Принимающему узлу необходимо просмотреть несколько полей, по одному на заголовок, чтобы идентифицировать следующий заголовок или поле в полученном сообщении. Например, хост A использует сетевой адаптер Ethernet для подключения к сети, поэтому полученное сообщение представляет собой кадр Ethernet. Поле типа Ethernet определяет тип заголовка, который следует за заголовком Ethernet - в данном случае со значением шестнадцатеричного значения 0800, заголовком IPv4. Заголовок IPv4 имеет аналогичное поле, называемое полем протокола IP. Поле протокола IPv4 имеет стандартный список значений, которые идентифицируют следующий заголовок, с десятичным числом 6, используемым для TCP, и десятичным числом 17, используемым для UDP. В этом случае значение 6 определяет заголовок TCP, следующий за заголовком IPv4. Как только принимающий хост понимает, что заголовок TCP существует, он может обработать поле порта назначения, чтобы определить, какой процесс локального приложения должен получить данные. Теперь вас ждет материал про списки управления доступом IPv4
img
Что такое парадигмы программирования? Это не более, чем просто замысловатое название для популярных способов и стилей организации процесса написания программного кода. Я постараюсь разбить эту тему на части и дать простое пояснение по каждой парадигме. Таким образом, вы сможете легко понять, о чем говорят люди, когда произносят такие слова, как «объектно-ориентированный», «функциональный» или «декларативный». Давайте начнем! Что такое парадигма программирования? Парадигмы программирования – это различные способы и стили, которые используются для организации программы или языка программирования. Каждая парадигма состоит из определенных структур, функций и взглядов на то, как следует решать известные задачи программирования. Вопрос о том, почему существует так много различных парадигм программирования, схож с вопросом о том, почему существует так много языков программирования. Определенные парадигмы лучше подходят для определенных типов задач. Именно поэтому имеет смысл использовать разные парадигмы для разных типов проектов. Кроме того, методики, которые составляют каждую парадигму, развивались с течением времени. Благодаря достижениям как в области программного, так и аппаратного обеспечения появились различные подходы к решению задач, которых раньше просто не было. И последняя причина – я думаю, это просто творческое начало в человеке. По своей натуре, нам просто нравится создавать новые вещи, улучшать то, что другие когда-то создали, и адаптировать инструменты под себя и свои предпочтения или просто делать их более эффективными (в нашем понимании). Все это привело к тому, что на сегодняшний день мы имеем огромное количество вариантов, которые могут помочь нам написать и структурировать ту или иную программу. Чем парадигма программирования не является? Парадигмы программирования – это не языки и не инструменты. Вы не сможете ничего «создать» с помощью парадигмы. Они больше похожи на некий набор образцов и руководящих принципов, о которых условились большое количество людей, которым они следовали и которые они подробно изложили. Язык программирования не всегда привязан к определенной парадигме. Есть языки, которые были созданы с учетом определенной парадигмы и имеют функции, которые облегчают программирование в этом контексте больше, чем другие (хороший пример – Haskel и функциональное программирование). Однако существуют и «многопарадигмальные» языки. Это означает, что вы можете адаптировать свой код, чтобы он подходил под какую-то из парадигм (хороший пример – JavaScript и Python). При этом парадигмы программирования не являются взаимоисключающими в том смысле, что вы можете без каких-либо проблем использовать приемы из различных парадигм одновременно. Популярные парадигмы программирования Теперь, когда вы знаете, что такое парадигмы программирования, а что к ним не относится, давайте рассмотрим самые популярные из них, их характеристики и сравним их. Имейте в виду, что этот список не полный. Существуют и другие парадигмы программирования, которые мы здесь рассматривать не будем. Здесь я расскажу вам только о самых популярных и широко используемых. Императивное программирование Императивное программирование – это набор подробных инструкций, которые даются компьютеру, чтобы тот выполнил их в заданном порядке. Этот тип программирования называется «императивным», потому что мы некоторым образом указываем компьютеру (как программисты), что он должен делать. Императивное программирование концентрируется на описании того, как программа работает, шаг за шагом. Допустим, вы хотите испечь торт. Ваша императивная программа для такого рода задачи может выглядеть следующим образом: 1- Pour flour in a bowl 2- Pour a couple eggs in the same bowl 3- Pour some milk in the same bowl 4- Mix the ingredients 5- Pour the mix in a mold 6- Cook for 35 minutes 7- Let chill Воспользуемся конкретным примером и предположим, что мы хотим отфильтровать массив чисел так, чтобы остались только числа, которые больше 5. Наш императивный код тогда будет выглядеть следующим образом: const nums = [1,4,3,6,7,8,9,2] const result = [] for (let i = 0; i < nums.length; i++) { if (nums[i] > 5) result.push(nums[i]) } console.log(result) // Output: [ 6, 7, 8, 9 ] Обратите внимание, что мы указываем программе, что нужно перебрать каждый элемент массива, сравнить каждый из них с 5 и, если элемент больше 5, то поместить его в конечный массив. Наши инструкции предельно детализированы и конкретны, и именно это и является императивным программированием. Процедурное программирование Процедурное программирование – это производное от императивного программирования только с функциями (также известных как «процедуры» или «подпрограммы»). Процедурное программирования предлагает пользователю разделить выполнение программы на функции, чтобы оптимизировать модульный принцип организации. Вернемся к нашему примеру с тортом. Процедурная программа для этого примера будет выглядеть следующим образом: function pourIngredients() { - Pour flour in a bowl - Pour a couple eggs in the same bowl - Pour some milk in the same bowl } function mixAndTransferToMold() { - Mix the ingredients - Pour the mix in a mold } function cookAndLetChill() { - Cook for 35 minutes - Let chill } pourIngredients() mixAndTransferToMold() cookAndLetChill() Как вы можете видеть, благодаря реализации функций, мы можем просто прочитать три вызова функций в конце файла и понять, что делает наша программа. Такое упрощение и абстрактное представление является одним из преимуществ процедурного программирования. Однако внутри функций находится все тот же императивный код. Функциональное программирование Функциональное программирование продвигает концепцию создания функций немного дальше. В функциональном программировании функции рассматриваются как «полноправные граждане». Это означает, что их можно присваивать переменным, передавать в качестве аргумента и возвращать в качестве результата других функций. Еще одна ключевая концепция – это идея чистых функций. Чистая функций – это функция, которая, чтобы получить результат, полагается только на свои входные данные. И при одних и тех же входных данных всегда будет один и тот же результат. Кроме того, эти функции не имеют никаких побочных эффектов (то есть не вносят никаких изменений вне контекста функции). С учетом всех этих концепций, функциональное программирование призывает писать программы с помощью функций. Оно также поддерживает идею о том, что модульность кода и отсутствие побочных эффектов облегчают определение и разделение обязанностей внутри кодовой базы. Таким образом, это облегчает сопровождение кода. Вернемся к примеру с фильтрацией массива. В императивной парадигме мы можем использовать внешнюю переменную для хранения результата функции, что по сути может считаться побочным эффектом. const nums = [1,4,3,6,7,8,9,2] const result = [] // External variable for (let i = 0; i < nums.length; i++) { if (nums[i] > 5) result.push(nums[i]) } console.log(result) // Output: [ 6, 7, 8, 9 ] Для того, чтобы преобразовать это в функциональное программирование, мы можем сделать следующее: const nums = [1,4,3,6,7,8,9,2] function filterNums() { const result = [] // Internal variable for (let i = 0; i < nums.length; i++) { if (nums[i] > 5) result.push(nums[i]) } return result } console.log(filterNums()) // Output: [ 6, 7, 8, 9 ] Это практически тот же самый код, но мы проворачиваем все итерации внутри функции, в которой мы также сохраняем и массив результатов. Таким образом, мы можем гарантировать, что функция не будет ничего менять за своими пределами. Она создает переменную только для обработки своей собственной информации, и после завершения своей работы удаляет ее. Декларативное программирование Декларативное программирование скрывает всю сложность и приближает языки программирования к человеческому языку и мышлению. Это абсолютная противоположность императивному программированию, хотя бы потому что программист дает инструкции не о том, как компьютеру следует решать задачу, а о том, какой требуется результат. Будет намного понятнее, если мы приведем пример. Воспользуемся примером с фильтрацией массива. Декларативный подход здесь будет выглядеть следующим образом: const nums = [1,4,3,6,7,8,9,2] console.log(nums.filter(num => num > 5)) // Output: [ 6, 7, 8, 9 ] Обратите внимание, что, используя функцию фильтрации filter, мы явно не указываем компьютеру перебирать массив или сохранять значения в отдельном массиве. Мы просто говорим о том, что мы хотим («filter») и условие, которое необходимо выполнить («num > 5»). Что хорошего в таком подходе? Его легче читать и понимать, и зачастую он более емкий в записи. Хорошими примерами декларативного кода являются функции filter, map, reduce и sort в JavaScript. Еще один хороший пример – современные фреймворки/библиотеки JS, такие как React. Посмотрите, например, на этот код: <button onClick={() => console.log('You clicked me!')}>Click me</button> Здесь у нас есть кнопка (button) с приемником событий, который запускает функцию console.log при нажатии кнопки. Синтаксис JSX (то, что использует React) совмещает HTML и JS. Это упрощает и ускоряет написание приложений. Но это не то, что браузеры читают и выполняют. Код React позже преобразуются в обычный HTML и JS, а вот это уже то, с чем работают браузеры. JSX является декларативным, поскольку его цель заключается в том, чтобы предоставить разработчикам более удобный и эффективный интерфейс для работы. Здесь также важно отметить, что в декларативном программировании компьютер все равно обрабатывает информацию как императивный код. Если снова вернуться к примеру с массивом, то компьютер по-прежнему выполняет итерацию по массиву, как в цикле for, но нам, как программистам, не нужно писать это напрямую. Декларативное программирование скрывает всю сложность от программиста. Объектно-ориентированное программирование Одной из самых популярных парадигм программирование является объектно-ориентированное программирование (ООП). Основная концепция ООП заключается в разделении понятий на сущности, которые описываются как некие объекты. Каждая сущность группирует заданный набор информации (свойств) и действий (методов), которые может выполнять эта сущность. ООП широко использует классы. Классы - это способ создания новых объектов с помощью макета или шаблона, который задает программист. Объекты, которые были созданы с помощью класса, называются экземплярами. Вернемся к примеру с приготовлением пищи на псевдокоде. Предположим, что в нашей пекарне у нас есть главный повар (по имени Фрэнк) и помощник повара (по имени Энтони). У каждого их них есть определенные обязанности. Если бы мы использовали ООП, то наша программа бы выглядеть следующим образом: // Create the two classes corresponding to each entity class Cook { constructor constructor (name) { this.name = name } mixAndBake() { - Mix the ingredients - Pour the mix in a mold - Cook for 35 minutes } } class AssistantCook { constructor (name) { this.name = name } pourIngredients() { - Pour flour in a bowl - Pour a couple eggs in the same bowl - Pour some milk in the same bowl } chillTheCake() { - Let chill } } // Instantiate an object from each class const Frank = new Cook('Frank') const Anthony = new AssistantCook('Anthony') // Call the corresponding methods from each instance Anthony.pourIngredients() Frank.mixAndBake() Anthony.chillTheCake() Преимущество ООП заключается в том, что оно облегчает понимание программы за счет четкого разделения задач и обязанностей. Итоги Как мы увидели, парадигмы программирования – это различные способы решения задач программирования и организации нашего кода. Одними из самых популярных и широко используемых на сегодняшний день парадигм являются императивная, процедурная, функциональная, декларативная и объектно-ориентированная. Знание о том, что они из себя представляют, полезно для общего развития, а также для лучшего понимания других тем, связанных с программированием.
img
Первая часть тут Как только изменение в топологии сети было обнаружено, оно должно быть каким-то образом распределено по всем устройствам, участвующим в плоскости управления. Каждый элемент в топологии сети может быть описан как: Канал или граница, включая узлы или достижимые места назначения, прикрепленные к этому каналу. Устройство или узел, включая узлы, каналы и доступные места назначения, подключенные к этому устройству. Этот довольно ограниченный набор терминов может быть помещен в таблицу или базу данных, часто называемую таблицей топологии или базой данных топологии. Таким образом, вопрос о распределении изменений в топологии сети на все устройства, участвующие в плоскости управления, можно описать как процесс распределения изменений в определенных строках в этой таблице или базе данных по всей сети. Способ, которым информация распространяется по сети, конечно, зависит от конструкции протокола, но обычно используются три вида распространения: поэтапное (hop-by-hop) распространение, лавинное (flooded) распространение и централизованное (centralized) хранилище некоторого вида. Лавинное (flooded) распространение. При лавинной рассылке каждое устройство, участвующее в плоскости управления, получает и сохраняет копию каждой части информации о топологии сети и доступных местах назначения. Хотя существует несколько способов синхронизации базы данных или таблицы, в плоскостях управления обычно используется только один: репликация на уровне записи. Рисунок 6 иллюстрирует это. На рисунке 6 каждое устройство будет рассылать известную ему информацию ближайшим соседям, которые затем повторно рассылают информацию своим ближайшим соседу. Например, A знает две специфические вещи о топологии сети: как достичь 2001: db8: 3e8: 100 :: / 64 и как достичь B. A передает эту информацию в B, который, в свою очередь, передает эту информацию в C. Каждое устройство в сети в конечном итоге получает копию всей доступной топологической информации; A, B и C имеют синхронизированные базы данных топологии (или таблицы). На рисунке 6 связь C с D показана как элемент в базе данных. Не все плоскости управления будут включать эту информацию. Вместо этого C может просто включать подключение к диапазону адресов 2001: db8: 3e8: 102 :: / 64 (или подсети), который содержит адрес D. Примечание. В более крупных сетях невозможно уместить все описание подключений устройства в один пакет размером с MTU, и для обеспечения актуальности информации о подключении необходимо регулярно задерживать время ожидания и повторно загружать данные. Интересная проблема возникает в механизмах распространения Flooding рассылки, которые могут вызывать временные петли маршрутизации, называемые microloops. Рисунок 7 демонстрирует эту ситуацию. На рисунке 7, предположим, что канал [E, D] не работает. Рассмотрим следующую цепочку событий, включая примерное время для каждого события: Старт: A использует E, чтобы добраться до D; C использует D, чтобы добраться до E. 100 мс: E и D обнаруживают сбой связи. 500 мс: E и D рассылают информацию об изменении топологии на C и A. 750 мс: C и A получают обновленную информацию о топологии. 1000 мс: E и D пересчитывают свои лучшие пути; E выбирает A как лучший путь для достижения D, D выбирает C как лучший путь для достижения E. 1,250 мс: лавинная рассылка A и C информации об изменении топологии на B. 1400 мс: A и C пересчитывают свои лучшие пути; A выбирает B для достижения D, C выбирает B для достижения E. 1500 мс: B получает обновленную информацию о топологии. 2,000 мс: B пересчитывает свои лучшие пути; он выбирает C, чтобы достичь D, и A, чтобы достичь E. Хотя время и порядок могут незначительно отличаться в каждой конкретной сети, порядок обнаружения, объявления и повторных вычислений почти всегда будет следовать аналогичной схеме. В этом примере между этапами 5 и 7 образуется микропетля; в течение 400 мс, A использует E для достижения D, а E использует A для достижения D. Любой трафик, входящий в кольцо в A или D в течение времени между пересчетом E лучшего пути к D и пересчетом A лучшего пути к D будет петлей. Одним из решений этой проблемы является предварительное вычисление альтернативных вариантов без петель или удаленных альтернатив без петель. Hop by Hop При поэтапном распределении каждое устройство вычисляет локальный лучший путь и отправляет только лучший путь своим соседям. Рисунок 8 демонстрирует это. На рисунке 8 каждое устройство объявляет информацию о том, что может достигнуть каждого из своих соседей. D, например, объявляет о достижимости для E, а B объявляет о доступности для C, D и E для A. Интересно рассмотреть, что происходит, когда A объявляет о своей доступности для E через канал на вершине сети. Как только E получит эту информацию, у него будет два пути к B, например: один через D и один через A. Таким же образом у A будет два пути к B: один напрямую к B, а другой через E. Любой из алгоритмов кратчайшего пути, рассмотренные в предыдущих статьях, могут определить, какой из этих путей использовать, но возможно ли формирование микропетель с помощью лавинного механизма распределения? Рассмотрим: E выбирает путь через A, чтобы добраться до B. Канал [A, B] не работает. A обнаруживает этот сбой и переключается на путь через E. Затем A объявляет этот новый путь к E. E получает информацию об измененной топологии и вычисляет новый лучший путь через D. В промежутке между шагами 3 и 5 А будет указывать на Е как на свой лучший путь к В, в то время как Е будет указывать на А как на свой лучший путь к В—микропетля. Большинство распределительных систем hop-by-hop решают эту проблему с помощью split horizon или poison reverse. Определены они следующим образом: Правило split horizon гласит: устройство не должно объявлять о доступности к пункту назначения, который он использует для достижения пункта назначения. Правило poison reverse гласит: устройство должно объявлять пункты назначения по отношению к соседнему устройству, которое оно использует, чтобы достичь пункта назначения с бесконечной метрикой. Если разделение горизонта (split horizon) реализованный на рисунке 8, E не будет объявлять о достижимости для B, поскольку он использует путь через A для достижения B. В качестве альтернативы E может отравить путь к B через A, что приведет к тому, что A не будет иметь пути через E к B. Централизованное Хранилище. В централизованной системе каждое сетевое устройство сообщает информацию об изменениях топологии и достижимости контроллеру или, скорее, некоторому набору автономных служб и устройств, действующих в качестве контроллера. В то время как централизация часто вызывает идею единого устройства (или виртуального устройства), которому передается вся информация и который передает правильную информацию для пересылки всем устройствам обработки пакетов в сети, это чрезмерное упрощение того, что на самом деле означает централизованная плоскость управления. Рисунок 9 демонстрирует это. На рисунке 9, когда канл между D и F не работает: D и F сообщают об изменении топологии контроллеру Y. Y пересылает эту информацию другому контроллеру X. Y вычисляет лучший путь к каждому месту назначения без канала [D, F] и отправляет его каждому затронутому устройству в сети. Каждое устройство устанавливает эту новую информацию о пересылке в свою локальную таблицу. Конкретный пример шага 3 - Y вычисляет следующий лучший путь к E без канала [D, F] и отправляет его D для установки в его локальной таблице пересылки. Могут ли микропетли образовываться в централизованной плоскости управления? Базы данных в X и Y должны быть синхронизированы, чтобы оба контроллера вычисляли одинаковые пути без петель в сети Синхронизация этих баз данных повлечет за собой те же проблемы и (возможно) использование тех же решений, что и решения, обсуждавшиеся до сих пор в этой статье. Подключенным устройствам потребуется некоторое время, чтобы обнаружить изменение топологии и сообщить об этом контроллеру. Контроллеру потребуется некоторое время, чтобы вычислить новые пути без петель. Контроллеру потребуется некоторое время, чтобы уведомить затронутые устройства о новых путях без петель в сети. Во время временных интервалов, описанных здесь, сеть все еще может образовывать микропетли. Централизованная плоскость управления чаще всего переводится в плоскость управления не запущенными устройствами переадресации трафика. Хотя они могут казаться радикально разными, централизованные плоскости управления на самом деле используют многие из тех же механизмов для распределения топологии и достижимости, а также те же алгоритмы для вычисления безцикловых путей через сеть, что и распределенные плоскости управления. Плоскости сегментирования и управления. Одна интересная идея для уменьшения состояния, переносимого на любое отдельное устройство, независимо от того, используется ли распределенная или централизованная плоскость управления, заключается в сегментировании информации в таблице топологии (или базе данных). Сегментация-это разделение информации в одной таблице на основе некоторого свойства самих данных и хранение каждого полученного фрагмента или фрагмента базы данных на отдельном устройстве. Рисунок 10 демонстрирует это. В сети на рисунке 10 предположим, что оба контроллера, X и Y, имеют информацию о топологии для всех узлов (устройств) и ребер (каналов) в сети. Однако для масштабирования размера сети доступные места назначения были разделены на два контроллера. Существует множество возможных схем сегментирования - все, что может разделить базу данных (или таблицу) на части примерно одинакового размера, будет работать. Часто используется хеш, так как хеши можно быстро изменить на каждом устройстве, где хранится сегмент, чтобы сбалансировать размеры сегментов. В этом случае предположим, что схема сегментирования немного проще: это диапазон IP-адресов. В частности, на рисунке представлены два диапазона IP-адресов: 2001: db8: 3e8: 100 :: / 60, который содержит от 100 :: / 64 до 10f :: / 64; и 2001: db8: 3e8: 110 :: / 60, который содержит от 110 :: / 64 до 11f :: / 64. Каждый из этих диапазонов адресов разделен на один контроллер; X будет содержать информацию о 2001: db8: 3e8: 100 :: / 60, а Y будет содержать информацию о 2001: db8: 3e8: 110 :: / 64. Не имеет значения, где эти доступные пункты назначения подключены к сети. Например, информация о том, что 2001: db8: 3e8: 102 :: / 64 подключен к F, будет храниться в контроллере X, а информация о том, что 2001: db8: 3e8: 110 :: / 64 подключен к A, будет храниться на контроллере Y. Чтобы получить информацию о доступности для 2001: db8: 3e8: 102 :: / 64, Y потребуется получить информацию о том, где этот пункт назначения соединен с X. Это будет менее эффективно с точки зрения вычисления кратчайших путей, но он будет более эффективным с точки зрения хранения информации, необходимой для вычисления кратчайших путей. Фактически, возможно, если информация хранится правильно (а не тривиальным способом, используемым в этом примере), чтобы несколько устройств вычислили разные части кратчайшего пути, а затем обменивались только результирующим деревом друг с другом. Это распределяет не только хранилище, но и обработку. Существует несколько способов, с помощью которых информация о плоскости управления может быть разделена, сохранена и, когда вычисления выполняются через нее, чтобы найти набор путей без петель через сеть. Согласованность, доступность и возможность разделения. Во всех трех системах распределения, обсуждаемых в этой статье, - лавинной, поэтапной и централизованных хранилищ - возникает проблема микропетель. Протоколы, реализующие эти методы, имеют различные системы, такие как разделение горизонта и альтернативы без петель, чтобы обходить эти микропетли, или они позволяют микропетлям появляться, предполагая, что последствия будут небольшими для сети. Существует ли объединяющая теория или модель, которая позволит инженерам понять проблемы, связанные с распределением данных по сети, и различные сопутствующие компромиссы? Есть: теорема CAP. В 2000 году Эрик Брюер, занимаясь как теоретическими, так и практическими исследованиями, постулировал, что распределенная база данных обладает тремя качествами: Согласованностью, Доступностью и устойчивость к разделению (Consistency, Accessibility Partition tolerance-CAP). Между этими тремя качествами всегда есть компромисс, так что вы можете выбрать два из трех в любой структуре системы. Эта гипотеза, позже доказанная математически, теперь известна как теорема CAP. Эти три термина определяются как: Согласованность: Каждый считыватель видит согласованное представление содержимого базы данных. Если какое-то устройство С записывает данные в базу данных за несколько мгновений до того, как два других устройства, А и В, прочитают данные из базы данных, оба считывателя получат одну и ту же информацию. Другими словами, нет никакой задержки между записью базы данных и тем, что оба считывателя, А и В, могут прочитать только что записанную информацию. Доступность: каждый считыватель имеет доступ к базе данных при необходимости (почти в реальном времени). Ответ на чтение может быть отложен, но каждое чтение будет получать ответ. Другими словами, каждый считыватель всегда имеет доступ к базе данных. Не существует времени, в течение которого считыватель получил бы ответ «сейчас вы не можете запросить эту базу данных». Устойчивость к разделению: возможность копирования или разделения базы данных на несколько устройств. Проще изучить теорему CAP в небольшой сети. Для этого используется рисунок 11. Предположим, что A содержит единственную копию базы данных, к которой должны иметь доступ как C, так и D. Предположим, что C записывает некоторую информацию в базу данных, а затем сразу же после, C и D считывают одну и ту же информацию. Единственная обработка, которая должна быть, чтобы убедиться, что C и D получают одну и ту же информацию, - это A. Теперь реплицируйте базу данных, чтобы была копия на E и еще одна копия на F. Теперь предположим, что K записывает в реплику на E, а L читает из реплики на F. Что же будет? F может вернуть текущее значение, даже если это не то же самое значение, что только что записал К. Это означает, что база данных возвращает непоследовательный ответ, поэтому согласованность была принесена в жертву разделению базы данных. Если две базы данных синхронизированы, ответ, конечно, в конечном итоге одинаковым, но потребуется некоторое время, чтобы упаковать изменение (упорядочить данные), передать его в F и интегрировать изменение в локальную копию F. F может заблокировать базу данных или определенную часть базы данных, пока выполняется синхронизация. В этом случае, когда L читает данные, он может получить ответ, что запись заблокирована. В этом случае доступность теряется, но сохраняется согласованность и разбиение базы данных. Если две базы данных объединены, то согласованность и доступность могут быть сохранены за счет разделения. Невозможно решить эту проблему, чтобы все три качества были сохранены, из-за времени, необходимого для синхронизации информации между двумя копиями базы данных. Та же проблема актуальна и для сегментированной базы данных. Как это применимо к плоскости управления? В распределенной плоскости управления база данных, из которой плоскость управления черпает информацию для расчета путей без петель, разделена по всей сети. Кроме того, база данных доступна для чтения локально в любое время для расчета путей без петель. Учитывая разделение и доступность, необходимые для распределенной базы данных, используемой в плоскости управления, следует ожидать, что непротиворечивость пострадает - и это действительно так, что приводит к микропетлям во время конвергенции. Централизованная плоскость управления не «решает» эту проблему. Централизованная плоскость управления, работающая на одном устройстве, всегда будет согласованной, но не всегда будет доступной, а отсутствие разделения будет представлять проблему для устойчивости сети.
ВЕСЕННИЕ СКИДКИ
40%
50%
60%
До конца акции: 30 дней 24 : 59 : 59