Django와 Gunicorn/Uvicorn을 사용하는 매우 간단한 웹 서비스가 있습니다.
foo.service
[Unit]
Description=Foo service
Requires=foo.socket
After=network.target
[Service]
User=foo
Group=www-data
Restart=on-failure
WorkingDirectory=/var/lib/foo/current/backend
ExecStart=/var/lib/foo/.local/bin/poetry run gunicorn \
--env DJANGO_SETTINGS_MODULE=foo.settings \
--capture-output \
--log-level info \
--bind unix:/run/foo.sock \
--worker-class uvicorn.workers.UvicornWorker \
--workers 4 \
foo.asgi:application
[Install]
WantedBy=multi-user.target
foo.socket
[Unit]
Description=Foo socket
[Socket]
ListenStream=/run/foo.sock
[Install]
WantedBy=sockets.target
서비스를 활성화하고 시작했습니다. 애플리케이션을 재배포할 때 애플리케이션을 오프라인 상태로 유지해야 하는 동안 데이터베이스를 마이그레이션하고 다른 작업을 수행합니다. 하지만 내가 발행할 때:
sudo systemctl restart foo.service
이 메시지를 받았습니다
Warning: Stopping foo.service, but it can still be activated by:
foo.socket
소켓을 다시 시작해야 합니까? 서비스를 비활성화하고 소켓만 활성화하시겠습니까? (이 소켓은 nginx에서 사용됩니다.) 여기서 가장 좋은 방법은 무엇입니까? 데이터베이스를 마이그레이션할 때 소켓을 통해 서비스가 활성화되는 것을 원하지 않습니다.
답변1
여기에는 세 가지 옵션이 있습니다.
- 두 장치를 함께 시작/중지합니다. 이 작업을 수행해야 한다는 점을 기억해야 하므로 이는 최선의 솔루션은 아닙니다.
sudo systemctl stop foo.{service,socket}
- 관리 서비스만 가능합니다. 이를 위해서는 다음이 필요합니다.
[Install]
소켓 부분을 내려 놓습니다 . 서비스가 이미Requires=
소켓이므로 이는 필요하지 않습니다. 서비스가 시작되면 소켓도 시작됩니다.PartOf=foo.service
소켓 섹션에 추가되었습니다[Unit]
. 이는 중지되거나 다시 시작될 때foo.service
명령이 소켓에 전파된다는 것을 의미합니다.
# foo.service
[Unit]
Requires=foo.socket
After=network.target
[Service]
...
[Install]
WantedBy=multi-user.target
#foo.socket
[Unit]
PartOf=foo.service
[Socket]
ListenStream=/run/foo.sock
이제 가능하며 sudo systemctl {restart,stop,start} foo.service
소켓은 항상 동기화됩니다.
- 소켓만 관리합니다. 데이터가 소켓에 도착할 때만 서비스가 실행되기 때문에 이 옵션을 선호합니다. 이것을하기 위해:
Requires=
서비스에서 제거되었습니다. 서비스를 직접 시작하지 않기 때문에 이것이 필요하지 않습니다.[Install]
서비스에서 이 부분을 제거하세요. 대신 소켓을 사용하겠습니다.PartOf=foo.socket
서비스 섹션에 추가되었습니다[Unit]
. 애플리케이션이EOF
stdin 또는 stdout에서 종료되는 경우 이는 필요하지 않을 수 있습니다.- 서비스 섹션
StandardInput=socket
에 추가하세요 .[Service]
이는 꼭 필요한 것은 아니지만systemctl start foo.service
소켓이 시작되지 않으면 실패합니다.
# foo.service
[Unit]
PartOf=foo.socket
After=network.target
[Service]
StandardInput=socket
...
#foo.socket
[Socket]
ListenStream=/run/foo.sock
[Install]
WantedBy=sockets.target