异步启停 aiohttp 服务程序

异步启停 aiohttp 服务程序

目录

  • [异步启停 aiohttp 服务程序](#异步启停 aiohttp 服务程序)
    • 一、引言
    • [二、aiohttp 服务端的基本用法](#二、aiohttp 服务端的基本用法)
    • [三、异步启停 Application 实例](#三、异步启停 Application 实例)

一、引言

aiohttp 是一个很好的 python 异步 web 库,可以用它建立高效的 web 服务端和客户端。它支持 http 协议,也支持 websocket 长连接。

一般情况下,开发 web 服务端时,我们会用 run_app 启动一个 aiohttp 的 Application,run_app 是阻塞运行的,直到整个程序的退出才关闭。

如果需要在一个线程的序运行中按需启停服务,或者是启动多个服务,就需要异步地的启动 Application,本文根据 aiohttp 的官方文档,对这个问题进行一些探讨。

有关异步启停和优雅关闭服务方面可供参考的官方文档网址如下:https://docs.aiohttp.org/en/stable/web_advanced.html#aiohttp-web-graceful-shutdown

二、aiohttp 服务端的基本用法

aiohttp 官网给出服务端的基本用法 。启动一个服务端须经历以下几个步骤:

1. 生成一个 aiohttp.web.Application 实例;

2. 编写一个或多个服务程序;

3. 将服务程序加入 Application 实例的路由(route);

4. 运行 Application 实例,启动服务。

下面的程序简单演示了 aiohttp 的基本用法:

python 复制代码
from aiohttp import web


# 2. 编写服务程序;
async def hello(request):
    return web.Response(text="Hello, world")

# 1. 生成 Application 实例;
app = web.Application()
# 3. 将服务加入 Application 的路由;
app.add_routes([web.get('/', hello)])
# 4. 启动服务。
web.run_app(app, host="127.0.0.1", port=8888)

运行这个程序,在本机打开浏览器,地址栏输入:127.0.0.1:8888。浏览器就会显示服务返回的"Hello world"字符串。

上述程序中,还可以用 route 装饰形成路由表,启动前直接将路由表加入 Application 实例:

python 复制代码
from aiohttp import web

# 定义路由表
routes = web.RouteTableDef()


# 定义路由表中的应用服务程序
@routes.get('/')
async def hello(request):
    return web.Response(text="Hello, world")


app = web.Application()
# 将路由表加入 Application 实例
app.add_routes(routes)
web.run_app(app, host="127.0.0.1", port=8888)

三、异步启停 Application 实例

上述 web.run_app 方法是阻塞运行的。它无法在一个线程中启动多个不同 url 的服务,也不方便服务的随时启动和停止。为此,aiohttp 提供了 runner 类,可以异步启停多个服务。

上述使用 web.run_app 方法运行 Application 的程序略加修改,就可以使用 runner 类启动:

python 复制代码
from aiohttp import web
import asyncio


async def hello(request):
    return web.Response(text="Hello, world")


# 由于 runner 的设置和 site 的启动是异步方法,所以它们必须处于一个异步函数中
async def run_server():
    app = web.Application()
    app.add_routes([web.get('/', hello)])
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, 'localhost', 8080)
    # 异步启动 site,下面的语句不阻塞
    await site.start()
	# 如果需要启停一个或多个服务,可以将代码放在这个位置,但要保证 run_server 不退出,
	# 否则所有的服务都退出了。
	
	# 这是模拟的代码,保证 run_server 不退出。
    while True:
        await asyncio.sleep(3600)

# 启动程序的同步代码
asyncio.run(run_server())

它的运行结果和和前面的程序是一样的,但与之相比,这个程序做了如下修改和补充:

1. 用已经生成的 Application 实例建立一个 web.AppRunner 的实例(runner);

2. 用 setup 方法对 runner 进行设置;

3. 建立一个 web.TCPSite 实例,并用 start 方法启动这个实例。

如果将 run_server 方法的最后两行(while True: 和 await asyncio ...两行)改为:asyncio.sleep(20),再运行这个程序就会发现:运行20秒后程序就退出了。

实际应用程序中,服务的退出不应该如此粗暴,关于优雅地退出服务的内容,可以参见官网文档

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax