суббота, 9 июня 2012 г.

[prog.thoughts] Несколько слов о самодельном прикладном пакетном протоколе и заточенной под него логике

Предположим, что есть компонент A, который должен делать асинхронные запросы к компоненту B посредством пары сообщений request/response. Т.е. A отсылает request, B его обрабатывает, а затем отсылает response. Каждая пара request/response идентифицируется уникальным номером. Поскольку взаимодействие асинхронное, то A может отослать B сразу несколько request-ов (например, с номерами 1, 2, 3, 4 и 5). Компонент B будет отвечать по мере готовности и его ответы могут идти в совсем другом порядке. Например, сначала response с номером 4, затем 5, затем 2 и 1, и только затем 3. Компонент A на каждый запрос ждет ответа в течении определенного тайм-аута. Если ответ не пришел, то A повторяет запрос, но обязательно с тем же самым номером, что и в первый раз.

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

Проблема в возможности перепосылок сообщений request. Из-за этого компонент B получив очередной request должен проверить его уникальность. Если же запрос получен повторно, то он не должен обрабатываться. Тут все зависит от того, в какой стадии находится выполнение запроса – если запрос обрабатывается в данный момент, то повторный request игнорируется. А если запрос уже был обработан, то на повторный request нужно повторить ранее отосланный response.

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

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

И вот в качестве одного из решений было предложено объединять request и response в пакеты. Т.е. компоненты A и B переходят на взаимодействие посредством сообщений request_pkg и response_pkg, внутри которых уже собраны request-ы и respons-ы.

Например, компонент A отсылает request_pkg с идентификатором 1, в котором находятся request-ы с номерами 1, 2, 3, 4, 5. Компонент B сначала присылает request_pkg_ack с идентификатором 1 – это есть подтверждение того, что запросы дошли до компонента B. Если request_pkg_ack до A не дойдет за положенное время, то A вновь отсылает request_pkg с идентификатором 1 с точно таким же содержимым внутри.

По мере обработки запросов компонент B будет формировать response_pkg, в которые будет собирать готовые ответы. При этом размер и идентификатор response_pkg никак не связан с request_pkg. Так, компонент B может сначала отослать response_pkg с идентификатором 2, в котором будут response с номерами 3 и 5. А затем – response_pkg с идентификатором 3, в котором будут response с номерами 1, 2 и 4.

В ответ на response_pkg компонент A должен выслать response_pkg_ack. Если он этого не сделает, то после некоторого тайм-аута компонент B перепошлет response_pkg.

Краеугольными принципами этого пакетного протокола являются:

  • если сообщение с идентификатором X включено в пакет с идентификатором Y, то оно может присутствовать только в пакете с идентификатором Y и ни в каком другом;
  • состав конкретного пакета должен быть постоянным. Т.е. если в пакет с идентификатором Y входили сообщения с идентификаторами X, Z и W, то только эти сообщения и только в этом количестве должны присутствовать в пакете Y при всех его перепосылках.

Благодаря таким принципам, объем работы по проверке уникальности получаемых от удаленного компонента сообщений уменьшается в разы (пропорционально размеру пакета). Ведь сейчас нужно проверять уникальность не индивидуальных request/response, а уникальность пакетов.

Вот такая в итоге сложилась схема. В соответствии с ней для компонента A создана табличка responses в БД, первичным ключем в которой является уникальный номер request/response. Вставки строк в эту таблицу происходят при обработке response_pkg_ack.

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

Соответственно, при получении второго пакета с тем же самым response внутри, компонент A попытается добавить в табличку responses строку с неуникальным значением первичного ключа. И получит ошибку при работе с БД. Причем, поскольку компонент B будет перепосылать проблемный пакет (не получая из-за сбоев компонента A подтверждения), то компонент A будет “падать” снова и снова (не обязательно падать в прямом смысле, достаточно будет того, что он начнет тратить время на устранение этой ситуации).

Вот, собственно, хорошая ситуация для размышлений. Должны ли компоненты A и B защищаться от возможных ошибок в реализации друг друга? Особенно принимая во внимание, что компоненты разработаны одной командой, предназначены для работы в рамках одной задачи. Просто отвечают за разные куски функциональности.

PS. Это вопрос риторический. Я его озвучил не для того, чтобы посоветоваться с общественностью. Просто выступаю в роли акына – что вижу вокруг себя, то и пою :)

[life.photo.nature] Здорово!

FEED ME! An Indian myna held a grasshopper in its beak to feed chicks Friday in a nest built inside the wall of an underpass on the outskirts of New Delhi. (Parivartan Sharma/Reuters)

