Python依赖注入容器构建异步监控守护进程教程
概述
本文将介绍如何使用Python依赖注入容器(dependency-injector)构建一个基于asyncio的监控守护进程。我们将创建一个能够定期检查网站可用性的监控服务,通过这个实际案例展示依赖注入在异步编程中的应用。
项目目标
我们将构建一个监控守护进程,主要功能包括:
- 定期向目标网站发送HTTP请求
- 记录响应状态码、内容长度和响应时间
- 使用异步I/O提高监控效率
- 采用依赖注入管理组件依赖关系
技术栈
- Python 3
- asyncio (异步I/O框架)
- aiohttp (异步HTTP客户端)
- dependency-injector (依赖注入框架)
- Docker (容器化部署)
环境准备
项目结构
首先创建项目基础结构:
asyncio-daemon-tutorial/
├── monitoringdaemon/
│ ├── __init__.py
│ ├── __main__.py
│ └── containers.py
├── config.yml
├── docker-compose.yml
├── Dockerfile
└── requirements.txt
依赖配置
在requirements.txt中添加以下依赖:
dependency-injector
aiohttp
pyyaml
pytest
pytest-asyncio
pytest-cov
Docker配置
创建Dockerfile:
FROM python:3.13-bookworm
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY . /code/
RUN apt-get install openssl \
&& pip install --upgrade pip \
&& pip install -r requirements.txt \
&& rm -rf ~/.cache
CMD ["python", "-m", "monitoringdaemon"]
docker-compose.yml配置:
services:
monitor:
build: ./
image: monitoring-daemon
volumes:
- "./:/code"
核心组件实现
1. 依赖注入容器
容器是应用的核心,管理所有组件及其依赖关系。首先创建基础容器:
# containers.py
import logging
import sys
from dependency_injector import containers, providers
class Container(containers.DeclarativeContainer):
config = providers.Configuration(yaml_files=["config.yml"])
logging = providers.Resource(
logging.basicConfig,
stream=sys.stdout,
level=config.log.level,
format=config.log.format,
)
2. 主程序入口
# __main__.py
from dependency_injector.wiring import Provide, inject
from .dispatcher import Dispatcher
from .containers import Container
@inject
def main(dispatcher: Dispatcher = Provide[Container.dispatcher]) -> None:
dispatcher.run()
if __name__ == "__main__":
container = Container()
container.init_resources()
container.wire(modules=[__name__])
main()
3. 监控调度器
调度器负责管理所有监控任务:
# dispatcher.py
import asyncio
import logging
import signal
import time
from typing import List
from .monitors import Monitor
class Dispatcher:
def __init__(self, monitors: List[Monitor]) -> None:
self._monitors = monitors
self._monitor_tasks: List[asyncio.Task] = []
self._logger = logging.getLogger(self.__class__.__name__)
self._stopping = False
def run(self) -> None:
asyncio.run(self.start())
async def start(self) -> None:
self._logger.info("Starting up")
for monitor in self._monitors:
self._monitor_tasks.append(
asyncio.create_task(self._run_monitor(monitor)),
)
asyncio.get_event_loop().add_signal_handler(signal.SIGTERM, self.stop)
asyncio.get_event_loop().add_signal_handler(signal.SIGINT, self.stop)
await asyncio.gather(*self._monitor_tasks, return_exceptions=True)
self.stop()
# 其他方法...
4. HTTP监控实现
创建HTTP客户端和监控器:
# http.py
from aiohttp import ClientSession, ClientTimeout, ClientResponse
class HttpClient:
async def request(self, method: str, url: str, timeout: int) -> ClientResponse:
async with ClientSession(timeout=ClientTimeout(timeout)) as session:
async with session.request(method, url) as response:
return response
# monitors.py
import logging
import time
from typing import Dict, Any
from .http import HttpClient
class HttpMonitor(Monitor):
def __init__(self, http_client: HttpClient, options: Dict[str, Any]) -> None:
self._client = http_client
self._method = options.pop("method")
self._url = options.pop("url")
self._timeout = options.pop("timeout")
super().__init__(check_every=options.pop("check_every"))
async def check(self) -> None:
time_start = time.time()
response = await self._client.request(
method=self._method,
url=self._url,
timeout=self._timeout,
)
# 记录监控结果...
配置监控目标
在config.yml中配置监控目标:
log:
level: "INFO"
format: "[%(asctime)s] [%(levelname)s] [%(name)s]: %(message)s"
monitors:
example:
method: "GET"
url: "http://example.com"
timeout: 5
check_every: 10
运行与测试
构建并运行容器:
docker compose build
docker compose up
总结
通过本教程,我们实现了一个基于依赖注入的异步监控守护进程,展示了:
- 如何使用dependency-injector管理组件依赖
- 如何构建asyncio守护进程
- 如何实现可扩展的监控系统
- 容器化部署的最佳实践
这个架构具有良好的扩展性,可以方便地添加新的监控类型或调整监控策略。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考