Wednesday, 6 April 2011

Blogspot expandable posts

Давно я не писал сюда. Сегодня решил исправится и первым делом настроил себе красивый скрипт для длинных статей.

Встречайте:
Ссылка "Read more" появляется только в тех статьях, которые действительно этого заслуживают (и где я собственноручно проставил нужный тег). Работает всё предельно просто, код взят отсюда. Правда пришлось самую малость допилить.

index

Tuesday, 22 June 2010

Видео прокси для вещания в локальной сети

В период чемпионата мира по футболу очень хотелось следить за ходом матчей в живую, да вот беда - работа. Решение казалось бы банально - on-line видео трансляции, но не я один такой заинтересованный оказался. А при 30-40 одновременных потоках входящий Интернет канал оставляет остальным сотрудникам офиса лишь маленькую надежду на закачку чего бы то ни было.
Очень быстро родилась идея организовать видео прокси, которое бы принимало on-line трансляцию и раздавало видео поток в сети. Локальный трафик не так значим, как входящий интернет трафик, потому приступил к реализации. Выбор пал на VLC media player, который сначала показался несколько монстроидальным, но в дальнейшем оправдал все надежды.

Итак, что такое VLC player? Это open-source программный комплекс, позволяющий творить с видео чудеса. В плейере уже находиться масса возможностей, фактически плейер может одновременно выступать и сервером и клиентом. В поставку входят интерфейсы для удалённого управления (telnet, http), так что можем смело ставить vlc на консольную виртуальную машину (здесь и далее все команды приводятся для Ubuntu):
sudo aptitude install vlc vlc-plugin-*

Далее запускаем VLC с активным http интерфейсом удалённого управления:
vlc -vvv -I http --http-host 10.1.6.3:8181

, здесь
  • -vvv - verbose опция (количество букв v отображает уровень логов)
  • -I - включает один из интерфейсов удалённого управления (здесь http)
  • --http-host - задаёт имя (ip) которое пользователь должен ввести, чтобы попасть в админ часть и порт, который будет слушать встроенный сервер
Заходим по адресу и видим:
В принципе данного интерфейса хватает для экспериментов. Для лучшей наглядности лучше сразу же нажать кнопочку "Help".

Первым делом, я нажал кнопку "Open", ввёл адрес сервера (для экспериментов было выбрано футбольное on-line вещание ICTV) и... И насладился цветной картинкой ASCII видео в консоли удалённого сервера. Поборов восхищение и отключив видео - нашел в http интерфейсе кнопку "Stream output", которая и привела меня к победе. Догадался одновременно заполнить обе секции перед нажатием кнопки "Play":
  • в Input (Open кнопка) адрес вещания в интернете.
  • в Stream output выбрал http, ввёл адрес (всё тот же 10.1.6.3), указал порт (на этот раз 8080, чтобы не пересекаться с админкой) и отметил тип кодирования "MPEG TS"
Подключившись локальным VLC player'ом к адресу http://10.1.6.3:8080/ получил звук и картинку ICTV. Казалось бы вот он успех, но всё не закончилось так быстро. После нескольких переподключений локальным плейером оказалось, что в половине случаев видео даже не пытается стартануть, зато звук передаётся отлично. После танцев с бубном вокруг логов проблема решилась дополнительной отметкой "" в "mp2v" и 1024 kb/s. Эта опция перекодирует видео на лету в выбранный формат.

И на последок консольный вариант запуска:
vlc -vvv -I http --http-host 10.1.6.3:8181 http://<internet.on-line.video.url> -sout "#transcode{vcodec=mp2v,vb=1024,scale=1}:std{access=http,mux=ts,dst=10.1.6.3:8080}"

index

Friday, 18 June 2010

Несколько наблюдений о PostgreSQL

1. Postgresql 8.4 + PostGis 1.5.1 оказался в 4 раза производительнее при использовании st_intersects на большом кол-ве данных, нежели Postgresql 8.3 + PostGis 1.3

2.
Слышали про магическое
"\d" в psql? Не знаете какие же запросы делает этот оператор? Вот вам лекарство: "\set ECHO_HIDDEN t"

3.
Как вывод из предыдущего пункта, напрашивается решение следующих вопросов:
* "А как создать таблицу, но только если она еще не существует?"
* "А как создать индекс, но только если он еще не существует?"
В Postgresql это решается обёрткой создания в функцию следующего вида:

