компьютерные сети — Блог Валерия Леонтьева https://valera.ws Место публикации личных заметок. Технологии, управление, бизнес, жизнь Sat, 07 Feb 2015 08:32:47 +0000 ru-RU hourly 1 https://wordpress.org/?v=5.6.2 https://valera.ws/wp-content/uploads/2020/02/favicon.png компьютерные сети — Блог Валерия Леонтьева https://valera.ws 32 32 Архитектура веб приложений: экстерьер (видео-лекция) https://valera.ws/2014.01.18~web-applications-architecture-exterio/ https://valera.ws/2014.01.18~web-applications-architecture-exterio/#respond Sat, 18 Jan 2014 17:34:57 +0000 http://valera.ws/?p=730 Читать далее Архитектура веб приложений: экстерьер (видео-лекция) ]]> Архитектура веб-приложений: экстерьерРассказ о популярной универсальной архитектуре стека, в котором работает веб-приложение. Само приложение может быть написано на любом интерпретируемом языке с использованием любого фреймворка фреймворков. В данном случае это не важно, так как архитектура программной инфраструктуры — технологического стека, в котором оно работает, отличается мало.

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

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

Смотрите в полноэкранном режиме.

]]>
https://valera.ws/2014.01.18~web-applications-architecture-exterio/feed/ 0
Классификация знаний в области программирования https://valera.ws/2013.10.05~computer-science-knowledge-classification/ https://valera.ws/2013.10.05~computer-science-knowledge-classification/#respond Sat, 05 Oct 2013 20:39:13 +0000 http://valera.ws/?p=721 Читать далее Классификация знаний в области программирования ]]> CSМеня иногда спрашивают, что нужно выучить, чтобы стать программистом. Вопрос несколько наивный, т.к. нормально ответить на него по-моему невозможно. Т.е. для начала нужно выяснить, каким программистом нужно стать. Да и вообще, программистом ли? Кроме того, на рынке востребованы как высококвалифицированные дорогие специалисты, так и “рабочая сила”. Пакет знаний и опыта первых и вторых отличается в значительной степени.

Но, не смотря на такую расплывчатость вопроса, дать ответ на него все же можно. Можно описать примерный максимум знаний, которые так или иначе относятся к программированию. Собственно, этот максимум обычно и стремятся преподать в ВУЗах на специальностях, в названии которых фигурирует слово “программист”.

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

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

В предыдущем абзаце я нарочно ввел термин “инженер-программист”. Как-то получается так, что программист — это не обязательно инженер. Даже из определения Википедии следует, что инженер — это в первую очередь проектировщик. Это тот, кто создает, т.е. проектирует системы. А в практике программирования проектирование нужно не всегда. Иногда достаточно кодирования: используя данный набор технологий, слепить что-то работающее. Типичный пример — стадо корпоративных или маркетинговых сайтов на джумлах, ворпрессах, друпалах и т.д. Это уровень техника, не инженера. Это уровень среднего образования. И работать техником можно даже после окончания курсов какого-либо языка программирования, крепкая теоретическая база там не нужна.

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

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

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

Первый уровень из CS (computer science) — Специальная база. Это стартовая площадка для любого программиста по четырем фронтам:

  • арифметические основы ЭВМ (системы счисления и операции с числами, логические операции);

  • физические основы ЭВМ (полупроводники, транзисторы, логические элементы, схемы, интегральные микросхемы);

  • теория алгоритмов (алгоритмы и структуры данных; сложность, эффективность; способы представления информации в памяти);

  • языки программирования (задача и понятие ЯП, уровни, типы языков, абстракция, уровни абстракции, трансляция/компиляция, шаблоны, принципы, парадигмы — обзор).

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

Уровнем выше располагаются дисциплины, которые являются базовыми именно в программировании. По-этому я назвал этот уровень Основы. В него входят:

  • архитектура ЭВМ (процессоры, микроархитектура, память, шины, ввод/вывод);

  • обработка информации (теория информации, статистика, модели, поиск данных, лингвистические аспекты, обработка информации средствами табличных процессоров);

  • основы C/C++ (базовые свойства языка, синтаксис, указатели, ввод/вывод, массивы, основы STL).

Следом за Основами идет Уровень 1. Это первый прикладной уровень, и особо нетерпеливые могут начать коммерческую практику, овладев этим уровнем. Он включает 5 дисциплин:

  • основы ASM (развитие архитектуры ЭВМ в направлении программирования, написание простейших драйверов и алгоритмов, ассемблерные вставки в C/C++);

  • C/C++ (ООП, разработка прикладных приложений, библиотеки, WinAPI, make utils, параллельное программирование).

  • операционные системы (архитектура ОС, процессы, межпроцессное взаимодействие, потоки, планирование, работы с памятью и переферией, POSIX-системы);

  • системный анализ (предметная область, бизнес-процессы, потоки, диаграммы, принципы и теория системного анализа);

  • базы данных (теория множеств, виды СУБД, реляционные СУБД, модели данных, SQL, конкретные БД).

