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

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

相关推荐
西安小哥10 小时前
破局与重生:大厂前端如何借力 AI 转型“超级全栈“
前端·人工智能
sunly_11 小时前
TypeScript总结:16、面向对象速查
前端·javascript·typescript
MXN_小南学前端11 小时前
React超长文本域中实现“返回顶部”浮动按钮
前端·javascript·react.js
学习嵌入式的小周11 小时前
Notepad++8.8.7下载安装(附安装包)
前端·notepad++
gs8014011 小时前
解构 Cordis:面向“时空可组合性”的 TypeScript 元框架深度剖析
前端·javascript·typescript
岁岁种桃花儿12 小时前
Vue核心语法第一篇:Vue是什么?
前端·javascript·vue.js
观无13 小时前
若依EasyExcel实现单元格合并
开发语言·前端·javascript
愚公搬代码13 小时前
【愚公系列】《Web应用安全》001-VMware的安装
前端·安全
xiaohaiAIgeo13 小时前
【2026年】HG/T 20656-2024化工暖通空调设计规范:新版标准的变化与影响
java·前端·javascript·科普知识
立少→万能汉编13 小时前
用“立少→超文本”写静态网页,标签<倍>
服务器·前端·javascript