• Как подключиться к Xdebug запущенному в Docker контейнере на удаленной машине?

    voskobovich
    @voskobovich Автор вопроса
    PHP Developer | 8+ years exp.
    Вот развернутый ответ на мой вопрос.

    Рассмотрим ситуацию со стороны удаленного сервера на котором запущен докер контейнер.
    Докер уже позаботился о бОльшей части проблемы и сделал все роуты так, что ты из контейнера можно было пинговать интерфейс eth0, через который должен поступать интернет на серверную машину. Мало того, из контейнера можно пинговать любой хост на докер-хосте, кроме 127.0.0.1 самого хоста - по вполне понятным причинам (127.0.0.1 из контейнера будет lo интерфейс самого контейнера).
    Допустим IP на eth0 вашего хоста 10.45.6.87. То есть пинг из докер контейнера на 10.45.6.87 должен проходить успешно.
    А раз eth0 это выход во внешний мир, значит можно xdebug`у сказать, что клиент будет на хосту 10.45.6.87 порт 9000, пусть там его ждет. Мы же потом сделаем туда SSH тунель.

    Создаем тунель.
    Пробрасываем удаленный порт через SSH-тунель на локальную машину
    ssh -R 9000:localhost:9000 user@server.com
    и рассчитываем на то, что в итоге бинд на удаленной стороне будет выглядеть так
    10.45.6.87:9000 => 127.0.0.1:9000
    но мы сильно ошибаемся :)
    И эта ошибка стоит нам кучи времени.

    Давайте посмотрим что нам скажет netstat -plnt.
    А сказать он должен, что после запуска тунеля, на удаленной машине мы имеем бинд на
    127.0.0.1:9000, а не 10.45.6.87:9000 как ожидали.
    То есть, получается, что xdebug ждет клиента на 10.45.6.87:9000, а после открытия тунеля клиент оказывается на 127.0.0.1:9000.
    Беда в том, что забиндить клиента мы можем только на локальный хост.
    Так написано в доке man ssh.

    Из контейнера мы 127.0.0.1:9000 докер-хоста увидеть не можем, а значит остается только сделать роутинг пакетов с 10.45.6.87:9000 на 127.0.0.1:9000 внутри удаленной машины.
    Сделать это можно множеством способом, в том числе и iptables. Лично я сделал еще один SSH тунель внутри своего сервера вот так:

    1. В конфигах xdebug указываем
    xdebug.remote_port = 9001
    xdebuh.remote_host = 10.45.6.87

    2. На свою локальную машину через тунель с виртуалки прокидываем порт 9000.
    ssh -R 9000:127.0.0.1:9000 user@server.com
    3. На локальной машине создаем тунель с порта 9000 на 9001
    ssh -g -L 9001:localhost:9000 -f -N 127.0.0.1
    Вот и все.

    Но стоит учесть, что это решение рассчитано только на одного разработчика и полно костылей.
    Так что через пару дней после понятия проблемы я поднял на том же сервере OpenVPN сервер в докере и проблема отпала сама собой.
    Поясняю. VPN создает виртуальную локальную сеть. Моя локальная машина и моя виртуалка которая находится на серверах хостинг-провайдера оказывается в одной локальной сети. А раз так. В таком случае, я могу из docker-контейнера запущеном на виртуалке пинговать свою локальную машину. Значит Xdebug будет подключаться сразу к моей локальной машине без всяких пробросов и костылей.

    При таком раскладе можно настроить Xdebug двумя способами.
    Первый.
    Xdebug будет стучаться на конкретный IP.
    xdebug.remote_port = 9000
    xdebug.remote_host = <IP локальной машины>

    Это полезно когда вы один разработчик на проекте и нужно отлаживать консольные скрипты.

    Второй.
    Xdebug будет стучаться на IP с которого пришел запрос.
    xdebug.remote_connect_back=1
    xdebug.remote_port = 9000

    Удобно, когда работает команда разработчиков, но не удобен когда нужно отладить консольный скрипт. При запуске скрипта в консоли нужно передавать Xdebug`у IP локальной машины разработчика, чтобы он знал куда отдавать дебаг-логи.
    Ответ написан
    1 комментарий
  • Чем лучше анализировать поведение пользователя на сайте?

    ArsenyMatytsyn
    @ArsenyMatytsyn
    Руководитель frontend направления, предприниматель
    Matomo (Piwik)
    Ответ написан
    Комментировать
  • 7 лет опыт разработчиком + 13 лет в продажах и бизнесе. Дальнейшей выбор направления IT?

    paran0id
    @paran0id
    Умный, но ленивый
    Presale Engineer
    Ответ написан
    Комментировать
  • Что учить (на будущее) для back-end веб приложений?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    5cbadd2d35ab2283111560.png
    Ответ написан
    Комментировать
  • Оптимизировать код или как выделить всю вычислительную мощность пк на его выполнение?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Первое, что бросается в глаза - это многократное копирование массива. Представьте, что при сортировке мы бы после каждых двух-трех перестановок делали бы полный дубликат массива. Это же ужас! И это слабое место, постоянное перевыделение памяти больших размеров.

    Второе, что тоже важно - это сложность O(N*N). В вашем случае это критично, потому что много элементов в исходном массиве.

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

    И маленькая оптимизационная хитрость - поиск интервала происходит по индексу, то есть O(1). Нужно немного поразмыслить, чтобы до этого догадаться, но в целом всё просто.
    Код
    <?php
    $arr = [100,125,75,175,25,300,275,325,375];
    $step = 50;
    
    $b = []; //-1 - deny, 0 - not set, 1 - has interval
    $int = []; //intervals if necessary 
    $step2 = intdiv($step,2);
    $arr = array_values(array_filter($arr, function($v) use ($step2,&$b,&$int) {
        $i = intdiv($v,$step2);
        $mod = $v % $step2;
        $res = true;
        if (isset($b[$i])) {
            if ($b[$i] === -1) $res = false;
            elseif ($mod < $int[$i][0] or $mod > $int[$i][1]) $res = false;
        }
        $b[$i] = -1;
        $b[$i+1] = -1;
        $b[$i-1] = -1;
        if (!isset($b[$i+2])) {
            $b[$i+2] = 1;
            $int[$i+2] = [$mod,$step2];
        } elseif ($b[$i+2] === 1) {
            if ($int[$i+2][0] < $mod) {
                $int[$i+2][0] = $mod;
                if ($int[$i+2][0] >= $int[$i+2][1]) $b[$i+2] = -1;
            }
        }
        if (!isset($b[$i-2])) {
            $b[$i-2] = 1;
            $int[$i-2] = [0,$mod];
        } elseif ($b[$i-2] === 1) {
            if ($int[$i-2][1] > $mod) {
                $int[$i-2][1] = $mod;
                if ($int[$i-2][0] >= $int[$i-2][1]) $b[$i-2] = -1;
            }
        }
        return $res;
    }));
    
    var_dump($arr); // [100, 175, 25, 300, 375]
    ?>

    Переписав алгоритм на С++, получите дополнительно 50-кратное увеличение скорости.
    Ответ написан
    3 комментария
  • Как это работает(сайт угадывающий загаданное число)?

    Lynn
    @Lynn
    nginx, js, css
    вы задумали даузначное число. Пусть это будет 10а+б. Вычитаем из него цифры а и б. Получаем 10а+б-а-б=9а (внезапно). А теперь посмотрите на таблицу внимательно. Там все делители 9 обозначены одним символом
    Ответ написан
    Комментировать
  • Какие материалы можете посоветовать по архитектуре программных продуктов?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Сначала надо получить хотя бы 5 лет реального опыта программирования на проектах, которые разрабатывают и поддерживают более десяти человек более одного года. Только потом появляются возможность нормально осмыслить книги вроде "Чистой архитектуры" Мартина и "Designing Data-Intensive Applications" Клеппмана. А после их чтения появляются возможность куда-то двигаться и понимание куда.
    Ответ написан
    Комментировать
  • Как в Yii2обеспечить текущую работу в соседних вкладках, если пользватель запустил "тяжелый" (долгий) запрос?

    Если сессии хранятся в файлах, то перед началом тяжелого запроса закрывайте сессию, так как PHP не может открыть новую сессию, если не закрыта предыдущая
    Ответ написан
    1 комментарий
  • Какую книгу подарить программисту?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    5c133ef9db284397856577.png
    Ответ написан
    Комментировать
  • Выбор средств разработки для системы учета. Что выбрать?

    Sanes
    @Sanes
    PHP нормально подходит. Вам нужен всего лишь программист.
    Ответ написан
    Комментировать
  • Как выгрузить записи по ближайшим городам определенного радиуса?

    kawabanga
    @kawabanga
    1) использовать яндекс АПИ, чтобы конвертировать адрес в координаты. (геокодер) проходим по бэкенду и конвертируем адреса. потом конвертируем уже при добавлении нового мероприятия. Заметьте, это раньше нарушало лицензионное соглашение яндекса.
    2) Смотрим в сторону POINT. Наблюдаем за Spatial index если данных/пользователей много(mysql 5.7.19+)
    3) читаем доки по гис функциям. ST_Distance_Sphere . В yii2 есть пара библиотек для работы с point.
    4) грубо вычисляем город пользователя и координаты - ip-api.com
    5) точно вычисляем место пользователя, используя гугл мапс и систему определения локации. работает точнее, но заморочек больше.

    По сути, если что-то не получается, можно ограничиться конвертацией адресов в координаты, использовать не радиус, а квадрат вокруг пользователя, пусть даже не точный.
    Ответ написан
    Комментировать
  • Счего начать изучение DevOps?

    @yellowmew
    Cloud infrastructure, monitoring engineer. SRE
    Saboteur неплохо ответил(что не отменяет того что все остальные ответившие тоже правы)
    Девопс - это практики. Это не набор инструментов( инструменты используются на определенных этапах, реализация которых необходима для приближения к идеалу), однако определенные необходимые инструменты опять же есть.
    Про девопс можно прочитать очень много информации, но я, как админ (win-админ :D) вижу ситуацию для вас, как и любого, с опсовой основой, примерно так:
    1. Жирным вы выделили вопросы который для вас вот конкретно сейчас не играют ни малейшей роли. Дмитрий Шицков и Saboteur написали почему: зависит от проекта.
    2. Завет любого ops-а: автоматизируй всё что можно
      Если выбор между configuration management (chef, ansible, puppet и тд) и скриптами - то лучше первое. Хотя и тут можно поспорить, у меня в проекте chef-ом автоматизированное не очень-то используется на последнем этапе доставки в прод, поскольку мы все равно запечатываем машину и запускаем в AWS с asg без пост-конфигурации. Тут можно до посинения спорить хорошо это или нет, но скрипты в идеальном мире проигрывают DSL
    3. Вы пишете код для автоматизации
      Вам понадобится git (который тянет за собой git-хостинг: bitbucket, github, gitlab и тп.) и навыки правильной работы с гитом. Для отслеживания и планирования изменений - понадобится какой-нибудь таск трекер (jira, таск трекер встроенный в gitlab, что-то другое).
    4. Инфраструктура как код
      Автоматизируй всё означает автоматизацию развертывания инфраструктуры
      Здесь уже вступают в силу особенности вашего окружения - в облаках вы скорее всего захочете использовать terraform или, например, CloudFormation в AWS - встроенное средство оркестрации, или же будете сразу все запускать в контейнерах - docker , kubernetes используя соответствующие инструменты.
    5. Мониторинг
      Без правильного и подходящего вашему продукту мониторинга(+логирования) жить нельзя. И это было еще до DevOps тренда - это классика администрирования. Здесь ничего не посоветую, с Zabbix-ом сам не ужился, переехал на influx и прилегающие (TICK stack). Для логирования - graylog, ELK. В некоторых частях используется prometheus который в том числе и для кубера удобен. В общем - с чем подружитесь.


    Это только то, что вы уже должны знать и вам легче будет к ним приступить.
    Будете хорошо ориентироваться (не только знать, но и выбрать правильные инструменты, уметь построить правильный пайплайн) - вас с руками оторвут, несмотря на то что вы можете быть слабы в других областях (тестирование, билд и проч.)

    Для примерного осознания всего цикла можно посмотреть на (картинка относительно рандомная,таких много, два года назад я ориентировался по другой, с более подходящим мне списком инструментов, но найти не могу =( )
    Slide1.jpeg

    P.S. Еще раз хочу отметить что описанное выше основано на личном опыте и это - движение в devops со стороны ops. Есть те, кто сразу пытаются строить все по девопсу параллельно обучаясь опсовой части и девелоперской( видел таких, не у всех получалось ). Есть те, кто двигается в девопс со стороны Dev. Все будут иметь разные мнения что важно для того, чтобы начать
    Ответ написан
    1 комментарий
  • Как правильно обратиться к БД оператором INSERT INTO?

    DevMan
    @DevMan
    1. предлагаю прекратить учиться по этой книге - глядя на представленный код, она не научит вас ничему хорошему.
    2. как минимум воспользоваться функцией https://secure.php.net/manual/ru/mysqli.error.php для получения описания ошибки.
    Ответ написан
    2 комментария
  • Кто знает простые альтернативы JQuery?

    VanillaJS, очень хороший фреймворк. Перешел на него с jQuery и всем советую.
    Ответ написан
    3 комментария
  • Хочу стать реверс-инженером. Что изучать для этого?

    Adamos
    @Adamos
    "Хочу стать мастером спорта. Посоветуйте, что почитать".
    Ответ написан
    15 комментариев
  • Поскажите хорший курс по алгоритмам?

    @bogomazov_vadim
    Подскажу не курс, а книгу, если именно алгоритмы интересуют - Грокаем алгоритмы. Имхо хорошо подходит для "въезжания" в тему и очень доступно для начинающих.
    Ответ написан
    1 комментарий
  • Как правильно хранить оценки для постов, но быстро сортировать посты по средней оценке?

    inoise
    @inoise
    Solution Architect, AWS Certified, Serverless
    Как уже правильно было сказано должно быть:
    • таблица с постами
    • таблица с оценками
    • таблица с рейтингом

    Прим. Не обязательно таблица, не обязательно база реляционная - для задачи это не играет никакой роли

    Эти 3 сущности напрямую ни через одну логику влиять друг на друга не должны, ибо может привести к довольно печальным последствиям.

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

    Для того чтобы сделать все красиво существуют Message Brokers (RabbitMQ, Kafka, ... да какой угодно в принципе - выбор зависит от требований к системе).
    Архитектура такая:
    1. пользователь оставляет оценку к посту
    2. оценка сохраняется в базе оценок
    3. после сохранения в брокера падает сообщение "у поста 12345 новая оценка" (сама оценка для этого кейса не важна, но ее можно тоже указать)
    4. клиент счастливо идет дальше серфить интернеты, не ожидая обработки всякой логики, которую задумал программист
    5. на той стороне брокера сидит маленький демон и слушает эти события
    6. при появлении события демон моментально пересчитывает рейтинг поста и обновляет его в отдельной таблице
    7. при росте нагрузки на демона ничего страшного не происходит - все сообщения встают в очередь и ждут обработки
    8. ну, если хочется совсем все быстро обрабатывать - запускаем ХХХ этих демонов чтобы пережевывали за раз больше информации


    Вот так. Надеюсь вам поможет такой маленький пример их мира энтерпрайз-разработки
    Ответ написан
    4 комментария