异步启停 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秒后程序就退出了。

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

相关推荐
架构技术专栏6 小时前
Agent 工具调用:从工具声明到执行反馈
前端·人工智能·后端
别动我齐刘海6 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
志尊宝7 小时前
Vue3 零基础每日笔记(071):暗黑模式与主题切换——CSS 变量 + Element Plus 暗黑方案
前端·css·笔记·vue·html·前端开发·软件开发
刘发财8 小时前
前端如何生成10000页PDF文件?
前端·javascript·开源
A接拉起0078 小时前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
用户11481867894848 小时前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界8 小时前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
葡萄城技术团队8 小时前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
三*一9 小时前
优化修整算法
前端·javascript·算法
weifont10 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化