ZeroNet Blogs

Static ZeroNet blogs mirror

BORS©.Blog

Блог PHP-фреймворка и просто разной DevOps всячины

По случаю тут вспомнилось. Тесты «мат-фильтра» пришлось сразу пополнить «словами-исключениями». А то, типа, как на известном военном авиафоруме долгое время слово «истребитель» писалось со звёздочккми: «истр*тель». Военная авиация! :D Но со временем стали попадаться более редкие и изысканные обороты, требующие пополнения матфильтра с обоих сторон. «Разрешённые» слова из юнит-теста привожу тут для прикола :)

    static function __unit_test($test)
    {
        // Список нормальных слов с выглядещами обсценно подстроками.
        $allowed = ['ансамбля Джебат дебаты колебания колебать колебаться постебаться дебилов учёба'];
        $allowed[] = 'Усугубляясь истребители застрахуйте рубля Хулиганы потребляет потреблять тихую психуют психующим';
        $allowed[] = 'оскорблять уподобляться Усугубляясь Олеговна плохую лихую употребляющих сухую глухую';
        $allowed[] = 'хребтами Глеб Глеба небу сабля гребля корабля лапидарий скипидар туебень залужью';
        $allowed[] = 'абляция'; // В начале строки!
        $allowed[] = 'аббляционного веба потребляемого стеблями констебля';
        $allowed[] = 'небу ещёб ещеб нёбу хлебом Пиебалгс деблокировать хлебнуло хулит';
        $allowed[] = 'ибупрофен Ибашники';
        $allowed[] = 'хребтом хребтами хребту сердцебиение досудебную колеблется беби мразеблоггерша';
        $allowed[] = 'дирижабля дубля волшебную внеблоковый пищеблоку хребта ассеблеров';
        $allowed[] = 'заштрихуйте Хулиан Хулио потребную Хулимсунт'; // Хулимсунт — посёлок такой.
        $allowed[] = 'хулахуп ибо хулению служебную Себу'; // Себу — провинция на Филиппинах.

// ...

Похоже, нужно возвращаться к идее индивидуальных серверов БД в LXC-контейнерах. С одной стороны, это заметный оверхед по памяти/кешам, из-за которых я и пришёл к идее использования общей БД на хосте для всех контейнеров, с другой стороны, начинается каша при попытке многосторонней репликации баз данных и лишний геморрой при переносе контейнера на другой сервер. Когда всё в локальной БД контейнера, то этот контейнер можно тупо запаковать и перебросить куда надо целиком.

Единственное, над чем надо ещё подумать, делать ли LXC-контейнер полностью автономным или держать два отдельных контейнера для БД и для сайта. Во втором случае получаются лишние сущности, но процесс переноса можно разделить на этапы.

Смотрю тут движки форумов. Вижу на официальном сайте одного из них в новостях вот такое чудо :D

wtf-developers.png (647x258)

Яндекс...

- Posted in BORS©.Blog by with comments

Что-то Яндекс совсем опустился. Вот, к примеру, подобные записи в блоге:

http://www.zites.cf/2016/03/6-new-troubles

Уникальный для Интернета контент. Никаких копипаст. Однако, из поиска выбрасывается: «Недостаточно качественный контент». И такое — сотнями. Ну и какого им ещё нужно, блин?

yandeks-hernya.jpg (300x200)

Возвращаясь к старому спору :)

У меня тут образовался новый и пока пустой сервер на Scaleway. Решил сравнить свежим взглядом и посмотреть, что изменилось с последних моих тестов. Использую всё тот же sysbench, тест complex на 1 млн строк. Три варианта:

  • host через сокет
  • host через 127.0.0.1
  • docker с мапингом на 127.0.0.1

Условия:

  • Конфиги идентичны (оптимизированы)
  • MariaDB-10.2.7. На хосте — Ubuntu xenial, в Docker — официальный образ на jessie.
  • Сам каталог базы контейнера смонтирован в хост
  • Параметры docker по умолчанию, запуск через docker-compose

Результат, итоговый, минимальные значения из небольшой серии.

