Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

Graceful shutdown #29

Closed
alexlapa opened this issue Jun 17, 2019 · 3 comments · Fixed by #30 or #37
Closed

Graceful shutdown #29

alexlapa opened this issue Jun 17, 2019 · 3 comments · Fixed by #30 or #37
Assignees
Labels
feature New feature or request k::deploy Related to deployment capabilities
Milestone

Comments

@alexlapa
Copy link
Collaborator

alexlapa commented Jun 17, 2019

Part of 0.2.0 Roadmap (#8)

PR: #30, #37

Background

В данный момент, в случае завершения приложения все ws клиенты получат close code 1006 (отсутствие close frame). Так как этот код также может быть получен в случае "обрыва" соединения, он будет вести к попыткам реконнекта со стороны клиента.

Problem to solve

Требуется разработать мехнизм graceful shutdown в случае получения сигналов завершающих приложение: SIGHUP, SIGINT, SIGTERM, SIGQUIT. В рамках которого все ws-клиенты будут закрываться со статусом 1000.

Possible solutions

Для подписки на сигналы следует использовать actix::actors::signal.

@alexlapa alexlapa added feature New feature or request k::api Related to API (application interface) labels Jun 17, 2019
@alexlapa alexlapa added this to the 0.2.0 milestone Jun 17, 2019
@alexlapa alexlapa mentioned this issue Jun 17, 2019
15 tasks
@nWacky
Copy link
Contributor

nWacky commented Jun 18, 2019

Обсудили, решили сделать следующее:

  • Добавить graceful shutdown в Room
  • Удалять всех пользователей из redis при получении сигнала о завершении
  • Прокидывать ProcessSignals через конструктор

@nWacky nWacky mentioned this issue Jun 18, 2019
16 tasks
@nWacky
Copy link
Contributor

nWacky commented Jun 20, 2019

@alexlapa,

Проблема с закрытием приложения.

В функции main мы подписываем Room на System::current().registry().get::<signal::ProcessSignals>(), затем запускаем actix_web::HttpServer, который тоже подписывается на сигналы System::current().registry().get::<signal::ProcessSignals>().

В случае получения SIGHUP, SIGINT, SIGTERM, SIGQUIT, SIGCHILD System::current().registry().get::<signal::ProcessSignals>() посылает signal::Signal всем подписавшимся. signal::Signal - enum, содержащий сигнал, который был получен.

При получении signal::Signal actix_web::HttpServer устанавливает флаг exit на true, после чего посылает себе сигнал StopServer. StopServer вызывает stop на своих workers.

Workers или завершаются в течение shutdown_timeout (если получили SIGTERM) или делают request ServerMessage::ForceShutdown.

После того, как завершение workers закончено, actix_web ждет еще 300ms и выключает текущую систему Actix (при exit = true), в которой может еще работать код закрытия Room.

Закрытие Room посылает сигнал CloseRoom, который закрывает все RpcConnection и удаляет всех IceUser, о которых знает Room.

Суть проблемы

actix_web выключит систему через 300ms после получения закрывающего сигнала, и Room нужно успеть сделать все за 300ms, иначе ее выключат и она ничего не сможет сделать (и всем ws-клиентам вернется код 1006)

Возможные варианты решения

Насколько я знаю, мы не можем добавить свои классы к worker'ам actix_web

Можно запретить actix_web реагировать на закрывающие сигналы, и потом выключить систему, но тогда actix_web workers не смогут shut down gracefully

Можно сохранить Addr<HttpServer> в main и послать StopServer как только получен сигнал, предварительно запретив обработку сигналов. actix_web тогда не будет останавливать систему после закрытия, нужно ее закрыть вручную. Можно всегда закрывать HttpServer gracefully.

.

Я предлагаю 3-й вариант. Тогда есть 2 варианта:

  1. Сделать класс, который будет вызывать Close везде, смотреть закрылось ли все и потом выключать систему
  2. Обрабатывать сигнал закрытия каждым компонентом индивидуально и выключать систему в течение некоторого shutdown_timeout

Я предлагаю 2 вариант

@alexlapa
Copy link
Collaborator Author

alexlapa commented Jun 21, 2019

@nWacky ,

Можно сохранить Addr в main и послать StopServer как только получен сигнал, предварительно запретив обработку сигналов.

Не совсем уловил в чем различие с текущей реализацией. Сейчас сервер сам подписывается на сигнал и бросает в себя StopServer, а так мы подпишемся на сигналы и будем бросать серверуStopServer.

Сделать класс, который будет вызывать Close везде, смотреть закрылось ли все и потом выключать систему

В такой формулировке смысл появляется. Сначала уведомляем наши компоненты, ждем пока они ответят что закрылись, потом перекидываем сигнал серверу, который закроет систему.

alexlapa pushed a commit that referenced this issue Jul 18, 2019
- impl GracefulShutdown service which listens to OS signals and shutdowns each component gracefully
- impl graceful shutdown for Room and HTTP server
- add [shutdown] config section

Additionally:
- provide explicit states for Room
@alexlapa alexlapa modified the milestones: 0.2.0, 0.1.0 Jul 18, 2019
@alexlapa alexlapa mentioned this issue Jul 18, 2019
5 tasks
@tyranron tyranron added k::deploy Related to deployment capabilities and removed k::api Related to API (application interface) labels Jul 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature New feature or request k::deploy Related to deployment capabilities
Projects
None yet
3 participants