Снимок найден в очередном выпуске WSJ's Photos of the Day

[life.sport.darts] Гари Андерсон играет на UK Open 2012 новыми дротиками…

…и уже сделал 9-darter в своей первой же игре!

Новые дротики Андерсона похожи на те, что PureDarts продает под названием Scalloped. Интересно, долго ли Андерсон ими будет играть? И если он на них останется, как быстро Unicorn выпустит их в продажу? Помнится, эксперимент Тейлора с Phase 6 длился всего несколько месяцев, а в продаже они появились через полгода после того, как Тейлор вернулся на Phase 5.

PS. PureDarts сменил свой дизайн. Вслед за a180. Нужно привыкать.

среда, 6 июня 2012 г.

[life.photo] Какой-то небольшой выбор стекол у Nikon-а оказался :(

К хорошему быстро привыкаешь. Вот и я поснимав в последние месяцы светосильными объективами не хочу больше возвращаться на штатный 18-105/3.5-5.6. А выглядывающий из-за горизонта отпуск заставляет думать, что же взять с собой. Обойтись одним 35-миллиметровым фиксом вряд ли получится. Поэтому озадачился поиском среднефокусного светосильного зума.

И оказалось, что выбор в продукции Nikon-а не так уж велик. А именно:

  • 17-55/2.8
  • 24-70/2.8
  • 24-120/4
  • 24-85/2.8-4

При этом первые три весьма и весьма недешевые (особенно топовый 24-70/2.8).

Грустно как-то.

PS. Разыскивая информацию об объективах наткнулся на интересный Youtube-канал с роликами о разнообразной Nikon-овской продукции.

понедельник, 4 июня 2012 г.

[work] Вдруг война, а я уставший!

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

Поскольку создание ПО, как очень точно заметил дедушка Кнут, очень ресурсоемкая операция, да еще требующая полной сосредоточенности на какой-то одной теме. А управление людьми – это совсем другая крайность, в которой очень важна постоянная готовность к “внезапным вбрасываниям”. Т.е. как к неожиданными вопросам/спорам подчиненных, так и к еще более неожиданным идеям/инициативам руководства.

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


* участие в уточнении задачи, в выборе архитектуры, разрешении споров, уточнении степени и зоны ответственности, согласование тестирования и пр. И это без еще оформления планов, жесткого контроля и тотального учета ;)

[prog.flame] Поднимается шум вокруг Visual Studio 2011 Express edition

Говорят, что десктопные приложения для Windows можно будет разрабатывать только с помощью профессиональной версии Visual Studio 2011. Бесплатный же вариант Visual Studio 2011 Express for Web будет позволять делать только HTML+JavaScript Web-сайтики и ничего больше. Информация взята отсюда: No-cost desktop software development is dead on Windows 8.

Не то, чтобы меня это сильно заботило (самый большой и старый С++ный проект у нас до сих пор работает под VS 2003, более новые мы собираем VS 2008, а в VS 2010 нашли фатальную ошибку, не позволяющую собирать наши проекты, так что 2010-я студия отправилась в топку). Но, имхо, это еще один непонятный шаг MS-а про который остается только сказать – опять хуйней страдают.

Ну а картинка из упомянутой выше статьи прикольная:

PS. Из чтения сопутствующих новостей у меня сложилось впечатление, что MS пытается кнутом заставить разработчиков писать новые Windows-приложения на смеси из HTML5+JavaScript (т.н. Metro-style app). Так вот что-то мне подсказывает, что такая ориентация на JavaScript (точнее его повсеместное насаждение) закладывает в индустрии бомбу похлеще Y2K-problem. Исходя из своего опыта могу сказать, что динамика – это здорово и очень удобно в мелких масштабах. Но с течением времени, ростом кодовой базы, ротацией внутри команды и пр. неизбежных попутчиках жизненного цикла запущенного в эксплуатацию продукта, геморройность сопровождения кода на динамических ЯП растет значительно быстрее, чем для статических ЯП. Так что не удивлюсь, если лет через N-адцать будут очень востребованны спецы по JavaScript-у для переписывания старых приложений на более удобные для сопровождения языки.

[prog.thoughts] Вспомнил свой старый пост про причины разработки OpenSource проектов

Новая тема на RSDN заставила вспомнить, что когда-то я написал довольно многабукфф на эту тему: “А зачем вы выпускаете OpenSource проекты?

Удивительное дело: прошло ровно семь(!) лет, а я придерживаюсь той же самой точки зрения.