Следующий уровень — Уровень 2 — развивает предыдущий. Кстати, компьютерные сети попали в него только по той причине, что для их изучения желательно (но не обязательно) предварительно освоить операционные системы. По развитости этот предмет ближе все-таки к первому уровню.

Уровень 2 включает:

  • разработку ПО (жизненный цикл ПО, этапы разработки, основы ведения программных проектов, инструменты);

  • анализ данных (Data Mining, OLAP, машинное обучение, нейронные сети, ИИ);

  • компьютерные сети (по уровням стеков TCP/IP и/или ISO/OSI “от и до”, протоколы, сетевое программирование на C/C++);

  • языки программирования с управляемым кодом (управляемый код, виртуальные машины, сборщики мусора, юнит-тестирование, собственно практика на C# или Java);

Уровень 3 — последний уровень для среднего программиста. Он самый объемный и включает только те дисциплины, которые непосредственно связаны с разработкой ПО. Всего их получилось 6:

  • разработка UI и юзабилити (принципы построения интерфейсов пользователя);

  • управление командами и проектами (методологии разработки и другие вопросы управления);

  • тестирование ПО (обзорно: виды тестирования, инструменты);

  • веб-технологии (HTTP-протокол, веб-сервер, CGI, кэширование и проксирование, клиентское программирование);

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

  • интерпретируемые языки программирования (особенности, основы по двум-трем языкам, практика по одному-двум языкам: JS, PHP, Python, Ruby).

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

Интересно в графе то, что он не только показывает предпочтительный порядок изучения предметов, но также:

  • дает возможность понять, какие дисциплины нужны больше, какие меньше для работы в определенной специализации (просто выбрать основной предмет специализации и смотреть по связям и удаленности до других);

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

Граф — это модель. А хорошая модель как правило дает ответы сразу на множество вопросов. Я поставил перед собой задачу сделать хороший граф, близкий к реальности. Естественно, он основан на моем личном опыте и не претендует на идеал. Я старался сделать его наиболее объективным. И еще раз напоминаю, что это граф для программиста. Т.е. для тестировщика, сисадмина и других близких к программированию профессий он будет более или менее близким, но явно другим.

Граф
]]>
https://valera.ws/2013.10.05~computer-science-knowledge-classification/feed/ 0
Выдача файла из PHP через nginx (Accel-Redirect) + докачка + некоторые тонкости https://valera.ws/2012.03.06~accel-redirect-apache-dokachka/ https://valera.ws/2012.03.06~accel-redirect-apache-dokachka/#respond Tue, 06 Mar 2012 20:28:27 +0000 http://valera.ws/?p=644 Читать далее Выдача файла из PHP через nginx (Accel-Redirect) + докачка + некоторые тонкости ]]> Как контролировать скачивание больших файлов, проверяя права доступа или считая количество закачек? Как сделать, чтобы при проксировании на Apache работала докачка? Как вообще работает докачка, почему она не работает с nginx в IE 9 и как она работает в других браузерах?

1. Мы хотим контролировать скачивание больших файлов, проверяя права доступа или считая количество закачек. Мы используем nginx и PHP (или другой серверный язык).

Это реализуется очень просто через заголовок Accel-Redirect. nginx получает запрос, передает его скрипту, скрипт в заголовки ответа выдает Accel-Redirect с ссылкой на файл, который нужно выдать пользователю. Если файл выдавать нельзя (например, нет прав), скрипт просто выдаст ошибку (например, 403).

В данном случае не важно, работает ваш PHP через проксирование из nginx на Apache, либо на *CGI. Предположим, что вы хотите отдавать на скачку файлы, которые находятся в каталоге /var/files. Тогда в секции server в nginx добавьте:

location /_download_files {
        root /var/files;
        internal;
}

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

header("X-Accel-Redirect: /_download_files/filename.zip");

Никакой выдачи (echo) делать не надо, после отдачи заголовка можно завершить работу скрипта. В этом случае будет скачан файл /var/files/filename.zip. Вместо filename.zip может быть любой длинный путь с каталогами, который должен повторять путь к файлу в /var/files/.

В принципе этого достаточно, чтобы переложить выдачу файла на плечи nginx. Если нужно обязательно показать диалог закачки (даже если файл такого типа, который браузер может показать сам), нужно добавить выдачу заголовка:

header("Content-Type: application/x-force-download");

Обратите так же внимание на то, что в случае проксирования на Apache последний обязательно установит Content-Type (по умолчанию обычно text/html) в случае PHP-скриптов, и этот тип отправится пользователю, так как nginx его не перепишет при выполнении Accel-Redirect. Т.е. в этом случае эту строку нужно писать обязательно. Как будет в случаях с *CGI, не знаю — не проверял.

Чтобы предложить пользователю имя файла для сохранения, отличное от того, что в адресной строке (это особо актуально в случаях «download.php&file_id=12332»), отправим такой заголовок:

Content-Disposition: attachment; filename="Super File Name.zip";

2. В такой схеме при проксировании на Apache не работает докачка. Исправляем.

Докачка в HTTP работает через HTTP-заголовок Range. В нем указывается с какого байта начать передачу. Можно так же указать, сколько байт нужно передать. Это передается в запросе. Например:

Range: bytes=33-
Range: bytes=33-100

