Перейти до

Abram

Сitizens
  • Всього повідомлень

    729
  • Приєднався

  • Останній візит

  • Дней в лидерах

    6

Сообщения додав Abram

  1. Это точно. С нетворкменеджером вы не поспорите. Либо им. Либо выключать его нафиг и делать ручками.

    Раньше его недолюбливал, но последние годы активно пользуюсь на десктопе. Действительно удобно.

    Умеет всё - даже Интертелекомовские CDMA-модемы сам запускает, нужно только выбрать "Украина" и "Intertelecom".

  2. Просто уберите кабель и повесьте сбоку муфту.

     

    С одной стороны - вы не имели права вешать там кабель.

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

     

    Но если он пойдёт на принцип и заставит вас перенести кабель в судебном порядке - вам это обойдется на порядок дороже, чем просто взять и перетащить.

  3. Ну я ж и грю - как минимум переписывать mysqlclient библиотеку...

    Существует асинхронный клиент. И есть обертки - например, twisted предлагает выносить mysql в отдельный поток (собственно, и выносит), где будет всё говно, а в основном потоке будет асинхронный код, который будет работать с асинхронным интерфейсом (оберткой) MySQL. Хрень, конечно, но всё равно получается на порядок шустрее, чем синхронный код.
  4.  

    SQL для апликухи - это самый что ни на есть i/o, который можно не ждать, а заняться в это время своими делами (обслуживать другой запрос, например).

    Покажи мне асинхронный MySQL запрос :) Я что-то не припомню таковой реализации в мускуле, как и в других СУБД.

     

    Запрос сам по себе синхронный, но это не должно никого волновать :).

    Грубо говоря, соединение с MySQL - это сокет. В сокет можно написать что-то и благополучно на него забить болт до того времени, пока что-то оттуда не придёт.

    В асинхронном программировании логика такова: отправил в MySQL запрос, пнул реактор (слышь ты, вот есть fd/socket, придёт чего-то вызовещь вот эту ф-цию) и всё - функция завершилась, возвращаемся в реактор. Дальше реактор запускает следующую функцию (или не запускает, если ничего не пришло ни в один fd и не сработал alarm; в таком случае реактор висит в select/epoll/итд, пока ничего не придёт). Главное здесь - не ожидать окончания каких-либо операций (будь то запрос в БД, дисковое IO, сетевое взаимодействие), а быстренько пнуть и вернуться в реактор. Реактор сам вызовет твои функции по цепочке callback-ов, когда им РЕАЛЬНО нужно будет работать и не ждать.

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

     

    Примеры удачных реализаций: twisted в Python, POE в Perl, Qt, nginx, node.js.

  5. SQL для апликухи - это самый что ни на есть i/o, который можно не ждать, а заняться в это время своими делами (обслуживать другой запрос, например).

    Да, именно это же делает ОС, если использовать потоки/процесы, но практика показала, что накладные расходы на это настолько высоки, что часто один асинхронный процес может обслужить больше клиентов, чем несколько синхронных.

     

    Вообще асинхронное программирование лично мне напоминает жонглирование: бросил мяч и забыл о нем до тех пор, пока он не прилетит к тебе назад. В это время можно сделать много чего ещё полезного (бросить/поймать другие мячи).

  6. Поднять пиринг с соседом, originate default, фильтр в сторону соседа: отправлять только дефолт, принимать только его подсети.

    Фильтры отправляемы в сторону аплинков маршрутов (они ведь есть? ;)): добавить сети соседа.

  7. С какой это радости - не должно быть? :) Т.е. однопоточная обработка запросов в порядке очереди - это хорошая, годная практика?

    Обычно есть поток-менеджер, и потоки-воркеры, на которые менеджер раскидывает задания...

    Если сервис асинхронный - то это очень годная тактика.

    FreeRADIUS НЕ асинхронный и никогда им не был.

  8.  

    Мне кажется, можно обойтись каким-нибудь атомарным select for update. Или быстренько заблокировать, select-нуть, update - обозначить, что этот адрес используется, и unlock.

    Кстати, насчет моей таблицы с используемыми IP: благодаря ей у меня получилось обойтись без вот такой конструкции (перебор занятых IP адресов):

    for (my $i = 0 ; $i <= $#pools_arr ; $i++) {
        %pool = %{ $pools_arr[$i] };
        foreach my $ip (@$list) {
          if (exists($pool{ $ip->[0] })) {
            delete($pool{ $ip->[0] });
            $self->{USED_IPS}++;
          }
        }
        last if (scalar(keys %pool) > 0);
      }
    
      my @ips_arr = keys %pool;
      my $assign_ip = ($#ips_arr > -1) ? $ips_arr[ rand($#ips_arr + 1) ] : undef;
    Вместо этого у меня так:

    SELECT
      *
    FROM
      (SELECT
         `u`.`ip`
       FROM `ipUsage` `u` JOIN `ippools` `p` ON `p`.`id` = `u`.`poolid`
         LEFT JOIN `dv_calls` `c` ON `c`.`framed_ip_address` = `u`.`ip`
         LEFT JOIN `dv_main` `dv` ON `u`.`ip` = `dv`.`ip`
       WHERE `c`.`acct_session_id` IS NULL AND `dv`.`ip` IS NULL AND `u`.`poolid` = %s AND
             `u`.`lastBlock` <= %s
       ORDER BY `p`.`priority` ASC
       LIMIT 50) data
    ORDER BY RAND();
    Фактически свободный IP находится за один запрос.

    Да, я знаю, что ORDER BY RAND() - это плохо, но там сначала ограничивается 50 записями.

     

     

    тут немного другой принцип заносятся все адреса по одной записи в таблицу

     

    а что делает этот блок ?

    `u`.`lastBlock` <= %s

     

    Вот именно от этого принципа я у себя и отказался.

    lastBlock - последнее время блокировки адреса. В %s там подставляется текущий unixtimestamp минус 60 секунд вроде бы.

     

    Суть такова: при авторизации делается UPDATE ... SET lastBlock = %s (%s = timestamp), т.е. пометка, что этот ещё 60 секунд использовать нельзя. Если за 60 секунд (это я взял с запасом) сессия не появится в dv_calls - адрес уже считается свободным. Если интересно - вот полностью ф-ция: http://pastie.org/private/ir1mpbpigh1ox53f5lgw . Код на Python, там реализован только нужный мне кусочек логики, да и лока таблиц нет (надо доделать), но суть понятна.

  9.  

    я думаю это всё просто предположения пока нет ни одного факта что будет плохо

    Вообщем-то локи в целом плохо, лучше когда без них, но без них навряд получится нормально...

     

    Мне кажется, можно обойтись каким-нибудь атомарным select for update. Или быстренько заблокировать, select-нуть, update - обозначить, что этот адрес используется, и unlock.

    Кстати, насчет моей таблицы с используемыми IP: благодаря ей у меня получилось обойтись без вот такой конструкции (перебор занятых IP адресов):

    for (my $i = 0 ; $i <= $#pools_arr ; $i++) {
        %pool = %{ $pools_arr[$i] };
        foreach my $ip (@$list) {
          if (exists($pool{ $ip->[0] })) {
            delete($pool{ $ip->[0] });
            $self->{USED_IPS}++;
          }
        }
        last if (scalar(keys %pool) > 0);
      }
    
      my @ips_arr = keys %pool;
      my $assign_ip = ($#ips_arr > -1) ? $ips_arr[ rand($#ips_arr + 1) ] : undef;
    Вместо этого у меня так:

    SELECT
      *
    FROM
      (SELECT
         `u`.`ip`
       FROM `ipUsage` `u` JOIN `ippools` `p` ON `p`.`id` = `u`.`poolid`
         LEFT JOIN `dv_calls` `c` ON `c`.`framed_ip_address` = `u`.`ip`
         LEFT JOIN `dv_main` `dv` ON `u`.`ip` = `dv`.`ip`
       WHERE `c`.`acct_session_id` IS NULL AND `dv`.`ip` IS NULL AND `u`.`poolid` = %s AND
             `u`.`lastBlock` <= %s
       ORDER BY `p`.`priority` ASC
       LIMIT 50) data
    ORDER BY RAND();
    Фактически свободный IP находится за один запрос.

    Да, я знаю, что ORDER BY RAND() - это плохо, но там сначала ограничивается 50 записями.

  10.  

    У я себя решил так: есть с IP-адресами, где записывается время последней выдачи адреса. Адрес считается свободным, если его нет в dv_calls и последняя выдача была больше n секунд назад. Таблица полностью сразу заполняется адресами и update-ится только время выдачи.

    А теперь ситуация - клиент начинает долбить авторизацию в 100500 потоков, но не согласовывается с сервером и режектится. В случае с записями таблице сессий - в худшем варианте займется N адресов по кол-ву брасов (при реконнекте на брас клиента с тем же CID/логином ему выдается старый ип), в твоем случае - засирается временный пул адресов.

     

    Коллизии возможны, но крайне маловероятны.

    А чтобы их не было - и используется лок.

     

    Алгоритм по сути тот же, разница - в том, куда и как пишется. Кстати, надо будет и у себя лок прикрутить - атомарность это правильно, тогда коллизий не сможет быть в принципе.

    Не проблема, записывай вместе с блокировкой IP сразу и UID, кем он заблокирован. При повторной попытке авторизации если за пользователем (или наверное правильнее за UID+CID) есть уже заблокированный, но не используемый IP - выдавай его же повторно.

    Занесения адресса при аккаунтенге плохой пример, может работать у маленьких провайдеров до 1000-2000 абонентов. У провайдеров с 10 тис онлайн за время между авторизацией и аккаунтингом может пролезть десяток абонентов с уже занятыми адреса.

    Чукча не читатель, чукча писатель. Вы читали выше о блокировке адресов на определённое время после авторизации?
  11.  

    IP ищется при авторизации, а вносится при первом аккаунтинге.

    Ну сессия создается при авторизации, занимая ип. Если аккаунтинг не пришел - сессия умирает. Если я ничего не попутал в алгоритме (давно ковырял код).

     

    А должна создаваться при первом Accounting.

    Когда-то с этим была проблема; был даже от тебя патч.

    У я себя решил так: есть с IP-адресами, где записывается время последней выдачи адреса. Адрес считается свободным, если его нет в dv_calls и последняя выдача была больше n секунд назад.

    Таблица полностью сразу заполняется адресами и update-ится только время выдачи.

    Из всех рассмотренных вариантов этот оказался самым быстрым. Коллизии возможны, но крайне маловероятны.

  12. То не фикс. А обеспечение атомарности операции выдачи адреса из пула (для чего - блокируется доступ к таблице на время поиска ип и внесения его в таблицу сессий). Ну чтобы не выдавался один и тот же адрес клиентам, выполняющим одновременно авторизацию...

    IP ищется при авторизации, а вносится при первом аккаунтинге. Возможен вариант, когда авторизация придёт, а аккаунтинг - нет (NAS по каким-либо причинам не поднял сессию - например, в случае PPP не согласовал с клиентом шифрование, в случае DHCP - клиент не откликнулся на OFFER).
×
×
  • Створити нове...