Авторские права © 2016 Aleksey Midenkov
История переиздания | |
---|---|
2016-08-14 | |
Добавлен Math calculator |
Список иллюстраций
Список примеров
|
||||||
CV: |
Резюме: |
Phorm (121 Media). Московский офис ООО "ФОРМ" (в прошлом ООО "Передовые интернет решения") насчитывал порядка 100 человек и состоял из нескольких отделов: Server, Datacapture, UI, DB, QA, SA, HR. Компания специализируется на целевой рекламе. Её основное отличие от конкурентов в том, что она способна собирать целевой профиль и осуществлять поставку рекламы на стороне провайдера, что улучшало качество профиля и соотношение клик : покупка в сравнении с веб-сайтами. Разработкой этой технологии работы с трафиком на стороне провайдера занимался отдел Datacapture.
В компании "ФОРМ" я работал в отделе Dataсapture с 2007-го по 2015 гг., затем в начале 2015-го был переведён в отдел Server, где я проработал несколько месяцев до увольнения. В отделе Datacapture я написал модули обработки запросов для Apache и Nginx, модуль восстановления пользователей по данным браузера, модуль защиты от фишинговых сайтов, новую версию стартующих скриптов, а также другие обновления в рамках соответствующих тикетов. Разработка велась в основном на C++, Perl, XSLT, Bash. Для внутрикластерного взаимодействия использовалась CORBA.
Также, я оптимизировал производительность процессов, исправлял утечки памяти и некорректные операции исполнения, работал с продакшн кластерами. Я хорошо ориентируюсь в большом объёме кода. Разбираюсь в устройстве серверных приложений, владею средствами POSIX, в том числе POSIX Threads. Работал с библиотеками libev и zlib. Писал скрипты для Make, CMake и Automake.
Не лишне будет упомянуть, что мой предпочитаемый дистрибутив – Debian, которым я пользуюсь с 1999-го года. И в котором я работал как с debhelper, так и с CDBS, а также репозиториями reprepro.
Посмею также заметить, что работу я делаю качественно. Тщательно обдумываю свои решения, смотрю на задачу с различных сторон. Если попытаться коротко описать моё жизненное кредо, то я бы представил его двумя афоризмами: «стремиться к идеалу изо всех сил, зная, что он недостижим» и «малыми шагами совершаются большие дела».
Расскажу поподробнее про модули, которые я написал. Модуль обработки запросов взаимодействует с браузером пользователя. Когда пользователь впервые обращается в домен компании, запрос приходит в этот модуль. Далее производится ряд операций – проверка на возможность установить куки, попытка восстановить куки из локальных хранилищ и наконец присвоение уникального идентификатора. Когда пользователь обращается за рекламой, то модуль может выступать в качестве прокси, если того требует инфраструктура и передать запрос в рекламный сервер.
Модуль восстановления пользователей по данным браузера. Если пользователь удалил свой идентификатор и восстановить его из локального хранилища не получилось, то существовала возможность восстановить его по данным браузера, т.к. все эти данные сохранялись в базе наряду с уникальным идентификатором и IP-адресом. При этом во время поиска по базе использовался алгоритм нечёткого сравнения (расстояние Левенштейна) на случай, если данные браузера немного изменились – например, обновилась версия или были установлены новые шрифты.
И наконец модуль защиты от фишинговых сайтов. В этом модуле производилась проверка оригинального URL пользователя в списке фишинговых URL. Если обнаруживалось соответствие, то пользователю вместо запрашиваемой страницы открывалась страница с предупреждением. Список хранился в shared memory и был доступен всем процессам и потокам демона. При этом он периодически инкрементально обновлялся по HTTP протоколу.
Содержание
Год: 2016 Инструментарий: С++11, POSIX, libev
Исходный код:
Текущий статус проекта: в HTTP-proxy реализован минимальный функционал, необходимый для успешной работы: Keep-Alive соединения, обработка Transfer-Encoding: chunked. В будущем предусматривается такая функциональность, как: пайплайнинг запросов (Issue #3), асинхронное разрешение доменных имён (Issue #4), HTTPS.
Программа написана на C++ с использованием элементов 11-го стандарта. Архитектура демона основана на неблокирующихся сокетах и состоит из пула потоков, в каждом из которых запущен цикл событий, обрабатывающий все принятые в данном потоке соединения. Дизайн Evoxy предполагает, что по возможности все ресурсы, необходимые потоку должны быть локальны в этом потоке, а значит свободны от многопоточной конкурентности. На данный момент программа не использует ни одного мьютекса (или какого-либо другого средства синхронизации потоков).
Демон работает на преаллоцированной памяти. На стадии инициализации каждому потоку из кучи выделяются все необходимые пулы памяти. Пулы памяти демона работают с блоками фиксированного размера, т.е. заточены на аллокацию объектов одного определённого типа. Размер пула соответствует установленным в настройках лимитам программы. На данный момент используется всего 3 различных пула: 1 для создания соединения и 2 для кэша доменных имён.
Главный недостаток текущей версии в том, что обработчики соединений Frontend и Backend жёстко связаны друг с другом в соотношении 1:1. Такая схема неэффективна для Keep-Alive соединений, поскольку запрос к каждому новому хосту на стороне Frontend-а обязывает Backend разрывать текущее соединение и устанавливать новое. Будущая версия программы должна иметь пул соединений Backend-ов, которым может пользоваться Frontend (см. Issue #1).
См. также: описание server-demo.
Год: 2016 Инструментарий: С++11
Исходный код:
Калькулятор вычисляет математические выражения с учётом приоритета операций и скобок. В
выражениях могут присутствовать унарные математические функции (см. math.h). Вычисление производится
двумя стадиями: построение бинарного синтаксического дерева (Calc::parse()
) и
исполнение синтаксического дерева (Calc::calculate()
). Программа не использует
рекурсивные вызовы.
Правила синтаксического дерева:
в корне всегда число, исполнение начинается с корня;
каждый левый потомок: операция (оператор или функция);
каждый правый потомок: число;
оператор исполняется над двумя операндами: предок и правый потомок;
функция исполняется над одним операндом: предок;
если у второго операнда (правый потомок) есть левый потомок (операция), то новая операция имеет приоритет над текущей.
Таким образом, вычисление начинается с корня и продолжается по левой ветви до первого ветвления (левый потомок у операнда). Затем, состояние сохраняется в стек и вычисление начинается в новой ветви (от операнда). Когда ветвь заканчивается, состояние восстанавливается из стека и продолжается вычисление старой ветви. Обход продолжается до тех пор, пока не закончится ветвь при пустом стеке.
Год: 2013 Инструментарий: C++, MySQL Connector/C
Исходный код:
С++ обёртка вокруг MySQL Connector/C. Основное её преимущество перед стандартным C++
коннектором -- многопоточный пул коннектов. Обёртка имеет дружественный интерфейс: не нужно
вручную создавать и разрушать объекты; текст SQL кода инстанцируется выводом в
stringstream
.
Пример 2.1. Схема использования MySQL wrapper
Conf c; c.host = "localhost"; c.user = "user"; c.passwd = "password"; c.db = "database"; Connection::Pool pool(pool_size); try { pool.connect(c); Query q(pool); q << "-- any SQL code (multiple statements allowed)\n"; q.execute(); // or q.execute_only() if no data returned Row row; while (row = q.fetch_row()) { // Get data from row. // integers are accessed with (POS_INDEX); // strings are accessed with [POS_INDEX], // like here: int integer_value = row(0); std::string string_value = row[1]; } } catch (Database::Error &ex) { std::cerr << ex.what(); } catch (Database::Exception &ex) { std::cerr << ex.what(); }
См. также рабочий пример использования: example.cpp.
Год: 2015 Инструментарий: UML class diagram Copyright: ©Phorm Corp
Диаграмма основана на UML диаграмме классов и представляет собой смесь поведенческой и структурной диаграммы. Диаграмма позволила быстро понять соотношение и поведение объектов в контексте конкретной задачи. Ни одна из существующих поведенческих видов диаграмм UML для этого не подошла.
Поясню устройство диаграммы:
жёлтым цветом обозначены классы, фиолетовым -- методы;
"ассоциацией" обозначены вызовы методов;
"реализацией" обозначена принадлежность методов классам;
"композицией" показано эксклюзивное владение объектом;
"агрегацией" показано временное владение объектом либо хранение указателя на объект.
Разберём содержимое диаграммы. Класс Frontend
в вызове
handle_request()
создаёт BaiduRequestTask
, который складывается
в очередь TaskRunner
. TaskRunner
вызывает execute()
у
BaiduRequestTask
, который в свою очередь вызывает
process_baidu_request()
у Frontend
. Каким образом -- показано в
верхнем правом углу: BaiduRequestTask
унаследован от RequestTask
,
а тот в свою очередь содержит указатель на объект Frontend
:
bid_frontend_
. Итак, process_baidu_request()
вызывает
fill_by_baidu_request()
у RequestInfoFiller
. На этом контекст
схемы заканчивается.
Подчеркну, что диаграмма описывает лишь очень небольшой срез, необходимый для решения
конкретной задачи. В огромном объёме кода подобные компактные наброски на мой взгляд
жизненно важны, т.к. они позволяют быстро вспоминать контекст задачи. Возможно, в диаграмме
была допущена неточность: RequestTask
вряд ли владеет объектом
Frontend
, отношение композиции должно быть заменено отношением
агрегации.
Год: 2007-2015 Инструментарий: Bash
Исходный код:
Скрипт для автоматизации workflow по разработке задач. Запускает сессию Bash с окружением, настроенным под контекст конкретного тикета задачи. В окружение добавляются CLI-команды, которые значительно сокращают рутинные действия по подготовке задачи к работе. Например, при помощи только одной команды 'new' происходят следующие действия:
Каждая задача имеет свою директорию с номером и кратким названием, внутри которой хранятся все файлы задачи: рабочие копии, деревья компиляции, деревья инсталяции, конфигурация, скрипты, заметки и пр. В данный момент скрипт заточен под задачи конкретной компании, но может быть переделан под любой workflow.
Год: 2010 Инструментарий: Perl, Linux system utilities
Исходный код:
Скрипт собирает системные данные хоста для случаев критических неисправностей:
информацию по системным ресурсам, системные логи и логи программы, информацию по коркам,
конфигурацию, текущее поведение системы и пр. Скрипт настраивается модификацией
@REGISTRY
:
Пример 2.2. Настройка работы trouble-report
my @REGISTRY = ( { title => 'Uptime', command => 'uptime', filename => 'common.txt' }, { title => 'Processes by user', command => 'ps uax', filename => 'ps.txt' }, { title => 'Process tree', command => 'pstree -p', filename => 'pstree.txt' }, { title => 'Last log files', command => "ls -1rt $O{program_root}/var/log/*|tail|xargs tail", filename => 'logs.txt' }, # ... and so on ... );
Скрипт имеет процедуру бинарного поиска для быстрого поиска записи лога по timestamp:
binary_find
.
Год: 2013 Инструментарий: Perl
Исходный код:
Скрипт подготавливает данные, необходимые для парсинга строчек User-Agent. Он преобразует списки сайта useragentstring.com в упорядоченные списки токенов, по которым происходит идентификация браузера и операционной системы. Основная сложность заключается в том, что строка User-Agent может содержать несколько токенов от разных браузеров. Так, например строка для AOL 9.7:
Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.5; AOLBuild 4337.43; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618)
содержит токен MSIE, поэтому проверка на AOL должна проходить раньше, чем на MSIE. Скрипт анализирует такие появления токенов от других браузеров и определяет порядок в котором токены должны проверяться, чтобы избежать неверного определения. См. также: описание использования скрипта.
Год: 2007-2014 Инструментарий: CMake, Bash, Perl
Исходный код:
Утилита позволяет избежать шага make install
в цикле
"редактирование-компиляция-запуск", что значительно облегчает работу с тяжеловесным кодом.
Для этого make install
вместо копирования файлов создаст символические ссылки
на дерево компиляции. Утилита работает с деревьями Autoconf, CMake и MakeMaker.
Год: 2016 Инструментарий: Perl
Исходный код:
Обёртка для GCC позволяет использовать этот компилятор в Visual Studio с корректным
выводом ошибок в окно Error List. Данный пример демонстрирует работу Select
в
связке с Open3
.
Год: 2013 Инструментарий: Ida Pro 6.1; Syser 1.99
В ходе анализа кода DirectX игры Atomic Bomberman были найдены функции, отвечающие за работу основного меню ($main_menu_loop), запуска новой игры ($new_game_options, $new_game_players, $new_game), работу настроек игры ($options_menu, $load_options), а также основные игровые переменные, такие как $newgame_goal_amount, $goal_type, $newgame_theme. Все символы с '$' были разработаны мной в процессе реверсинга, полный их список (73) можно посмотреть в bm95_discovered.map. Заметки по анализу находятся в bomberman.txt.