Улучшение сервиса для остановки «по требованию»
- часть: создание сервиса
- часть: вы читаете это прямо сейчас
- часть: обновление для Интернета
- часть: добавление SSE
- часть: простая функциональность внешнего интерфейса javascript
- часть: frontend - backend коммуникация
- часть: логирование на стороне сервера
- часть: запустить все в докере
- часть: добавление контейнера базы данных
- часть: база данных - служебная связь
Дополнение 1: функции, методы, указатели и интерфейсы
Дополнение 2: связь через веб-сокеты
Дополнение 3: связь через сокеты
Что значит «правильный путь»?
Вы сделали свою программу Go для запуска в качестве службы, и есть рабочий код, который занимает около 5 секунд, чтобы завершить всю работу. Вы же не хотите останавливать сервис посреди работы, не так ли?
В этой статье расширен код, который мы создали ранее, поэтому служба остановится только после того, как этот рабочий код будет выполнен.
Это означает: все, что происходит в вашем рабочем коде, не будет зашифровано, когда кто-то остановит вашу службу. Конечно, есть много способов, как это сделать. Это мой стиль работы.
Обновите код
Поскольку нам нравится знать состояние службы в каждый момент времени, когда код выполняется, мы добавим две логические переменные, которые показывают нам их статусы, например, используя fmt.Println()
.
Добавить переменные
Эти две переменные мы назовем serviceIsRunning
и programIsRunning
. Начнем с добавления этих двух переменных чуть ниже раздела импорта. Добавим третью переменную типа sync.Mutex
. Эта переменная берет на себя ответственность за синхронизацию при записи или чтении в / из этих двух логических переменных (когда две строки кода хотят обновить переменную serviceIsRunning
в одно и то же время, мьютекс допускает только одну строка кода, чтобы внести изменение, и затем пригласите вторую строку кода внести ее изменение).
В этом конкретном примере мы не будем записывать в одну переменную из двух разных разделов кода, поэтому в этом sync.Mutex
нет необходимости сейчас, но мы будем его использовать.
Как видите, все три переменные подчеркнуты красным. Причина снова та же: мы нигде не используем эти переменные.
Обновите методы
Сначала мы начнем с serviceIsRunning
.
Обновите Start()
метод приведенным ниже кодом. Первоначально для переменной serviceIsRunning
установлено значение false. После запуска службы мы установили для нее значение true. Перед установкой мы блокируем эту serviceIsRunning
переменную с помощью writingSync.Lock()
, поэтому любая другая будущая строка в программе (которая хочет записать в ту же переменную) должна ждать, пока эта writingSync
разблокирует обратно нашу serviceIsRunning
переменную. Теперь, когда наша служба запускается, наша переменная serviceIsRunning
установлена правильно.
Нечто подобное мы делаем с методом Stop()
. Больше никаких разговоров, код ниже, и идея та же.
Пришло время поиграть с переменной programIsRunning
. Переходим к run()
методу. Сначала мы хотим убедиться, что наш производственный код будет работать только в том случае, если служба уже запущена. Смотрите код ниже, ничего особенного. Добавление одного условия: производственный код выполняется, только если переменная serviceIsRunning
истинна.
Теперь вы можете протестировать свой код. Он будет работать так же, как и раньше, поэтому похоже, что мы не добились прогресса, но поверьте мне, мы добились прогресса.
Обновить производственный код
Чтобы увидеть эффект в работе, обновите метод time.Sleep()
, чтобы он подождал 2 секунды (вы можете попробовать 5 секунд, чтобы лучше увидеть эффект).
Мы снова играем с этой переменной мьютекса и впервые с переменной programIsRunning
. Код ниже показывает изменения.
Выполнение этого кода занимает около двух секунд. Вначале мы устанавливаем programIsRunning
на true (так что везде в нашем коде мы можем проверить, запущена ли эта программа). И после завершения этого цикла мы снова устанавливаем для этой переменной programIsRunning
значение false.
После того, как все это будет сделано, вы можете проверить, работает ли программа. И запускается, но… все равно никакого эффекта.
Окончательная точная настройка
Вернемся к нашему Stop()
методу. Обновите код новым циклом. Этот новый цикл просто ожидает, пока переменная programIsRunning
не станет false (что означает: он ждет, пока рабочий код завершит себя).
И только тогда цикл завершится Stop()
методом.
Финальный тест
Запустите код сейчас (если вы не видите эффекта, увеличьте time.Sleep()
в run()
методе до 5 секунд).
Надеюсь, вы заметите эффект. Когда вы пытаетесь остановить программу (имитируя, что кто-то останавливает службу), программа ожидает правильного завершения рабочего кода, и только после этого служба закрывается.
Например: если вы увеличите время сна в run()
методе до 10 секунд, вы увидите намного больше Medium service stopping ...
строк. Конечно, это зависит от того, когда вы остановите программу.
Резюме
Прочитав эту статью, вы узнаете, как…
- Сделайте так, чтобы ваша служба работала и завершалась должным образом
- знать в каждой части кода, каково состояние службы