Подробности реализации сервиса восстановления разговоров и особенности работы
1. Мониторинг сиповых нод
1.1. Мониторит все сиповые ноды (обслуживающие SIP-сигнализацию).
1.2. Микросервис RPCI дополнительно регулярно пингует ноды раз в 5 секунд и информирует остальных об обнаружении потери.
1.3. Если сервис отловил или RPCI его ноде сообщил, что пинг с сиповой нодой пропал - фиксирует потерю и засекает таймер на секунду.
1.4. Ждет в течение секунды какие сиповые ноды еще пропадут.
1.5. Отдает накопленное в виде события nodedown сервису восстановления.
2. Слежение за диалогами
2.1. Сервис обрабатывает события callevents: dlg_start, dlg_end, dlg_dead, dlg_down и dlg_binding.
2.2. Получая dlg_start, сервис усекает данные и сохраняет в своем распределенном хранилище (мнезия). Засекает резеврный таймер на два часа предельной длительности разговора, по истечении которого удаляет данные о диалоге из хранилища.
2.3. Событие dlg_start среди прочего содержит a_hops, b_hops - адреса и порты участвующих в обслуживании SIP-сигнализации плечей промежуточных узлов от b2b до юзер-агента, а также tags, URIs, contacts, usernames, domains - что необходимо для восстановления диалога.
2.4. Получая dlg_end, сервис удаляет данные о диалоге из хранилища.
2.5. Получая dlg_dead или dlg_down, сервис перезасекает таймер на 5 секунд, чтоб не остаться с данными лишними. По истечении таймера вычищает данные из хранилища.
2.6. Получая dlg_binding, сервис актуализирует сохраненную информацию в контексте, необходимом для восстановления сеансов (CCS и КЦ, требуется для восстановления очередей).
2.7. Если нода сервиса восстановления перезапускается или запускается резервный экземпляр, то вычитывает из хранилища все диалоги и удаляет просроченные, по актуальным засекает таймеры на оставшееся время.
2.8. Как только поступает событие nodedown о потере сиповых нод, сервис ищет среди всех актуальных диалогов из своего хранилища те, что зацепило (пересечение c hops).
2.9. Под каждый из зацепленных диалогов запускает асинхронный процесс восстановления, передавая ему контекст - информацию о диалоге и список зацепленных нод. Сохраняет идентификатор процесса восстановления в записи, а саму запись оставляет в хранилище, она удаляется стандартным путем при обработке событий callevents.
3. Подготовка к восстановлению
3.1. Если среди хопов есть промт (прослушка, суфлер), то задание отменяется. Восстановление подключений к разговорам не производится.
3.2. Если ранее диалог уже отправлялся на восстановление, то новый процесс восстановления синхронизируется с предыдущим обработчиком. Если он жив, то пытается его остановить (abort), после чего ожидает в течение 5 минут (запредельный навсякийслучай). В конце своей работы, а также перед непосредственным началом обработки, предыдущий процесс проверяет в очереди сообщений команду abort. Когда находит, выдает в ответ свой стартовый контекст и завершается.
3.3. Новый процесс, инициировавший синхронизацию, получая ответ от предыдущего обработчика, действует в зависимости от ответа (отменен, успешно восстановлен, прервался по ошибке). Либо продолжает с объединением своего и предыдущего контекстов (объединяет списки зацепленных узлов, так как второе задание могло содержать дополнительные ноды, потеря которых ранее не была обнаружена).
3.4. Если предыдущего обработчика нет или он завершен, то востановление запускается с собственным стартовым контекстом.
3.5. Перед началом восстановления ожидает появления путей для вызова обоих абонентов. Регулярно проверяет в течение минуты: нужно наличие регистрации через живой доступный SG, наличие коннекта с провайдером, наличие нод и активных микросервисов всех необходимых типов - конференций, айвиаров, b2b, sg, esg - всё в соответствии с контекстом восстанавливаемого диалога.
3.6. Как только наличие пути подтверждено, обработчик проверяет, не отменяют ли его более новым заданием. Если команда на обрыв уже есть в очереди, он прерывается и отдает в ответ свой стартовый контекст.
3.7. В обычном режиме обработчик определяет режим восстановления диалога и запускает его.
4. Восстановление
4.1. Всего поддерживается 7 разных видов процедур восстановления.
4.2. В любом случае новый диалог будет от А к Б (в соответствии с восстанавливаемым диалогом).
4.3. Самый тривиальный - одношаговый реплейс с рефером реплейсовым - на случай если потерян только узел b2b.
4.4. Самый сложный - параллельный интеркомный вызов обоих абонентов от сценария IVR с тишиной, и последующий двойной реплейс коллменеджером - на случай если потеряны полностью все узлы. Этот режим есть, но он фактически не используется.
4.5. Средний режим - вызов интеркомный абонента Б, затем вызов реплейсовый абонента А и рефер реплейсовый для А на подмену нового плеча Б.
4.6. Все 7 режимов следующие в порядке усложнения:
4.6.1. одношаговый реплейс в плечо А с рефером реплейсовым на плечо Б,
4.6.2. одношаговый интерком на номер А с рефером реплейсовым на плечо Б,
4.6.3. двухшаговый реплейс: первый реплейс в плечо Б от ivr с тишиной, второй реплейс в плечо А с рефером реплейсовым на новое плечо Б.
4.6.4. двухшаговый с интеркомом: первый интерком на номер Б от ivr-пустышки, второй реплейс в плечо А с рефером реплейсовым на новое плечо Б.
4.6.5. двухшаговый двойной интерком: первый интерком на номер Б от ivr-пустышки, второй интерком на номер А с рефером реплейсовым на новое плечо Б.
4.6.6. поочередный вызов А и Б с последующим коллменеджеровским двойным реплейсом новых плеч. Изначально интерком или реплейс - зависит от того, есть в плече потерянные хопы или нет.
4.6.7. параллельный вызов А и Б с последующим коллменеджеровским двойным реплейсом. Изначальный интерком или реплейс - зависит от того, есть в плече потерянные хопы или нет.
4.7. Всегда сначала делается вызов в плечо, где есть потерянные хопы.
4.8. Всегда сначала делается попытка реплейсом забрать вызов, если операция завершается неудачей, то выбирается другая более сложная операция из 4.6 с интеркомом (опциональный режим, по умолчанию выключен).
4.9. Рефер всегда реплейсовый, производится на плечо, про которое достоверно известно, что оно не потеряно. Оно либо уже восстановлено ivr-пустышкой, либо изначально в нем не терялись хопы (кроме, возможно, центрального b2b).
4.10. Если вызов второго плеча неудачен, то первое восстановленное плечо завершается (коллменеджером bye из b2b в плечо). Завершаемый вызов имеет живую сигнализацию, поскольку он создан в новых условиях уже после начала восстановления.
4.11. Когда новый диалог успешно создан, инициируется завершение предыдущего диалога на b2b, а также плечей на юзерагенте А, и юзерагенте Б. Это значимо для сервера, если b2b остался жив, но плечи оба отвалились, и это значимо для телефонов, когда плечи отвалились, и b2b не может уже отменить предыдущий вызов, чтобы телефон сбросил предыдущий висящий диалог. Для этого непосредственно отправляется BYE (пока только с sg в сторону телефона/софтфона).
4.12. Из хранилища диалог удаляется либо по завершении на b2b, либо отложенно по событию dlg_down.
4.13. В логе можно обнаружить много ответов 481 ответы на BYE и на re-INVITE, отправляемые телефоном.
5. Эффекты
5.1. Обмен медиа-трафиком производится до тех пор, пока ни один из телефонов не переключился на новый диалог. Все время, пока ожидается появление путей вызова, обмен трафиком производится. Основное условие - остался жив медиашлюз, обслуживающий диалог.
5.2. Если b2b выжил, а только sg перезагрузился, то разговор не обязательно восстанавливать, но тем не менее он все равно пересоздается (поскольку не различаются случаи использования пограничного медиа-шлюза, подключения устройств через резервные экземпляры sg и некоторые другие).
5.3. При восстановлении такого разговора в некоторых случаях кратковременно может быть слышна мелодия ожидания, поскольку телефон при интеркомном вызове переключается в холд. Но вероятность этого низкая, поскольку сначала делается реплейс, и он в подавляющем количестве случаев успешен.
5.4. Если в сигнализации что-то будет происходить, пока ожидается появление пути и начало восстановления, то диалог разрушится, и тогда его ожидающий процесс может восстановить интеркомами, если такой режим активирован.
5.5. Если трубку положили во время ожидания появления пути - абонентов снова свяжет система интеркомами, поскольку задание уже в обработке. Это также требует включения режима вызова с интеркомами.
5.6. Активация задания происходит не раньше чем через секунду, но вообще может быть через установленное в конфиге время pang_to_disconnect + 2-3 секунды - случай обрыва связи между серверами и последующего длительного ожидания восстановления или завершения TCP соединения.
5.7. Если упал b2b, и он есть в альтернативных экземплярах, то восстановление начинается через 1-2 секунды.
5.8. Если упал sg и не поднимается, но есть альтернативные экземпляры (случай, когда телефон настроен на несколько outbound proxy, и не используется Virtual IP), то сначала секунд 15 отсчитывается время перед отправкой команды на перерегистрацию (NOTIFY event=reload-account), а в особых случаях команда может отправиться в течение минуты (например переезжали одновременно БД и mdc). Затем когда телефон пререгистрируется, через 1-2 секунды начинается восстановление. Телефон должен поддерживать этот тип эвента и обрабатывать его при поступлении в том числе с других серверов (без фильтра). Случай использования Virtual IP отрабатывается стандартным образом через 1-2 секунды после обнаружения потери.
5.9. Если упал sg и переподнялся, то восстановление начинается через 1-2 секунды после его загрузки.
5.10. Попытка восстановления каждого диалога однократная - реакция на каждое агрегированное событие о потере сиповых нод, имеющих зацепление с обслуживающими диалог узлами.
5.11. Кроссайтовые ноды не отслеживаются. Если одно плечо уходит на другой сайт, то для восстановления нужно потерять именно узел на сайте, где трудится b2b.
5.12. Никакие ghost-вызовы не восстанавливаются. К ним относятся инициированные коллменеджером служебные операции.
5.13. Никакие неустановившиеся вызовы не восстанавливаются. То есть не получившие финального ответа.
5.14. Если вызов на удержании, то, восстанавливаясь реплейсом, он сохраняет режим удержания средствами телефона. А восстанавливаясь интеркомом - не сохраняет, поскольку это новый диалог.
5.15. Чтобы восстановление через интерком работало без необходимости абоненту взаимодействовать с устройством, нужно в телефоне задать приоритет интеркома.
5.16. Настраивается callstore.sip_restore_enabled (по умолчанию false), sg.reregister (по умолчанию false) - последний полезен лишь в случае, если используется режим настройки нескольких outbound proxy.
5.17. Вебртс софтфон не рвет разговор при потере sg, а, сохраняя разговор и медиа, начинает попытку переподключиться на тот же или альтернативный адрес. Как только регистрация восстанавливается, возникает новый диалог, подменяющий предыдущий. Если медиашлюз оставался активен, то потеря звука в пределах полусекунды.
5.18. При восстановлении производится привязка к тому же идентификатору сеанса, который был у потерянного разговора. Это дает возможность восстановить контекст обслуживания в коллцентре.
5.19. Активация сервиса восстановления для односерверной системы имеет не много смысла, поскольку защищает лишь от риска перезагрузки нод или системы целиком. Первое возможно либо вручную, либо при нехватке ОЗУ, либо при критических ошибках в системе - всё маловероятно. Второе требует слишком длительного (2-3 минуты) ожидания абонентами загрузки системы до состояния готовности, чтобы ожидать что они не положат трубки в ожидании. Таким образом для односерверной системы функционал имеет скорее демонстрационный и тестовый смысл.
5.20. В журнале разговоров восстановленный разговор будет представлять собой отдельную запись. По каждой из записей будет сформирована запись разговора (при условии, что сервер с медиашлюзом предыдущего разговора доступен).
6. Внешние абоненты
6.1. Если esg не упал, то восстановление происходит путем вызова с подменой, который обрабатывается выжившим esg как обычно.
6.2. В учетной записи провайдера настраивается режим восстановления (opts.sip_restore_mode). Применяется только если упал экземпляр esg. По умолчанию replace. есть еще regular и disabled.
6.3. Для восстановления плеча, где esg упал, сервис дожидается успешной регистрации/пробивки. То есть esg должен сообщить о том что коннект доступен.
6.4. В режиме replace внешние вызовы восстанавливаются путем отправки аплинку информации о подмененном плече. Эти заголовки проходят насквозь через новую реинкарнацию esg, хотя этот esg формирует полноценный новый вызов. Ожидается что аплинк способен обрабатывать реплейсы (инвайты с заголовком реплейса).
6.5. В режиме regular делается новый вызов без передачи информации о подмене плеча.
6.6. В режиме disabled происходит отмена процедуры восстановления.
6.7. Интерком к аплинкам не применяется.
7. Конференции
7.1. При потере части b2b, через которые идет обслуживание звонков в конференции, на общих основаниях производится инициация подменного вызова. Абонент вызывает конференцию подменой. Для конференции это обычная подмена, а для абонента это обычный случай восстановления.
7.2. Если упал микросервис активной конференции, то все абоненты вызывают конференцию заново, и фактически создают новую с тем же номером. Для всех абонентов почти незаметно.
8. IVR
8.1. При потере b2b - на общих основаниях производится инициация подменного вызова. Абонент вызывает живой ivr подменой. Для IVR это обычная подмена, как будто абонент перевел на него другого абонента. А для абонента это обычный кейс восстановления. Обслуживание в IVR не приостанавливалось.
8.2. Если свалился микросервис активного IVR - абонент вызывает IVR заново по изначальному номеру. Фактически создается новый обработчик сценария с самого начала от фичакода. Поэтому важно при серьезных переключениях осуществлять перевод на другой номер фичакода - тогда восстановление будет происходить с начала сценария по последнему набранному фичакоду. Если сценарий использует вложенные сценарии - начинается с начала первого сценария - того фичакода, на который был совершен последний вызов.
8.3. Сценарий умеет сохранять свое полное состояние, включая информацию о стеке вложенных сценариев, в хранилище (микросервис с ролью store, который multi-active-passive - в произвольном количестве групп по хешрингу одновременно).
8.4. Восстановление плеча сценария IVR происходит с передачей информации о факте восстановления. И новый сценарий может обнаружить в хранилище состояние и полностью его загрузить.
8.5. Выполнение начинается с отправки последнего ответа и дальше с начала последнего сохраненного компонента.
8.6. В данный момент сохранением состояния занимается компонент ПАУЗА с включенной опцией соответствующей. По умолчанию выключена.
8.7. Как сохранение состояния будет тормозить систему - предстоит устанавливать. Если не жестить - вроде бы и не сильно. Но если после каждого компонента добавлять сохраняющую паузу, то очевидно на порядок возрастет и нагрузка, и время исполнения, если сценарий занимается алгоритмической работой без пауз. И, конечно, в сценарии есть связанные блоки, которые не имеет смысла разделять. Работа по подготовке сценария к восстановлению - творческая и ответственная.
8.8. IVR восстанавливается только пока жив медиа-сеанс. Пост-ветка не сохраняется, до ответа 200 OK также сохарнять бессмысленно, потому что не установившийся диалог не восстанавливается сервисом.
9. Перспективы развития
9.1. Процесс восстановления способен породить интенсивный трафик и CPS. Запуск заданий следует распределять во времени и управлять приорететами различных диалогов на основании их типов и возможно других признаков. Так, например, с одной стороны, восстановление IVR может быть более приоритетным в разрезе обслуживания в колл-центре, чем внутренние вызовы. А с другой стороны менее приоритетным за счет того, что фактически обслуживание в IVR это лишь ожидание - при сохранении медиашлюза и воспроизведениях длинных отрезков или мелодии ожидания, скорость восстановления некритична. Таких примеров и случаев представляется довольно много.
9.2. Сохранять в контексте диалога информацию о типе использования пограничного шлюза (sg, bgmg, IP-адрес), чтобы исключать восстановление разговора целиком при условии, что SIP-запросы через новую реинкарнацию шлюза продолжат ходить и обмен медиа-трафиком не прекратится.
9.3. Вызов, ожидающий в очереди коллцентра, должен восстанавливать свою позицию на основании идентификатора сеанса, замещая там свою предыдущую запись.
9.4. В отчетах коллцентра восстановленные разговоры могут дублировать записи по разговорам, и могут искажать часть статистики.
9.5. Полезна будет настройка отсечки по времени, исключающая запуск задания на восстановление после чрезмерно долгого интервала - например, долго не было доступного пути, или после перезагрузки или обновления системы.