• Как асинхронная программа(event loop) понимает, что пришел ответ от сервера?

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

    Итак, мы пишем на нашем высокоуровневом любимом языке, неважно JS/Rust/C#/Scala/Python или любой другой. В современном мире у нас скорее всего есть какая либо абстракция для работы с асинхронными апи, предоставляемая или стандартной библиотекой языка или сторонними библиотеками. Она может быть примитивной и основанной на колбэках или более продвинутой, вроде Future/Promise/Task или чем-то подобным. Иногда наш язык предоставляет синтаксис наподобие async/await для более простой работы с этими абстракциями, а иногда асинхронная работа может вообще быть скрыта от нас в рантайме языка, например как с горутинами в Go. Но в любом случае где-то под капотом у нас будет event-loop, а иногда и не один, так как никто не запрещает нам писать многопоточку в то же время используя асинхронные вызовы.

    Сам event-loop - это не более чем обычный while(true) или любой другой бесконечный цикл. И внутри этого цикла наша программа имеет доступ на извлечение к некоторой очереди (если не знаете, что это за структура данных, то погуглите), которая содержит в себе результаты уже обработанных задач. Программа берет очередной результат, находит ожидающий ее колбэк/Promise/Future/Task и запускает выполнение ожидающего кода. Очередей опять же может быть несколько и обрабатываться они могут по разному, но это не важно. Важно то, что наш основной поток (или потоки) ничего не знают, о том как выполняются асинхронные задачи. Он лишь смотрит, есть ли в очереди результат, и если есть - обрабатывает его, а если нет, то принимает решение или выйти из цикла (и завершить поток, а иногда и весь процесс) или уснуть пока новых результатов не появится.

    Но откуда же в очереди берутся результаты? Надо понимать, что асинхронная программа почти всегда многопоточная и результат операций попадает в очередь из фоновых потоков, которые просто блокируются в ожидании нужного ресурса (или сразу многих ресурсов, если используют системные апи вроде epoll или kqueue). Как правило такие фоновые потоки большую часть времени находятся в состоянии ожидания, а значит не потребляют ресурсы CPU и не попадают в планировщик ОС. Такая простая модель действительно позволяет сильно экономить ресурсы по сравнению с моделью, где множество потоков выполняют по 1 задаче и самостоятельно ожидают свои запросы.

    Важно отметить, что в современном мире даже на среднеуровневых языках, вроде C или C++, не говоря уже о высокоуровневых, не реализуют асинхронность сами. Во-первых, на разных ОС для этого используются разные апи. Во-вторых, эти апи на разных ОС умеют обрабатывать разные типы ресурсов (с сетью вроде как умеют работать все основные ОС, но помимо сети асинхронно можно работать с пользовательским вводом, диском и периферийными устройствами, вроде сканеров, вебкамер и прочего цепляемого в usb). Наибольшую популярность (ИМХО) имеет кроссплатформенная библиотека libuv, хотя в Rust принято использовать mio (или даже абстракции над ней, вроде tokio), в C# подобные механизмы есть в .NET Core, а в Go оно уже зашито
    в те самые 1.5МБ рантайма, что Go засовывает в каждый бинарь
    (там правда еще и GC, но один фик это много и достойно вынесения в динамическую либу)


    Ок. С прикладным кодом вроде разобрались. А что же происходит в ядре ОС? Ведь, как писалось выше, у нас даже есть апи, чтоб ждать запросы пачкой. Все просто. Ядра ОС стали асинхронными еще до того, как это стало мейнстримом, если мы конечно имеем дело не с ОС реального времени (но у нас же винда/линь/мак/фряха, а не ОС для бортового компа боинга, где это критично). Смотрите, когда что-то происходит на внешней периферии (ну например диск запрошенные данные прочитал или по сети данные пришли, или юзер мышкой дернул), то формируется прерывание. CPU реально прерывает свою текущую работу и бежит смотреть что случилось, точнее вызывает обработчик предоставленный ОС. Но у ОС то есть основная работа, поэтому она скорее старается освободить обработчик и просто скидывает все данные в оперативку, а разбираться будет потом, когда очередь дойдет. Ничего не напоминает? Очень похоже, на то что происходило в event-loop, только вместо фоновых потоков "результаты" попадают в очередь из прерываний. А уже когда-то потом ОС отдаст данные в драйвер устройства, ну и т.д., пока они не дойдут до нашего прикладного приложения. Вот и все, никакой магии.
    Ответ написан
    3 комментария
  • Как из commita сделать ветку git?

    ruddy22
    @ruddy22
    Спасение утопающих — дело рук самих утопающих
    Встань на коммит, затем git checkout -b
    Ответ написан
    Комментировать
  • Как из commita сделать ветку git?

    Lynn
    @Lynn
    nginx, js, css
    Все чёрные метки на вашем скриншоте это уже ветки.

    Так что у вас уже есть ветка m5. Просто в ней пока нет ни одного собственного коммита, поэтому она не выделена в отдельную ступеньку.

    Так что
    git switch m5
    # редактируем
    git commit
    git push

    и будет у ветки m5 своя ступенька.
    Ответ написан
    Комментировать
  • Как добавить второй домен на сайт, что бы два домена ссылались на один сайт?

    Технически можно сделать множеством способов
    1. вы просто через порбел добавляете сервер нейм
    2 или через сервер алиас, то же самое в nignx (там директивы по другому называются но так же через пробел)
    ну если у вас веб панель то там как правило есть место где можно их вводить, так же через пробел.
    <VirtualHost *:82>
                   DocumentRoot /var/www/clients/client132/web171/web
                    ServerName 3dpaneli.ru site.ru site2.ru 
                    ServerAlias www.3dpaneli.ru site5.ru
                    ServerAdmin webmaster@3dpaneli.ru
                    ErrorLog /var/log/ispconfig/httpd/3dpaneli.ru/error.log

    3. Создать 2 отдельных сайта с двумя разными доменами ведущими в 1 папку.
    4. это третий вариант но вместо одной папки у сайта разные папки, одна из которых является симлинкой смотри ман по баш ln -s
    5. два сайта у ведомого сайта nginx проксирует на первый через proxy_pass
    6. mod_proxy - аналог 5 для апача.
    7. На сервере всего один сайт и он лежит в папке без явно указанного домена например listen 80 default_server; ( такая конфигурация у чисто установленного апача или nginx) в таком случае любой домен сославшийся на этот айпи будет открывать один и тот же сайт.
    Реально же вам должно хватить первых двух
    Ответ написан
    5 комментариев