CREATE OR REPLACE FUNCTION create_tables_if_not_exist()
RETURNS void AS
$BODY$
BEGIN
  IF NOT EXISTS ( select * from pg_class where relname = 'countries' ) THEN
    CREATE TABLE countries
    (
      id serial NOT NULL,
      geom geometry,
      name character varying(80),
      cid integer,
      CONSTRAINT countries_pkey PRIMARY KEY (id)
    )
    WITH (OIDS=FALSE);
  END IF;
END;
$BODY$ language 'plpgsql';

index

Monday, 29 March 2010

Neo4J - java graph DB

Недавно я рассказывал про граф ориентированные базы данных. А сегодня хочу поделиться с Вами историей использования одной из них. Встречайте Neo4J.
Итак немного о самой системе: Neo4J предлагает Вам полноценную базу данных с транзакциями, индексами (Lucene), несколькими режимами работы и низким порогом вхождения, благодаря очень простой структуре. Все коды открыты и доступны, а приложение поставляется под двойной лицензией AGPL для некоммерческого использования и тарифная сетка для коммерческого. Для начала использования данной базы Вам достаточно знать джаву и понимать чего Вы хотите от сетевой структуры данных (графа).

Мне, при моём знакомстве, была интересна производительность при больших объемах данных и удобство работы с самой БД. Начнём с удобства и создадим базу данных с большим кол-вом вершин и ребёр. Для этого используем специальный класс доступа к БД, который оптимизирован под вставку:

batchGraphDb = new BatchInserterImpl( dbpath, stringProps );
batchIndexService = new LuceneIndexBatchInserterImpl( batchGraphDb );

, где dbPath - путь к файлам будущей базы данных, а stringProps - настройки.
Cоздадим несколько вершин следующим образом:

Map<String, Object> properties = new HashMap<String, Object>();

properties.put("a_key", 5);
properties.put("b_key", "some string");

long createdNode = batchGraphDb.createNode(properties);
batchIndexService.index(createdNode, "a_key", properties.get("a_key"));

Далее в идеале стоит вызвать метод batchIndexService.optimize(); который приведёт индексы в порядок и продолжим создавать рёбра:

Map<String, Object> edgeProperties = new HashMap<String, Object>();
edgeProperties.put("length", 345);
edgeProperties.put("version", "7.5");

long startNodeId = batchIndexService.getSingleNode("a_key", 5);
long endNodeId = batchIndexService.getSingleNode("a_key", 7);

batchGraphDb.createRelationship(
startNodeId,
endNodeId,
DynamicRelationshipType.withName("trust"),
edgeProperties);

Не хитрые манипуляции создают ребро из одной вершины в другую с типом "trust" и собственными свойствами. Ну и на последок закрытие соединения с БД:

if ( null != batchIndexService ) batchIndexService.shutdown();
if ( null != batchGraphDb ) batchGraphDb.shutdown();

Данные готовы, а нам не терпиться проверить её производительность. Показатели качества будут озвучены в следующем посте, а пока можно ознакомиться с другой статьей на эту тему: MySQL vs. Neo4j on a Large-Scale Graph Traversal

index

Wednesday, 17 March 2010

Graph DB

Большинство из нас знают, что в последнее время наряду с привычными реляционными базами данных набирают обороты так называемые Document-oriented, key-value и иерархические базы. А я в последнее время заинтересовался другой разновидностью хранилищ - граф ориентированными базами данных.
Что такое граф, я думаю все знают, а вот зачем для них понадобились свои собственные базы данных? Дело всё в том, что для структуры данных типа граф, набор действий зачастую несколько отличается от привычных нам вставок, обновлений и выборок по заданным условиям. Чего только стоят поиск в ширину и глубину. В принципе на небольших объемах данных традиционные способы представления себя оправдывают, но если предположить, что ваш граф начинает расти и в нём становится несколько миллионов вершин и десятки миллионов связей - реляционные базы данных загибаются под попытками провернуть нужное кол-во join-ов дабы удовлетворить многим условиям выборки при прохождении графа в случае поиска.
Что представляет собой граф ориентированная БД - это хранилище, которое использует некоторые априорные знания о графах, для формирования своей внутренней структуры. В таких базах поиск по критерию зачастую происходит не самым эффективных способом, а вот вычитка связей вершины, и вершин связей сильно оптимизирована. Таким образом обход графа (traversing) становиться операцией, которая в несколько раз быстрее аналогичной родственной реализации в реляционных БД.

