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

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

相关推荐
小小小小宇5 小时前
虚拟列表兼容老DOM操作
前端
悦悦子a啊5 小时前
Python之--基本知识
开发语言·前端·python
安全系统学习6 小时前
系统安全之大模型案例分析
前端·安全·web安全·网络安全·xss
涛哥码咖6 小时前
chrome安装AXURE插件后无效
前端·chrome·axure
OEC小胖胖6 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水7 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
Sally璐璐7 小时前
零基础学HTML和CSS:网页设计入门
前端·css
老虎06277 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
灿灿121387 小时前
CSS 文字浮雕效果:巧用 text-shadow 实现 3D 立体文字
前端·css
烛阴7 小时前
Babel 完全上手指南:从零开始解锁现代 JavaScript 开发的超能力!
前端·javascript