• Как избавиться от требования обработки исключения в Project Reactor?

    Vamp
    @Vamp
    неужели есть только один вариант это обрабатывать с поощью try/catch внутри каждого блока что бы избежать Unhandled exceptions?

    Вобщем-то да. Можно вынести try/catch в отдельный универсальный метод, который оборачивает исключение в RuntimeException:

    private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) {
        return Mono.fromCallable(() -> clazz.getDeclaredConstructor(Server.class, Channel.class))
            .map(constructor -> ex(() -> constructor.newInstance(this.manager.getServer(), channel)))
            .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args))
            .onErrorResume(Mono::error);
    }
    
    private <T> T ex(Callable<T> code) {
        try {
            return code.call();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    Конкретно в вашем примере можно вызов конструктора переместить в callable, из которого делается Mono, так как из Callable разрешено стрелять проверяемыми исключениями, в отличии от Function, который принимает map:

    private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) {
        return Mono.fromCallable(() -> {
                var constructor = clazz.getDeclaredConstructor(Server.class, Channel.class);
                return constructor.newInstance(this.manager.getServer(), channel);
            })
            .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args))
            .onErrorResume(Mono::error);
    }
    Ответ написан
    Комментировать
  • Годная книга по Java Core для профессионалов?

    Vamp
    @Vamp
    class loader, JMM, GC

    Это не core, а продвинутые штуки. Их необязательно знать, чтобы программировать на java.

    Если хотите углубиться, то маст хэв - это многопоточность. Лучшая книга на эту тему - Java Concurrency in Practice. Читайте на английском, так как русский перевод ужасен.

    Далее Effective Java, Джошуа Блоха. Классика. Нельзя считать себя java профессионалом, не прочитав эту кингу.

    Ну и JLS. Это уже высший пилотаж. Очень сложное чтиво.

    Ещё посоветую смотреть записи докладов с конференций jpoint, jug, joker. Довольно доходчиво объясняют сложные вещи.
    Ответ написан
    Комментировать
  • Как правильно добавить точку монтирования в docker compose для elasticsearch?

    Vamp
    @Vamp
    Нужно монтировать /usr/share/elasticsearch/data

    volumes:
          - /home/user/green:/usr/share/elasticsearch/data
    Ответ написан
    Комментировать
  • Как на самом деле работает параллелизм?

    Vamp
    @Vamp
    Вопрос 1. Два конвейера позволяют только сократить накладные расходы на context switch. Параллелизм это не увеличивает, так как вычислительное ядро по-прежнему одно.

    Вопрос 2. Верно. Разделите понятия процесс и поток. Думайте о процессе как о контейнере для потоков, а не как об активной сущности, которая исполняет код. В каждом процессе есть как минимум 1 поток. Все без исключения программы стартуют как однопоточный процесс, который имеет возможность превратиться в многопоточный, заспавнив ещё потоков. Ну и, соответственно, ОС шедулит потоки, а не процессы.

    Вопрос 3. Нет. Процессор сам подгружает инструкции из кеша/основной памяти. Потоки не совершают никаких дополнительных действий для этого. Всё происходит прозрачно для потока.

    Вопрос 4. Kernelspace и userspace потоки отличаются только тем, в каких кольцах они исполняются. Kernel потоки исполняются в привилегированных кольцах, а user потоки в непривилегированных. Во всём остальном эти потоки ничем друг от друга не отличаются. Кольца ограничивают набор процессорных инструкций и системных вызовов, которые поток может использовать. Например, чтение файла с диска - это привилегированная операция (так как требует прямого доступа к девайсу), поэтому когда обычный userspace поток хочет прочитать файл, ОС приостанавливает userspace поток и передаёт управление kernelspace потоку, у которого достаточно привилегий на выполнение данной операции.

    Кооперативную многозадачность можно сделать и самому. Концепция называется green threads. В языках программирования встречается уже готовая реализация грин тредов, только называется иначе: корутины (python), горутины (go), виртуальные потоки (java). Все они делают одно и то же - реализуют кооперативную многозадачность в userspace. При большом желании можно написать и свою реализацию грин тредов без использования уже готовых языковых инструментов. Хотя практического смысла в этом мало (кроме нарабатывания опыта).

    Вопрос 5. Думаю, ответ на этот вопрос очевиден из ответа на предыдущий.

    И всё же под "kernel" обычно подразумевают ядро ОС, а не ядро процессора (которое называют core, а не kernel). Единственный способ запустить поток в kernelspace - написать модуль/драйвер ядра. Обычные программы так не могут.

    Финальный вопрос. Правильно понимаете. Вот только "пошаговая стратегия" - это про многозадачность, а не про параллелизм. Процессор с одним ядром многозадачным быть может. Параллельным - нет.
    Ответ написан
    7 комментариев
  • Стоит ли фильтровать пароль на символы?

    Vamp
    @Vamp
    У вас классическая проблема обработки пользовательского ввода. Решается она по-разному в зависимости от контекста, в котором используются данные. Так как вы не указываете контекст, то и ответ будет соответствующе широким.

    1. Запрос первоначально поступает в node.js (конкретно в движок v8, отвечающий за сетевое взаимодействие). Здесь возможны уязвимости, при которых специальным образом сформированный запрос может привести к отказу в обслуживании (DoS), несанкционированному доступу к памяти (вспоминается эпичнейшая уязвимость heartbleed) и иным спецэффектам.

    2. Далее запрос поступает в express, где он парсится и преобразовывается в объект req. Здесь так же могут быть уязвимости, эксплуатируемые путем отправки специально сформированного запроса.

    Пункты 1 и 2 исполняются до вашего кода, поэтому всё что вы можете здесь поделать - это вовремя обновлять софт и библиотеки.

    3. Далее ваш код занимается обработкой данных. Важный момент в этом - санация и валидация данных.

    Санация - это приведение данных к нужному виду. Например, удаление лишних пробелов в начале или конце строки (лишние пробелы чаще всего получаются когда пользователь откуда-то копипастит данные в вашу форму). Ещё пример - удаление ненужных дефисов, скобочек, ведущих нулей и прочих нецифровых символов из номера телефона.

    Валидация - это проверка данных на корректность. Например, вы ожидаете номер телефона в поле phone. После санации останется проверить, что длина номера не нулевая и не больше 15.

    Если данные предполагается передавать дальше, скажем, на удалённый JSON REST сервис, то вы должны будете корректно экранировать строку перед добавлением её в JSON, иначе случайная кавычка сломает ваш запрос.

    Либо если данные будут вставляться в базу данных, то необходимо экранировать данные (либо вставлять данные через подготовленные запросы) чтобы не получить SQL injection уязвимость.

    Вот тут как раз и появляется зависимость от контекста. В контексте базы данных - один способ экранирования. В контексте json - другой. В контексте HTML (при выводе данных пользователю) - третий. В ещё каком-нибудь другом контексте будут свои способы обезопасить данные.

    Если рассматривать конкретно пароль, то с ним всё просто. Как правило, пароли не хранятся на сервере в открытом виде и предварительно подвергаются преобразованию в криптографически стойкий хеш (например, argon2 или scrypt). Сам хеш уже имеет фиксированный размер и известный набор символов. Поэтому санировать пароль не нужно, а при валидации просто проверить минимально допустимую длину, несовпадение с логином, email и может ещё какие-нибудь проверки, навязанные бизнесом или применяемыми стандартами.
    Ответ написан
    6 комментариев
  • Как в контейнере сделаться рутом?

    Vamp
    @Vamp
    Ваш образ создан from scratch. Это значит, что в нём только приложение. И больше ничего лишнего нет. В том числе и бинарника /bin/bash, путь к которому вы указываете в /etc/passwd

    Возьмите образ на основе альпины: anycable/anycable-go:1.2-alpine
    Там есть /bin/sh, пакетный менеджер и ещё всяких разных утилит по мелочи.
    Ответ написан
    1 комментарий
  • Docker / PHP - Как организовать воркеры?

    Vamp
    @Vamp
    "нет возможности из процесса, поднятого в докере запускать под-процессы"

    Это неправда. Те же самые nginx и php-fpm запускают мастер процесс и стартуют кучу своих воркеров как отдельные процессы.

    Простейший способ сделать то что вы хотите - запустить скрипт внутри контейнера

    docker run -d -v /home/project:/var/www php:8.1-cli php /var/www/worker.php

    В дальнейшем если воркер упадет, докер его перезапустит. И таких docker run команд выполняете столько, сколько хотите одновременно работающих воркеров.
    Ответ написан
    3 комментария
  • Как работать с сырыми результатами SELECT MySQL CLI в PHP CLI?

    Vamp
    @Vamp
    Вам придется самостоятельно парсить $res в более удобный массив или объект. Можно слегка упростить вывод mysql, добавив аргумент --batch.
    Ответ написан
    1 комментарий
  • Как авторизовавшись на одном сайте в "сети сайтов", быть автоматически авторизованным и на других?

    Vamp
    @Vamp
    Видел однажды такую реализацию.

    При успешном прохождении авторизации кидает на страницу, где через тег img подключается "картинка" с каждого домена, участвующего в sso тусовке.

    <h2>Вы успешно вошли</h2>
    <img src="https://example.com/auth.php?key=1hB7fa014bbXCDg920">
    <img src="https://example.net/auth.php?key=hVVFD41looas8730MM">
    <img src="https://example.org/auth.php?key=QnaVBhj7mqwaBK9xq6">

    При авторизации создаётся и записывается в базу пачка одноразовых временных токенов, привязанных к только что авторизованному пользователю. При загрузке auth.php проверяется этот токен (передается через key в примере выше) и если токен ещё не просрочился, то выдаётся однопиксельный прозрачный gif с авторизационным кукисом. Этот кукис привязывается к домену, с которого загружается картинка.
    Ответ написан
    2 комментария
  • Зачем освобождать память в C?

    Vamp
    @Vamp
    Потому что неосвобождённая память остаётся занятой даже после выхода указателя за пределы области видимости. В итоге если вы будете только аллоцировать память, но не освобождать её, то рано или поздно программа сожрёт всю память в системе.
    Ответ написан
    1 комментарий
  • Что означает синтаксис dockerfile (php-fpm)?

    Vamp
    @Vamp
    что такое dev суфикс (freetype и freetype-dev) и как понять какую версию ставить (я ставил методом тыка, когда получал ошибки и гуглил)

    Dev суффикс означает, что в данном пакете присутствуют файлы, необходимые для компиляции кода, использующего устанавливаемую библиотеку. Устанавливать нужно обе версии. Обычная версия "freetype" содержит саму библиотеку в so файле, которую gd будет подключать в рантайме. Dev версия "freetype-dev" нужна для сборки самого gd, так как модуль собирается из исходников.

    почему, например, для mycrypt мне сперва нужно загрузить именно libmcrypt-dev, потом через pecl скачать mcrypt, а потом через алиас docker-php-ext-enable включить (экспериментировал и не работает с другими сценариями), а если смотреть на opcache, тот тут сразу docker-php-ext-install и все, а xdebug еще один сценарий: pecl -> docker-php-ext-enable - почему все по разному, как это понять?

    Для разных модулей требуются разные сторонние библиотеки. Для gd это freetype (для работы со шрифтами), libpng (для поддержки формата png), libjpeg-turbo (для поддержки jpeg). У opcache таких зависимостей нет, поэтому ничего дополнительно устанавливать не требуется.

    в чем отличие этих сценариев установки расширений (что делает каждая команда, простыми словами)?

    У php есть модули, которые поставляются с самим php. Например: zip, opcache, pdo_mysql, intl. Такие модули устанавливаются специально предусмотренным для этого скриптом docker-php-ext-install. Этот скрипт распаковывает исходники php, собирает запрошенные вами модули, копирует их в /usr/local/lib/php/extensions/no-debug-non-zts-20190902 (в других образах php путь может отличаться), прописывает загрузку модуля в ini и удаляет распакованные ранее исходники. То есть под капотом скрипт docker-php-ext-install вызывает скрипты docker-php-source, docker-php-ext-configure, docker-php-ext-enable.

    А есть модули, которые хостятся отдельно на сайте pecl.php.net. Это официальный репозиторий, где хостятся всякие разные сторонние модули типа mcrypt, imagick, xdebug. Для их установки нужно использовать утилиту pecl. Так как pecl автоматически не включает модули в ini, из-за этого необходимо самому включать их при помощи скрипта docker-php-ext-enable.

    нагуглил что
    docker-php-source - создает /usr/src/php

    Ещё распаковывает туда исходники самого php и поставляемых с ним модулей.

    docker-php-ext-install - скачивает (ОТКУДА?)

    Из архива /usr/src/php.tar.xz

    docker-php-ext-configure- конфигурирует перед установкой (что это значит?)

    Этот скрипт настраивает настройки, с которыми будет скомпилирован модуль. Например, тот же gd можно собрать без поддержки jpeg если сконфигурировать без опции --with-jpeg. Нужно ли запускать docker-php-ext-configure так же зависит от того, что написано в документации. Очень мало модулей требует предварительной конфигурации перед установкой. Мне на ум приходит только gd.

    В целом, официальная документация php вам поможет понять каким способом нужно устанавливать модули. Смотрим раздел requirements. Если написано "This extension is bundled with PHP", значит нужно устанавливать при помощи скрипта docker-php-ext-install. Если написано что-то вроде "This PECL extension is not bundled with PHP", значит нужно устанавливать через pecl.

    Независимо от способа установки, нужно всегда устанавливать библиотеки, от которых зависят конкретные нужные вам модули. Например, в том же imagick написано "ImageMagick >= 6.2.4 is required". Это значит, что нужно установить библиотеку imagemagick. В вашем базовом образе на основе alpine 3.16 в репозиториях ОС присутствует версия 7.1.0, которая подходит под условие >= 6.2.4:

    /var/www/html # apk info imagemagick
    imagemagick-7.1.0.35-r0 description:
    Collection of tools and libraries for many image formats
    
    imagemagick-7.1.0.35-r0 webpage:
    https://imagemagick.org/
    
    imagemagick-7.1.0.35-r0 installed size:
    4664 KiB


    Для intl нужна "ICU library, version 4.0.0 or newer". Такая библиотека тоже присутствует в репозиториях альпины:

    /var/www/html # apk info icu
    icu-71.1-r2 description:
    International Components for Unicode library
    
    icu-71.1-r2 webpage:
    https://icu.unicode.org/
    
    icu-71.1-r2 installed size:
    796 KiB


    Dev версии библиотек нужны только в момент установки модулей. Дальше их желательно удалить, чтобы уменьшить размер вашего образа.
    Ответ написан
    6 комментариев
  • Установка php в Docker?

    Vamp
    @Vamp
    RUN DEBIAN_FRONTEND=noninteractive apt-get install -y php php-pgsql php-mbstring php-xml php-apcu composer php-mongodb php-curl php-memcached
    Ответ написан
    Комментировать
  • Почему не работает List-Unsubscribe?

    Vamp
    @Vamp
    Спамеры пользуются этой фичей как подтверждением доставки. Раз отписался, значит точно живой и начнут спамить в три раза сильнее.

    Раз кнопка не появилась, значит ваша репутация рассыльщика недостаточно хороша или вообще отсутствует. Соблюдайте требования почтовых сервисов и кнопка появится рано или поздно.
    Ответ написан
    Комментировать
  • Как организовать monorepo с привязкой к версии maven?

    Vamp
    @Vamp
    Вы можете собрать весь проект целиком, тогда в maven reactor будут добавлены сразу все модули и dependency resolver сможет разобраться в зависимостях от соседних модулей. Но если собирать один конкретный модуль, то мавен уже не разберётся и полезет во внешние репозитории. В таком случае необходимо передать дополнительный ключ -am (--also-make):

    mvn -am -pl модуль package
    Ответ написан
    Комментировать
  • Как данные перемещаются в сети интернет, всегда конвертируются в кадры Ethernet или остаются в пакетах IP?

    Vamp
    @Vamp
    1. Пакеты не конвертируются друг в друга, а вкладываются. То есть в типичном пакете имеются сразу три заголовка - Ethernet, IP и TCP. И когда маршрутизатор решает куда отправить пакет дальше, смотрит только на заголовок IP. У маршрутизатора существует таблица маршрутизации, которая указывает какие IP адреса на какой интерфейс отправлять. Непосредственно перед отправкой маршрутизатор перезапишет ethernet заголовок и вставит в него свой MAC в поле "source MAC address", а MAC выбранного следующего получателя в поле "destination mac address".

    Но в таком случае ведь все-равно в ethernet нельзя закольцовывать пути, а маршрутизаторы по-любому где-нибудь закольцованы.
    Верно. Но обычно кольца не являются проблемой, так как легко разруливаются при помощи протокола STP. Иногда кольца делают даже специально для автоматического фэиловера.

    2. Упаковка в Ethernet может быть пропущена только если источник пакета по каким-то своим внутренним соображениям решает не отправлять его. Например, если сработало запрещающее правило фаервола. Очевидно, что такой пакет не покинет своего места рождения. И, кстати, Ethernet - это ещё не физический уровень.

    3. Ethernet используется в локальных сетях. И топология LAN на это не влияет - с маршрутизатором или без него.

    4. Если есть чисто локалка на свиче, то сетевой уровень по-любому используется?
    Да, сетевой уровень используется и здесь.

    Допустим с датаграммы udp упаковка в ip пакет, затем только в кадр ethernet?
    Да, UDP заворачивается сначала в IP, а затем в Ethernet.

    И по-любому отрабатывают dhcp и arp?
    DHCP не является обязательным для применения (он, кстати, работает поверх UDP). ARP тоже может не использоваться, если в этой сети не используется IP адресация (а вот ARP уже самостоятельный протокол канального уровня, который упаковывается только в Ethernet).

    5. Во времена до изобретения Ethernet использовались другие протоколы. Соответственно, и оборудование было другое, поддерживающее данные протоколы.
    Ответ написан
    3 комментария
  • Почему поток не останавливается?

    Vamp
    @Vamp
    Тут есть две проблемы.

    Первая очевидная проблема в том, что main поток на первой же итерации впадает в сон на методе wait(), а в программе больше нет потоков, которые могли бы вызвать notify() и разбудить main. Поэтому main бесконечно ждёт и не может остановить liche и sude.

    Вторая совсем неочевидная в том, что синхронизация некорректно используется. У вас синхронизируется только запись в переменную isRun. Чтение этой переменной так же должно быть синхронизировано. Иначе это приведет к странным неуловимым багам.
    Ответ написан
    2 комментария
  • Как запустить майнкрафт через коммандную строку?

    Vamp
    @Vamp
    Для 1.17.1 нужна java версии 17. Судя по ошибкам у вас 8 версия.
    Ответ написан
    Комментировать
  • DNAT. Где ошибка?

    Vamp
    @Vamp
    Нужно ещё указать таблицу nat

    iptables -t nat -A PREROUTING -d 4.4.4.100 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 192.168.100.100:22
    Ответ написан
    Комментировать
  • Методы или инструменты на python для построения маршрута на схематичной карте в игре?

    Vamp
    @Vamp
    Вам необходимо разбить карту на тайлы и воспользоваться одним из алгоритмов поиска пути.

    Например, A*. Это популярный алгоритм с большим количеством примеров по всему интернету. Наверняка найдется и готовая библиотека с его реализацией.
    Ответ написан
    1 комментарий
  • Как на PHP при OAuth-авторизации в Яндекс.Почте работать по протоколам IMAP и SMTP, используя не пароль, а OAuth-токен?

    Vamp
    @Vamp
    Стандартный модуль php_imap не поддерживает XOAUTH2. И, вероятно, никогда не будет поддерживать. Существует план поддержки XOAUTH2, но работа по нему не ведётся.

    Вам следует воспользоваться альтернативными реализациями IMAP протокола, поддерживающие XOAUTH2. Например, webklex/php-imap.

    С SMTP так же - берите любую библиотеку с поддержкой XOAUTH2.
    Ответ написан
    Комментировать