Для ознакомления можно взглянуть на:

index

Friday, 15 January 2010

10 истин про Erlang...

Недавно заинтересовался функциональными языками и так уж случилось, что под руки попался Erlang. А что Вы о нём знаете?

1. Erlang - еденица интенсивности телефоммуникационной нагрузки (кол-во траффика)
2. Erlang - датский учёный конца 19, начала 20 веков. Вплотную занимался теориями массового обслуживания и распределениями веротностей разнообразных параметров в разных сферах коммутационных сетей. Его формулы и теории используют по сей день. Его самый известный труд описывает принцип работы Коммутатора с точки зрения мат. статистики и по сути вводит понятие семафора.
3. Erlang - функциональный язык программирования, разработанный компанией Ericsson, оптимизированный для многопоточности и до сих пор использующийся в больших системах реального времени.

4. В Erlang языке нет переменных. Точнее они представленны в виде неизменяемых констант. Никакие две переменные не могут иметь одно и то же имя в пределах их области видимости.
5. Erlang исполняется в виртуальной машине.
6. Парадигма программирования на Erlang позволяет порождать процессы. Erlang-процессы это что-то сродни привычным всем потокам, но со своим уникальным адресным пространством и гораздо более легковеснее ОС-зависимых потоков. Erlang виртуальная машина сама управляет своими процессами.
7. Любые два Erlang-процесса могут обмениваться сообщениями, даже если они запущены в виртуальных машинах на разных компьютерах. Для этого достаточно знать IP-адрес и пароль доступа к запрашиваемой виртуальной машине.
8. Erlang позволяет менять код на лету.
9. Erlang не поддерживает строки напрямую, зато поддерживает массивы. Модель представления массива в памяти - однонаправленный список. Посему в языке определены стандартные операции "добавить в голову массива элемент" и "взять\удалить головной элемент массива"
10. Erlang поддерживает циклы только за счет хвостовой рекурсии. Правда компилятор-интерпретатор умён и если придерживаться определённых правил рекурсия при исполнении всё же будет представлена циклом, но это не меняет впечатления программиста при прочтении исходных кодов.

index

Sunday, 8 November 2009

boolean - боремся за Java память...

У Вас когда-либо случались такие ситуации, когда Ваше Java приложение трещит по швам? В моём случае это случилось из-за нехватки доступной оперативной памяти. И, естественно, обнаружилась нехватка в самый неподходящий момент: на носу очередной долгожданный релиз, один из серверов остановлен для обновления кода и данных и реинкарнация старого кода уже невозможна, в ближайшие дни запланировано несколько совещаний и собеседований, что сильно отвлекает от процесса оптимизации - в общем, ЧП не прошло незамеченным. 

К слову сказать, сделай я правильный backup и экстренные работы по восстановлению жизнеспособности прошли бы гораздо более спокойно, но это была бы уже совсем другая история. Итак в моём распоряжении есть код, которому не хватает 15Gb оперативной памяти для нормального функционирования и очень длительный и дорогостоящий процесс запуска (около 5 часов), в ходе работы которого можно только сидеть со скрещенными пальцами и надеятся, что в этот раз заветные слова OutOfMemoryError не появятся в консоли удалённого сервера. 

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

Как Вы думаете, сколько памяти занимает boolean например на Ubuntu server x64? 

Правильным ответом будет: неизвестно и зависит только от реализации JVM. 

Рассмотрим распространённую Sun JVM и прочтем в спецификации виртуальной машины, что boolean типа в ней нет как такового, вместо него используется int! А это означает, что для хранения значения типа "да\нет" используется ровно 32 бита, независимо от архитектуры процессора. Правда в том же разделе мы видим, что произведена оптимизация для работы с массивами boolean, которые преобразуются в массив байт, что даёт прирост доступной памяти в 4 раза. И всё же платить за хранение нолика или еденички семью лишними битами - иногда просто кощунство и издевательство над серверами (особенно при размерах массивов в 500 миллионов элементов). 

Спасением в таких случаях будет класс BitSet, который ведёт себя подобно массиву boolean, но упаковывает данные так, что для одного бита выделяется всего один бит памяти (с небольшими издержками для всего массива). BitSet хранит внутри себя массив типа long, а при запросе или установке значения определенного бита - высчитывает индекс нужного long и пользуясь побитовыми операциями и операциями сдвига производит вычисления над единственным битом. 