Первый вариант просит отдать весь файл, начиная с 33 байта (включительно). Второй вариант просит отдать с 33 байта по 100. Чтобы браузер понял, что докачка поддерживается, сервер отдает в ответе заголовок:

Accept-Ranges: bytes

Докачка не работает из-за того, что HTTP-заголовок Range попадает в Apache после просирования и последний думает, что его просят отдать кусок PHP-файла. А он это делать не хочет и отдает ошибку: HTTP/1.1 416 Requested Range Not Satisfiable.

Исправляется это довольно легко — просто зануляйте при проксировании Range (это нужно добавить туда, где у вас описано проксирование на Apache в конфиге nginx):

proxy_set_header   Range   "";

Тогда Apache (или PHP-скрипт) ничего знать про него не будут и спокойно сделают свое дело. А nginx после Accel-Redirect отдаст ответ в соответствии с запрошенным Range.

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

3. Даже так не работает докачка в IE 9.

Да. На сколько я понял методом простого тыка, IE требует поддержки ETag сервером для работы докачки. Игорь Сысоев (разработчик nginx) отказался внедрять в nginx поддержку ETag. Поэтому из коробки работать докачка в IE 9 не будет точно. Если это жизненно необходимо, пробуйте смотреть сюда (Ctrl+F Etag).

4. А как работает докачка в других браузерах?

Везде есть свои особенности. В общих чертах случай докачки выглядит так. Запрос/ответ на скачку (начало скачки):

GET /file.zip HTTP/1.1
Host: example.com

HTTP/1.1 200 OK
Server: nginx/1.0.3
Date: Tue, 06 Mar 2012 18:09:47 GMT
Content-Type: application/x-force-download
Content-Length: 13686314
Last-Modified: Thu, 23 Feb 2012 13:50:26 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Disposition: attachment; filename="Supre File Name.zip";
Accept-Ranges: bytes

Запрос/ответ на докачку:

GET /file.zip HTTP/1.1
Host: example.com
Range: bytes=5393683-

HTTP/1.1 206 Partial Content
Server: nginx/1.0.3
Date: Tue, 06 Mar 2012 18:10:11 GMT
Content-Type: application/x-force-download
Content-Length: 8292631
Last-Modified: Thu, 23 Feb 2012 13:50:26 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Disposition: attachment; filename="Super File Name.zip";
Content-Range: bytes 5393683-13686313/13686314

На практике ни один браузер не ограничивается таким набором заголовков. Все хотят защитить пользователя от скачки битого файла. Это может получиться так: начал закачку, поставил на паузу; в это время на сервере скачиваемый файл обновился; продолжил закачку с нужно места и получил кусок обновленного файла. В результате скачается «битый» файл — половина старая версия, половина — новая.

Opera. Она шлет указание на то, что «если файл не менялся со времени Last-Modified в первом ответе, дай мне указанный кусок; иначе — отдай мне весь файл заново». Делается это с помощью заголовка If-Range в запросе:

GET /file.zip HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.61
Host: example.com
Accept text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, ..., */*;q=0.1
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
If-Range: Thu, 23 Feb 2012 13:50:26 GMT
Range: bytes=5393683-

Firefox. Он делает немного иначе. Используется заголовок If-Unmodified-Since с указанием того же времени из Last-Modified. В этом случае сервер либо вернет запрошенный кусок (если файл не менялся), либо отдаст ошибку 412 Precondition Failed. Выглядит это так:

GET /file.zip HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Range: bytes=5878651-
If-Unmodified-Since: Thu, 23 Feb 2012 13:50:26 GMT

Chrome. Этот «пильмень» — самый хитрый. Он вообще не поддерживает докачку, хотя делает вид, что поддерживает. При постановке закачка на паузу он просто шлет некие TCP-пакеты для поддержания соединения. Когда сервер понимает, что его дурят, он разрывает соединение. Если дождаться этого момента и нажать в Хроме «Продолжить», он сделает умный вид, будто файл полностью скачался и все ОК, но при этом он останется в том размере, в котором успел скачаться до паузы.

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

IE. Про версию 9 уже сказано выше. Она требует работы Etag для поддержки докачки. В данном контексте ETag — это просто контрольная сумма файла. Когда Etag файла передается в первом ответе от сервера, IE даст возможность прервать скачку. При попытке докачки он отдаст заголовки:

GET /file.zip HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host: falcongaze.com
Range: bytes=3494051-
Unless-Modified-Since: Mon, 05 Mar 2012 08:31:06 GMT
If-Range: "1448453-f77f31-4ba7abf5a8680"
Connection: Keep-Alive

В добавок к If-Range он передает нестадартный заголовок Unless-Modified-Since — вероятено IIS его обрабатывает (только не понятно, зачем он, если есть стандартный If-Unmodified-Since; может для поддержки старых версий IIS?).

Собственно в первом ответе Etag выглядит примерно так (если он поддерживается сервером, например, Apache):

...
ETag: "1448453-f77f31-4ba7abf5a8680"

Дополнительная информация:

]]>
https://valera.ws/2012.03.06~accel-redirect-apache-dokachka/feed/ 0