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}"

archive

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';

archive

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

archive

Wednesday 17 March 2010

Graph DB

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

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

archive

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 поддерживает циклы только за счет хвостовой рекурсии. Правда компилятор-интерпретатор умён и если придерживаться определённых правил рекурсия при исполнении всё же будет представлена циклом, но это не меняет впечатления программиста при прочтении исходных кодов.

archive