MST

星途 面试题库

面试题:网络编程中异步编程模型在Web后端开发里如何实现高并发处理

在Web后端开发场景下,描述使用异步编程模型处理高并发请求的常见方式,例如以Python的asyncio库或者Node.js的异步机制为例,阐述如何通过异步操作避免线程阻塞,提升系统的并发处理能力。
37.9万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试

Python 的 asyncio 库

  1. 协程定义
    • 使用 async def 关键字定义协程函数。例如:
    async def fetch_data():
        await asyncio.sleep(1)
        return "Data fetched"
    
    • 这里 await 用于暂停协程,等待 asyncio.sleep(1) 这个异步操作完成,在等待期间,事件循环可以调度其他协程执行,从而避免线程阻塞。
  2. 事件循环
    • 通过 asyncio.get_event_loop() 获取事件循环对象,然后使用 loop.run_until_complete(coro) 来运行协程。例如:
    import asyncio
    
    async def fetch_data():
        await asyncio.sleep(1)
        return "Data fetched"
    
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(fetch_data())
    print(result)
    
    • 在现代 Python 中,也可以使用 asyncio.run() 来简化操作,asyncio.run() 内部会创建和管理事件循环。例如:
    import asyncio
    
    async def fetch_data():
        await asyncio.sleep(1)
        return "Data fetched"
    
    result = asyncio.run(fetch_data())
    print(result)
    
  3. 并发执行多个协程
    • 使用 asyncio.gather(*coros) 来并发运行多个协程。例如:
    import asyncio
    
    async def task1():
        await asyncio.sleep(1)
        return "Task 1 done"
    
    async def task2():
        await asyncio.sleep(2)
        return "Task 2 done"
    
    async def main():
        results = await asyncio.gather(task1(), task2())
        print(results)
    
    asyncio.run(main())
    
    • 这里 asyncio.gather 会同时启动 task1task2 两个协程,在 task1task2 等待 asyncio.sleep 的过程中,事件循环可以调度其他可运行的协程,大大提升了并发处理能力。

Node.js 的异步机制

  1. 回调函数
    • 早期在 Node.js 中,广泛使用回调函数来处理异步操作。例如读取文件:
    const fs = require('fs');
    
    fs.readFile('example.txt', 'utf8', (err, data) => {
        if (err) {
            console.error(err);
            return;
        }
        console.log(data);
    });
    
    • 但是这种方式容易导致回调地狱,当异步操作嵌套层次过多时,代码可读性和维护性变差。
  2. Promise
    • Promise 是一种更优雅的处理异步操作的方式。例如使用 fs.promises 来读取文件:
    const fs = require('fs').promises;
    
    fs.readFile('example.txt', 'utf8')
       .then(data => {
            console.log(data);
        })
       .catch(err => {
            console.error(err);
        });
    
    • 多个 Promise 可以通过 .then() 链式调用,避免了回调地狱。而且 Promise.all([...promises]) 可以并行执行多个 Promise,并在所有 Promise 都完成后返回结果,提升并发处理能力。例如:
    const fs = require('fs').promises;
    
    const promise1 = fs.readFile('file1.txt', 'utf8');
    const promise2 = fs.readFile('file2.txt', 'utf8');
    
    Promise.all([promise1, promise2])
       .then(([data1, data2]) => {
            console.log(data1, data2);
        })
       .catch(err => {
            console.error(err);
        });
    
  3. async/await
    • 基于 Promise,async/await 语法糖让异步代码看起来更像同步代码。例如:
    const fs = require('fs').promises;
    
    async function readFiles() {
        try {
            const data1 = await fs.readFile('file1.txt', 'utf8');
            const data2 = await fs.readFile('file2.txt', 'utf8');
            console.log(data1, data2);
        } catch (err) {
            console.error(err);
        }
    }
    
    readFiles();
    
    • await 只能在 async 函数内部使用,它暂停函数执行,直到 Promise 被解决(resolved)或被拒绝(rejected),在等待期间,Node.js 事件循环可以处理其他任务,提升了系统的并发处理能力。