• Как структурно разложить разные Dockerfile для одного проекта?

    glaphire
    @glaphire Куратор тега PHP
    PHP developer
    Dockerfile нужен только если основной образ нужно модифицировать, так достаточно в docker-compose.yml указать название основного образа и прописать пару настроек, если они изначально поддерживаются (имя юзера, пароль и т.п.). Мне например обычно нужно только для php-fpm Dockerfile прописать и иногда для mysql, остальные образы ставлю как есть
    Ответ написан
    2 комментария
  • Теоретический вопрос: можно ли запускать php скрипты и насколько такой подход правильный?

    Очереди и ограниченные по числу консьюмеры решают одну полезную задачу - если пользователь 50 раз запросит переиндексацию, больше чем N процессов не будет работать единовременно и эти 50 запросов не приведут к коллапсу.
    Если под подобные задачи классические mq - тяжело, то можно использовать что полегче - NATS или даже Redis.

    А так-то можно запускать скрипты чем угодно, но подход совсем-совсем не очень. Но честно говоря, есть что и похуже - видел проект в которым php-скрипты генерировали и запускали shell-скрипты.
    Ответ написан
    Комментировать
  • Теоретический вопрос: можно ли запускать php скрипты и насколько такой подход правильный?

    Если я верно понял, то схема такова:

    Producer (1-й PHP скрипт) -> MQ broker -> Consumer (2-й PHP скрипт)

    Это обычная микро-сервисная архитектура. Плюс каждого сервиса в том, что каждый из них не хранит состояние. То есть, производителя "не интересует" судьба отправленной задачи и он не ведет никакого учета по тому что и кому было отправлена задача.
    Если не хочется брать тяжеловесные брокеры очереди сообщений, то можно взять как посоветовал Дмитрий Шицков или даже ZeroMQ.

    Ту же задачу можно решить при помощи создания нового потока в основном потоке программы и ожидания окончания выполнения потока, выполняющего задачу. В случае Го вместо потока создается го-рутина (просто более легковесный вариант потока) - смысл тот же.
    Чтобы не сильно нагружать систему, используют ограниченное количество потоков-потребителей.

    Добавлено
    В случае Го, если не нужно ожидать окончания, то можно отправить задание в канал. Потребители канала должны забирать задания, иначе канал может заблокироваться (по заполнению буфера канала задач или при каждой новой задаче, в зависимости от конфигурации канала).
    Ответ написан
    Комментировать
  • Поясните пожалуйста bash скрипт?

    saboteur_kiev
    @saboteur_kiev Куратор тега Linux
    software engineer
    кода done < <(ls -1 "./my_temp_dir/")

    ls -1 выводит содержание каталога в одну строку по одному наименованию
    <(blabla) создает из команды поток, который передается как файловый десктриптор
    < перенаправление данных из файлового дескриптора в предыдущую команду
    done является частью цикла, поэтому перенаправление идет не в done а в весь блок цикла.
    Ответ написан
    Комментировать
  • Поясните пожалуйста bash скрипт?

    Lynn
    @Lynn
    nginx, js, css
    https://www.opennet.ru/man.shtml?topic=bash&catego...

    Это две разных конструкции.
    Первый знак < это стандартное перенаправление ввода.

    <(...) это Подстановка процессов, т.е. вывод команды в скобках будет как бы файлом.

    В данном скрипте это всё видимо сделано исключительно для демонстрации.
    Ответ написан
    Комментировать
  • Поясните пожалуйста bash скрипт?

    @RayHex
    1. https://tldp.org/LDP/abs/html/process-sub.html
    2. bash это интерпритатор, вы всегда можете вставить куски выражения, и посмотреть что они выдают, например:
    echo <(ls -1 .)
    /dev/fd/63

    3. Ваш код мягко говоря дурно пахнет, а по сути он вообще кривой и будет сбоить на файлах со спецсимволами или даже пробелами. Можно сделать проще и правильнее:
    shopt -s nullglob
    for f in my_temp_dir/*; do
        echo "$f"
    done

    nullglob нужен для случаев когда файлов совсем не будет, без него подставится строка со *, и это может вызвать ошибку в вашем коде.
    Ответ написан
    Комментировать
  • Микросервисная архитектура: насколько микро? и почему не возникает проблем с долгим ожиданием?

    @nApoBo3
    Если единственная проблема, это масштабирование по производительности, до попробуйте решить ее железом и минимальным разделением приложения. Переписывать монолит на микросервисы, это всегда дороже, ОЧЕНЬ СИЛЬНО дороже.
    Ответ написан
    Комментировать
  • Микросервисная архитектура: насколько микро? и почему не возникает проблем с долгим ожиданием?

    @deliro
    Начал изучать тему микросервисной архитектуры, для расписала нашего монолита из-за проблем с масштабируемостью.

    Добро пожаловать в дивный мир микросервисов. Теперь у тебя будут не только проблемы с масштабируемостью, но и куча других.

    ...SRP, т.е. каждый микросервис, должен отвечать только за одну задачу.

    Это не так, SRP говорит о другом.

    Все остальные проблемы — это большие вопросы, которые нужно разбирать долго.
    И прочитай здесь. Если коротко: микросервисы — это инфраструктура. Будешь думать, что они решат твои бизнесовые проблемы — получишь ещё больше бизнесовых проблем и целую гору инфраструктурных. А масштабировать можно и монолит прекрасно.
    Ответ написан
    Комментировать
  • Микросервисная архитектура: насколько микро? и почему не возникает проблем с долгим ожиданием?

    @dimuska139
    Backend developer
    для расписала нашего монолита из-за проблем с масштабируемостью

    Не очень понял связь между монолитом и масштабируемостью. Если следовать вот этим правилам, то любой монолит будет отлично масштабироваться. Я бы на вашем месте проект привёл именно к соответствию этим правилам, а не спешил перелезть на микросервисы, т.к. и у них проблем хватает.
    Проблема 1:

    Почему только 3? У вашего магазина нет авторизации? Есть - это отдельный микросервис. Рассылка элетронной почты есть? Есть - ещё один микросервис. Смски шлёте? Ещё один. Другое дело, что писать это всё, понятное, дело должен не один человек, и, скорее всего, не всё на php.
    Проблема 2:

    Последовательно (синхронно) в кучу сервисов никто запросы не делает. В Guzzle (библиотека для http-запросов) есть асинхронный режим, кстати. То есть можно сразу сделать обращение к нескольким сервисам и собрать результаты (время будет равно времени выполнения самого медленного запроса). Но вы и с фронтенда можете сделать обращение к нескольким сервисам сразу асинхронно ведь. Если вопрос в авторизации, то для этого можно использовать jwt-токены - их каждый сервис может сам валидировать. Также можно кешировать данные в определённых ситуациях и даже дублировать в разных сервисах (в микросервисной архитектуре это допустимо).
    Проблема 3:

    Обычно никак не решается, как ни странно. Распределённые транзакции - это боль. А общую базу для нескольких микросервисов использовать нельзя - это антипаттерн.

    P.s. возможно, в вашем случае не нужно всё дробить на кучи микросервисов. Это долго, дорого, трудоёмко - и сложно сделать так, чтобы было удобно, особенно когда опыта нет. Попробуйте что-то одно отделить по мере надобности, потом другое. А дробить бездумно точно никакого смысла не имеет.
    Ответ написан
    Комментировать
  • Микросервисная архитектура: насколько микро? и почему не возникает проблем с долгим ожиданием?

    angrySCV
    @angrySCV
    machine learning, programming, startuping
    обычно микросервисы нарезают так чтоб они обслуживали отдельную "тематику", которую можно было бы отдельно маштабировать и отдельно дорабатывать, от всех остальных. Пример:
    микросервис который обрабатывает работу каталога (и всё что связанно с ним), отдельно микросервис который будет работать с доставкой и отправкой заказов, микросервис который работает с партнёрской программой и начислением балов лояльности, и микросервис который занимается обработкой платежей. У каждого из этих микросервисов желательно иметь свою БД, тогда они могут независимо друг от друга работать и независимо маштабироваться, только отвечая потребностям свой нагрузки - очевидно нагрузка на каталог сильно выше чем на сервис обработки платежей (например каталог может обрабатывать 10 узлов, заказы обрабатывают 3 узла а платежи 1 узел)
    При использовании монолита вы масштабируете сразу все сервисы на узлы, что не так эффективно.
    -------
    По поводу перфоманса - при такой нарезке как описал выше, у вас крайне редко будет ситуация когда для ответа на один запрос от пользователя, нужно будет опрашивать сразу несколько сервисов, НО даже в таких ситуациях не так важна задержка между вызовами, сколько возможность масштабировать обработку этих запросов.
    -------
    транзакционность обычно осуществляется через SAGA паттерн.
    По поводу консистентности - если ты начинаешь масштабировать систему, значит состояние размазывается по множеству разных узлов/сервисов, вся суть что эти узлы/сервисы могут независимо друг от друга работать, значит консистентность будем мешать независимой работе (тоесть производительности), если сервисы зависимы то они не маштабируются (раз один узел ожидает что-то для работы от другого узла), поэтому там предъявляются "ослабленные требования" к консистентности состояния, как правило используют eventual consistency (согласованность в конечном счете), говорят что рано или поздно типа состояние в системе будет согласованно, если не будут поступать новые данные)
    ну а пока данные поступают, то состояние может быть не согласованно между узлами.
    Ответ написан
    Комментировать
  • Микросервисная архитектура: насколько микро? и почему не возникает проблем с долгим ожиданием?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Вы задаётесь очень сложными вопросами, развёрнутый ответ на каждый из которых вряд ли влезет в лимит символов ресурса. Чтобы разобраться с первой проблемой, стоит прочитать "Предметно-ориентированное проектирование" Эванса. Грубо говоря, микросервис должен оперировать небольшим самостоятельным подмножеством данных. Для поиска ответов на вторую и третью проблему хорошим стартом может быть "Высоконагруженные приложения" Клепмана. Да, взаимодействие внутри микросервисной системы очевидно медленнее, чем вызовы внутри монолита, у всего есть цена. Но при правильно написанном коде, правильно выбранной архитектуре и правильно построенной инфраструктуре скорость всё ещё достаточно, чтобы отвечать на запросы за доли секунды. А для согласованности приходится применять подходы вроде паттерна "сага".
    Ответ написан
    Комментировать
  • Docker: один сервис - один контейнер?

    vabka
    @vabka
    Токсичный шарпист
    а если у меня 10 микросервисов, у каждого своя бд, то мне необходимо помимо всего иметь 10 контейнеров в каждом из которых будет только mysql ?

    Да. 10 контейнеров для приложений и 10 для бд.
    Правда засовывать бд в контейнеры - это не очень хорошая практика, тк им часто очень нужно быстро обращаться к диску, а всякие докеры и кубернетесы добавляют кучу оверхеда (либо кучу работы для опсов).
    Часто, установленной на отдельной машине СУБД + пары реплик более чем хватает для всех сервисов..

    не совсем понял для чего это нужно? и как потом не путаться во всем этом ?

    Как не путаться - даёшь нормальные имена всем штукам.
    не совсем понял для чего это нужно?

    Докер или засовывание в контейнер только одного процесса?
    Ответ написан
    4 комментария
  • Микросервисная архитектура: насколько микро? и почему не возникает проблем с долгим ожиданием?

    @vitaly_il1
    DevOps Consulting
    1. ИМХО, 90% зависит от задач и от организации. То есть есть смысл в сотнях сервисах для громадной фирмы, но мне трудно представить чтобы это имело смысл для группы из трех разработчиков
    2. Как уже сказали, если не тормозит то потому что сервисы очень близко друг к другу. Но скорость - не единственная проблема. Мониторинг, дебаггинг - все выглядит совсем не так как раньше.
    3. Насколько понимаю тут идет серьезный спор - одна база на всех или база для микросервиса.

    Disclaimer - я DevOps, не архитект.

    См.
    https://world.hey.com/joaoqalves/disasters-i-ve-se...
    https://medium.com/microservices-in-practice/micro...
    https://k8s.af/ - Kubernetes Failure Stories
    highscalability.com/blog/category/example - Real Life Architectures
    Ответ написан
    Комментировать
  • Как правильно реализовать continuous deployment для запуска миграций?

    saboteur_kiev
    @saboteur_kiev Куратор тега Git
    software engineer
    Ну все руками делается.
    Делаете каталог для файлов миграции и в нем какой-то главный типа control.sh
    в control.sh инклюдите актуальные файлы миграции
    Для дедупликации проще всего в базе сделать таблицу, в которую при миграции добавляется "дата, имя скрипта миграции, статус (completed/failed), и при выполнении скрипта миграции соответствнено он проверяет по базе выполнялся уже или нет, чтобы не запускаться вторично. Может быть какие-то скрипты наоборот нужно прогонять каждый раз, тогда можно в таблицу добавить колонку для такого флага.

    И все. При автодеплое конкретной версии - в ее ветке оно найдет в control.sh список миграционных скриптов, control.sh через базу данных может перепровить надо ли их запускать или пропустить, если они уже выполнились, или выполнить независимо от этого и сделает запись в базу о выполнении.

    Естественно контроль - ответственность разработчиков, магии тут не будет. И предполагается, что вы всегда деплоите более позднюю версию поверх старой.
    Ответ написан
    Комментировать
  • RabbitMQ: как правильно выполнять тяжелые задачи?

    part_os
    @part_os
    Сложное в простом
    А как вы поддерживаете соединение с БД, если в течении генерации отчёта нету запросов к ней? Мы делаем ping к БД, так же и к ребитту тем самым сообщая что косьюмер живой м работает.
    Ответ написан
    2 комментария
  • Куки основного сайта "мешают" сайту на поддомене?

    @maltf0
    Добавьте в init.php
    session_name(\Bitrix\Main\Config\Option::get('main', 'cookie_name') . '_PHPSESSID');

    И в настройках Главного модуля -> Имя префикса для названия cookies
    Ответ написан
    Комментировать
  • Как вывести теги на основе php-массив (использую только 1 цикл)?

    Вот так вроде работает:
    $html = array_reduce(array_keys($arData), function($data, $i) use ($arData) {
        $item = $arData[$i];
        $is_last_item = $i == count($arData) - 1;
    
        if ($i == 0) {
            $data['result_html'] = '<div class="items-container">';
    
            if ($item['group']) {
                $data['group_html'] = '<div class="group" data-group="' . $item['group'] . '">'
                    . '<div class="item">' . $item['title'] . '</div>';
            } else {
                $data['result_html'] .= '<div class="item">' . $item['title'] . '</div>';
            }
        } else {
            if ($item['group']) {
                $previous_item = $arData[$i - 1];
    
                if ($previous_item['group']) {
                    if ($previous_item['group'] == $item['group']) {
                        $data['group_html'] .= '<div class="item">' . $item['title'] . '</div>';
                    } else {
                        $data['result_html'] .= $data['group_html'] . '</div>';
                        $data['group_html'] = '<div class="group" data-group="' . $item['group'] . '">'
                            . '<div class="item">' . $item['title'] . '</div>';
                    }
                } else {
                    $data['group_html'] = '<div class="group" data-group="' . $item['group'] . '">'
                        . '<div class="item">' . $item['title'] . '</div>';
                }
    
                if ($is_last_item) {
                    $data['result_html'] .= $data['group_html'] . '</div>' ;
                }
            } else {
                if (strlen($data['group_html'])) {
                    $data['result_html'] .= $data['group_html'] . '</div>';
                    $data['group_html'] = '';
                }
    
                $data['result_html'] .= '<div class="item">' . $item['title'] . '</div>';
            }
        }
    
        if ($is_last_item) {
            $data['result_html'] .= '</div>' ;
            return $data['result_html'];
        } else {
            return $data;
        }
    }, [
        'result_html' => '',
        'group_html' => '',
    ]);


    Только у вас в ожидаемом результате, кажется, ошибка: должно быть
    <div class="group" data-group="3">
    вместо
    <div class="group" data-group="4">
    Ответ написан
    Комментировать
  • RabbitMQ: как правильно выполнять тяжелые задачи?

    @yarkin
    Была подобная проблема, сишный клиент в один поток не умел нормально в heartbeat. При отключении heartbeat'ов на уровне AMQP протокола были проблемы с "зависшими клиентами" на стороне RabbitMQ, когда приложение выходило непредвиденно. Настройка TCP keepalive помогла решить данную проблему.
    Не знаю точно как работает современный php, но, если есть возможность держать отдельный поток для поддержания AMQP коннекта с включённым heartbeat'ом, то это будет лучше, чем через TCP keepalive. Отсылать ack обратно лучше всё же после завершения обработки задачи.
    Ответ написан
    Комментировать
  • RabbitMQ: как правильно выполнять тяжелые задачи?

    @dmtrrr
    Backend developer
    Это выглядит как проблема библиотеки php-amqplib, php до сих пор не умеет в многопоточность?
    Можно создавать процесс, который будет генерировать отчет.
    Ответ написан
    Комментировать
  • RabbitMQ: как правильно выполнять тяжелые задачи?

    samodum
    @samodum
    Какой вопрос - такой и ответ
    Сам консюмер не должен обрабатывать задачи. Его основное назначение - разгрузить очередь и отправить задачи дальше, например в базу данных или на другие сервера через балансировщик. Лучше всего первый способ.
    Далее некий воркер смотрит необработанные задачи в базе данных и неспеша их обрабатывает. Обработанные задачи помечает флагом.
    Ответ написан
    2 комментария