Существует еще более интересная реализация BitSet, OpenBitSet - Apache реализация, которая используется для Lucene. Она гораздо быстрее, но упускает некоторые проверки, проводимые в оригинальном BitSet. Что использовать - решать Вам.

index

Friday, 23 October 2009

Рефлексы

А Вы тоже держите свободную от разговора по мобильному руку в кармане джинс?

index

Friday, 9 October 2009

JMeter. Automated testing.

Тестирование. Я думаю, у многих это слово не вызывает приятных эмоций. Для разработчика это драгоценное время, потраченное на "ненужное" написание функциональных тестов, для тестера это проверка функциональности в кратчайшие сроки, для менеджера страх за приложение, который после беглого взгляда идёт в релиз.
Почему так происходит? Рассмотрим простейшую ситуацию, которая не редко проиходит на просторах отечественного девелопмента. Предположим, разработку оценили в 5 дней, еще 3 дня запланировали на тестирование и день на сам релиз и подготовку окружения. Разработка опаздывает на день-полтора и, конечно же, сроки не сдвигаются, а страдает фаза тестирования. Причем каждая из трех сторон бермудского треугольника "разработчик-ПМ-тестировщик" давит на другую и каждая чем-то не довольна.

С
егодня я не хочу разбирать причины или правильные действия в таких ситуациях, я хочу показать преимущества автоматического тестирования и, в качестве примера, описать JMeter. Аналогов у данной программы множество, но к основным плюсам я могу отнести открытый код и как следствие лёгкую расширяемость под собственные нужды в случае необходимости, возможность распределенного тестирования, понятная документация, стабильность и множество полезных out-of-the-box компонент. К числу минусов я пожалуй отнесу квалификацию человека, пишущего тесты - дело в том, что более ли менее серьезные тесты должен писать человек, хоть немного программирующий и хотя бы поверхностно знакомый с XPath или RegExp.

Итак, автоматические тесты позволяют потратить Вам на тестирование меньшее количество времени при единожды написанных тестах под конкретную функциональность. Что можно создавать с помощью JMeter?
- интеграционные тесты. Функциональные тесты показывают Вам как работает каждая из компонент системы/приложения, но изменяя компонент, часто изменяют и тесты под него, не выясняя как это отразится на двух десятках приложений использующих компонент. Здесь на выручку приходят интеграционные тесты. Основным полезным инструментом JMeter здесь являются JMeter Assertions.
- нагрузочные тесты. Сколько активных пользователей могут одновременно работать при конвертации ста загружаемых изображений на серверной стороне? А при 10 000 изображений? А если быть более точным, то вопрос состоит в обнаружении кол-ва пользователей, которым данные отдаются с задержкой не более секунды, например. Здесь полезны JMeter Controllers, JMeter Timers для эмулирования пользовательских действий.
- стресс тесты. Данная группа тестов призвана обнаружить тот предел, при котором приложение не способно обслуживать запросы, выяснить поведение системы при предельных нагрузках и зарегистрировать возможные потери данных/уязвимости при наступлении критических ситуаций. Здесь поможет распределенное тестирование и всё что уже упоминалось ранее.

В данной статье я хочу остановиться на разного рода HTTP тестировании и некоторых нюансах, хотя ничто не мешает Вам использовать предоставляемую JMeter'ом возможность тестировать FTP, WebServices, DB, LDAP, JMS, Mail.

JMeter представляет собой приложение на Java, которое прекрасно запускается под любыми операционными системами (проверено собственноручно), как в GUI, так и в консольном режиме (что позволяет сделать выбор между визуализацией и производительностью). Ознакомиться с основными компонентами можно в отличной документации или просто запустив приложение и ознакомившись с контекстным меню. Как видно после первого запуска, в приложении есть 2 основных рабочих пространства:
- Test Plan - используется для создания собственно теста, как и следует из названия. Все основные операции проводяться здесь.
- WorkBench - используется для хранения временных компонент теста и некоторых важных не тестирующих компонент. Основное свойство - не сохраняется вместе с сохранением теста.

Варианты создания теста:
1. Создать тест вручную в пространстве Test Plan, пользуясь контекстным меню и примерами из документации.