Тип transactions/30s min time avg time 95 percentile
сокет 39506 3.1мс 6.2мс 9.6мс
127.0.0.1 32856 3.9мс 7.3мс 10.9мс
docker 17622 6.4мс 13.6мс 20.4мс

В общем, если без хитростей, то docker по-прежнему вдвое медленнее. Если с хитростями, то я пока не знаю, куда копать :)

WTF-Code

- Posted in BORS©.Blog by with comments

Кидал тут в группу в Telegram примеры WTF-кода, которые встречал в своей практике. Решил и тут поделиться :)

Миграции БД

- Posted in BORS©.Blog by with comments

Уже писал ранее в одном из блогов (когда же я их объединю? :) ) о проблеме выбора места для хранения миграций composer-пакетов. Пока у нас один только набор миграций для приложения, проблемы нет. Когда же надо поддерживать отдельно пакеты composer, то нельзя их миграции хранить в общей базе. Они могут обновляться независимо! Значит, или по отдельной таблицей на каждый пакет в общем базе в MySQL (как правило) или, чтобы не засорять базу, по отдельному файлу sqlite для каждого пакета в composer/data. Склонялся ко второму варианту, но (отчасти из-за лени) реализовывал первый. Это меня и спасло, когда пришлось при отладке постоянно перегружать старые дампы сторонней БД. Если бы история миграций хранилась отдельно, в локальном sqlite, был бы облом из-за несоответствия БД и истории миграций. А тут, поскольку и история и БД хранятся вместе и консистентны, просто делаем phinx migrate после каждой загрузки дампа. И всё прекрасно обновляется.

Так что отныне — всегда отдельная таблица для отдельного пакета!

Я много лет использовал PEAR Image_GraphViz и не знал бед. Но теперь этот пакет устарел, не поддерживается, его нет в Composer и так далее. Вчера потребовалось по-быстрому вывести на PHP пару диаграмм из БД. Решил сделать современно/модно/молодёжно. Полез в libraries.io, отсортировал по популярности пакеты Composer с подстрокой Graphviz и... Завис. Есть монолитные пакеты, генерирующие готовые изображения, но с очень куцыми функциями, не реализующими многое из возможностей GraphViz. Есть в большом ассортименте более гибкие пакеты, создающие GraphViz-скрипты (для dot), но нет средств рендерить их. Два часа угрохал, но так ничего штатными средствами и не добился. Плюнул, быстро слепил костыль с прямой генерацией строками скрипта и вызов dot через exec, сделав задачу за 10 минут. А с библиотеками придётся разбираться позже :-/

Раньше активно использовал для запуска приложений синглтоны:

\Balancer\Board\App::instance()->run();

Пришлось отказаться. Ибо появились случаи, когда это же самое приложение нужно регистрировать внутри главного для работы по отдельным адресам. Так что теперь только фабрики!

\Balancer\Board\App::factory()->run();

Для простых случаев «один сайт — одно приложение» разницы нет, но в сложных... Я долго так ловил одну ошибку, не понимая, почему не срабатывает роутинг :)

Основательно зарылся в один крупный проект (конечно же, на BORS©), так что давно не писал ничего. А вылезла заметная проблема — с новым App-подходом, когда вся работа идёт не в рамках одного глобального приложения, а с локальными приложениями, вешающимися на конкретные домены и пути, отвалилась навигация («хлебные крошки»), ссылающаяся на посторонние ресурсы. Например, у нас форум на одном домене, а родителем к нему прописана страница в другом домене. Раньше второй проект всё равно был доступен в общей каше кода, теперь — нет. Нужно повесить этот проект при инциации приложения в точке входа на нужный домен:

// Форум
\Balancer\Board\App::instance()
    // Вот, то, что нужно, чтобы форум ссылался на нужную корневую страницу
    ->reg_app(\Balancer\Site\Main::class, '//www.balancer.ru/')
    ->run();

Следует обратить внимание на // вместо http:// или https://. Сейчас в движке происходит отход от использования явного указания протокола, поскольку это чревато проблемами http-ресурсов на https-страницах.