2. JMeter прекрасно работает как Proxy и умеет записывать все выполняемые Вами запросы. Для такого способа создания теста Вам понадобиться добавить в WorkBench-> Add-> Non-test elements-> HTTP Proxy Server. Из настроек следует указать как минимум:
* Port. Это порт, который будет слушать JMeter. Я обычно ставлю 9090.
* Target Controller. Создайте новый Thread Group в Вашем Test Plan и выберите его в выпадающем списке Target Controller. Именно в эту группу будут записаны все запросы, прошедшие через прокси.
* URL patterns to Include/Exclude. Данный пункт позволит Вам указать c помощью RegExp, какие именно запросы, прошедшие через прокси, нужно сохранить в тест план. Советую для экспериментов попробовать сначала не заполнять данный пункт, а затем отфильтровать только ".*html" к примеру, чтобы почувствовать разницу.
Не забывайте перенаправить свой браузер на вновь созданный прокси (я, например, пользуюсь FoxyProxy для быстрого переключения режимов прокси в браузере) и стартовать/останавливать JMeter HTTP Proxy Server.

3. Создание теста программно. Дело в том, что Test Plan сохраняется в XML, который не сложно создать программно, если есть такая потребность.


О JMeter помимо документации:
- Помимо расширяемых модулей, поддерживает 2 скриптовых языка JavaScript и BeanShell. BeanShell - это полноценная скриптовая Java.
- Поддерживает Cookies, что позволяет авторизировать/регистрировать пользователей прямо в тесте.
- Практически в любом поле JMeter можно ввести переменную вместо значения. Вообще работа с переменными достаточно гибкая и удобная.
- Пользуясь PostProcessor'ами можно вычленять из ответа сервера информацию и сохранять её в переменных для последующих запросов.
- Есть помошь по функциям Main menu-> Options-> Function Helper Dialog
- В HTTP Sampler есть галочка "Retrieve all embedded resources from HTML files", которая бывает полезной для эмулирования полноценных пользовательских действий.

Горячие клавиши и неявные настройки.
- Если Ваш JMeter стартует за прокси сервером и ему нужен доступ наружу, Вам помогут ключи при старте -H <host> -P <port> -u <user> -a <password> -N <non-proxy-hosts>
- При включенном GUI и графических слушателях JMeter использует достаточно много ресурсов компьютера - для нагрузочного и стресс тестов используйте non-GUI опции запуска
- Распределённое тестирование управляется одним инстансом JMeter, который может распространить нужный тест, собрать результаты со всех нод, и производить некоторое управление распределённых нод.
- Ctrl+R - запустить тест
- Ctrl+. - остановить тест
- Ctrl+E - очистить результаты

index

Monday, 5 October 2009

CloudMade in action

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

Всё ПО и данные распространяются под открытыми лицензиями (правда если вы модифицируете OSM данные в какой-либо формат, вы обязаны поделиться результатом преобразований с общественностью). В связи с этим фактом и неоспоримым качеством созданных карт существует достаточно большое количество проектов, призванных отшлифовать накапливаемое знание и предоставить конкурентноспособные сервиса.

CloudMade - компания, которая сумела запустить сразу несколько интересных проектов на базе OSM данных и при этом внести ощутимую лепту в развитие картографического сообщества.
- Поскольку это одна из ранних компаний использующих OpenStreetMap, она успела накопить и сформировать достаточно большое количество всевозможных фильтров данных (напомню, что OSM построена по принципу Wiki, а потому там иногда появляются дороги по экватору, подводные магистрали и т.п. вещи, которые Вы не увидите в продуктах CloudMade). Более того, все преобразованные данные доступны для публичного доступа.
- Разработаны всевозможные библиотеки для создания условий комфортного внедрения разработчиками карт от CloudMade.
- CloudMade занимается организацией Mapping parties, впрочем как и многие другие, но на мой субъективный взгляд гораздо более активно. А многие активисты CloudMade создают локальные комьюнити.
- Доступны карты как таковые, с большим спектром возможностей: построение маршрутов, геокодирование, векторными SVG картами, прекрасным редактором стилей, возможностью выгрузки построенного маршрута в GPX (формат, понятный для GPS устройств), равно как и загрузка карт на GPS устройства.
- В процессе финальных тестирований редактор OSM карт, который позволит пользователям более интуитивно справляться с задачей маппинга и автоматизировать некоторые трудоёмкие процессы.
- И многие другие приятные мелочи по ошибке или по другим причинам не включенные в данный обзор.

Будут вопросы - обращайтесь, расскажем что к чему.

index