高并发系统设计:从理论到实践(适合零基础初学者的入门教程)

不想写日报
2025-06-13 22:20
阅读 310

🌟 开篇:什么是高并发?它为什么重要?

🌟 开篇:什么是高并发?它为什么重要?

想象一下,你刚刚上线了一个电商网站。第一天只有10个人访问,系统运行得非常好;第二天有1万人同时访问,你的网站就崩溃了。

这就是我们今天要解决的问题——如何让系统在面对“大量用户同时访问”时仍然能正常运行。这种能力,叫做“高并发处理能力”。

为什么学习高并发?

  • 大公司(如淘宝、京东、微博)每天都要处理上百万甚至上亿次请求
  • 系统不稳定会让你的网站宕机、用户体验差、老板发火 😂
  • 掌握高并发技术是成为后端开发高手的必经之路

接下来我们将通过一个简单的实战项目带你了解什么是高并发,以及如何一步步优化系统来应对它。


⚙️ 环境准备:搭建你的开发环境

⚙️ 环境准备:搭建你的开发环境

在开始前,你需要安装以下几个工具:

1. 安装 Node.js(用于快速编写服务器)

验证是否安装成功:

node -v
npm -v

2. 安装 Express(轻量级 Node.js 框架)

npm install express --save

3. 安装压测工具 Artillery(模拟大量用户)

npm install -g artillery

验证是否安装成功:

artillery version

小提示:如果你是Windows用户,请使用命令行或 PowerShell 运行这些命令


🔍 核心概念:高并发背后的关键词解释

🔍 核心概念:高并发背后的关键词解释

在正式写代码之前,我们需要理解几个关键术语。我们会用最通俗的语言解释它们。

1. 请求(Request)

当你打开一个网页时,浏览器会向服务器发送一个请求,比如:“请把首页给我”。这个动作就是一次请求。

2. 响应(Response)

服务器收到请求后,会把数据返回给你。比如你访问百度,服务器就返回一个页面内容。

3. 并发(Concurrency)

指“有多少人同时在访问服务器”。例如,100个用户同时刷新页面,就有100个并发请求。

4. 吞吐量(Throughput)

单位时间内服务器能处理多少请求。比如每秒处理100个请求。

5. 阻塞与非阻塞

  • 阻塞式调用:必须等前面的请求完成才能继续执行下一个。
  • 非阻塞式调用:可以并行处理多个请求(Node.js 默认是非阻塞的)

6. 缓存(Cache)

把常用的数据预先保存在内存里,这样用户下次访问就可以直接从缓存中取,不用每次都去数据库查。


🛠 实战项目:从“单线程服务器”开始

🛠 实战项目:从“单线程服务器”开始

我们将从一个非常简单的 Node.js 应用开始,然后逐步优化它,让它能够承受更大的并发压力。

第一步:创建一个最基础的服务

新建文件 server.js 内容如下:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
    console.log("有人访问了首页");
    res.send("欢迎来到高并发世界!");
});

app.listen(3000, () => {
    console.log("服务启动于 http://localhost:3000");
});

运行服务:

node server.js

访问 http://localhost:3000 看到“欢迎来到高并发世界!”说明服务已启动。


第二步:使用 Artillery 发起并发测试

我们来模拟100个用户同时访问我们的首页。

新建一个压力测试配置文件 load.yaml

config:
  target: "http://localhost:3000"
  phases:
    - duration: 10
      arrivalRate: 100
scenarios:
  - flow:
      - get:
          url: "/"

然后运行压测:

artillery run load.yaml

你会看到输出类似下面的内容:

All virtual users finished
Summary report @ 18:05:00(+0800)
  Scenarios launched:  100
  Scenarios completed: 100
  Requests completed:  100
  RPS sent: 9.7
  ...

这说明我们的服务已经能处理100个并发请求了!是不是很酷?

但是问题来了👇


💥 问题来了:当请求变慢怎么办?

假设我们在首页加了一个耗时操作,比如读取一个大文件或计算斐波那契数列。

修改 server.js 如下:

app.get('/', (req, res) => {
    let result = 0;
    for (let i = 0; i < 1e8; i++) { // 模拟耗时操作
        result += i;
    }
    console.log("有人访问了首页");
    res.send(`结果是:${result}`);
});

再次用 Artillery 测试,你会发现响应时间变得非常慢,甚至有些请求超时了。

原因分析:

Node.js 是单线程的,默认情况下每次请求都会排队处理,如果其中一个请求很慢,其他请求就得等。


🚀 解决方案一:使用异步非阻塞代码

我们可以把“耗时任务”放到另一个线程中去做,避免卡住主进程。

安装多线程库 worker_threads:

npm install worker_threads

修改 server.js:

const express = require('express');
const { Worker } = require('worker_threads');

const app = express();

function runTask() {
    return new Promise((resolve, reject) => {
        const worker = new Worker('./taskWorker.js');
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.on('exit', (code) => {
            if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
        });
    });
}


![微服务架构示意图-1](https://code-guide.oss.shanghai.autogptai.club/common/file/download?name=date2025061322/696955a2-cdc2-42b6-9b18-e30d8f18ca78.jpg)


app.get('/', async (req, res) => {
    const result = await runTask();
    res.send(`计算结果是:${result}`);
});

app.listen(3000, () => {
    console.log("服务运行在 http://localhost:3000");
});

创建一个新的文件 taskWorker.js,用来执行耗时任务:

const { parentPort } = require('worker_threads');

let result = 0;
for (let i = 0; i < 1e8; i++) {
    result += i;
}

parentPort.postMessage(result);

现在再运行 Artillery 测试:

node server.js
artillery run load.yaml

你会发现虽然每个请求本身还是慢,但不会互相阻塞了!


☁️ 解决方案二:引入缓存减少重复计算

刚才的例子中,我们反复做同样的计算。其实很多业务场景也是一样的,比如查热门商品信息。

我们可以用 Redis 来缓存这些重复结果。

安装 Redis 和 Redis 客户端

npm install redis

修改 server.js 加入缓存逻辑:

const express = require('express');
const { Worker } = require('worker_threads');
const redis = require('redis');

const app = express();
const client = redis.createClient();

client.on('error', (err) => {
    console.log("Redis Error:", err);
});

function runTask() {
    return new Promise((resolve, reject) => {
        const worker = new Worker('./taskWorker.js');
        worker.on('message', resolve);
        worker.on('error', reject);
    });
}

app.get('/', async (req, res) => {
    const cacheKey = 'fibonacci_result';

    client.get(cacheKey, async (err, data) => {
        if (data) {
            res.send(`从缓存获取结果: ${data}`);
        } else {
            const result = await runTask();
            client.setex(cacheKey, 10, result); // 缓存10秒
            res.send(`新计算结果: ${result}`);
        }
    });
});

app.listen(3000, () => {
    console.log("服务运行在 http://localhost:3000");
});

现在再来测试一下,你会发现第一次请求慢,后面的都快了!


🌐 解决方案三:使用 Nginx 做负载均衡(可选进阶)

如果你部署多个 Node.js 实例,可以通过 Nginx 将请求分发到不同的实例上。

示意图如下:

[客户端] ——> [Nginx 负载均衡器] ——> [Node.js 实例1]
                                 \
                                  \——> [Node.js 实例2]

安装 Nginx(以 Ubuntu 为例):

sudo apt update
sudo apt install nginx

配置 /etc/nginx/conf.d/load-balancer.conf

upstream mynodes {
    least_conn;
    server localhost:3000;
    server localhost:3001;
}

server {
    listen 80;

    location / {
        proxy_pass http://mynodes;
    }
}

启动两个 Node.js 实例:

node server.js # 端口3000
node server.js --port 3001 # 修改代码监听3001端口

重启 Nginx:

sudo systemctl restart nginx

现在你可以通过 curl http://localhost 来测试负载均衡效果了。


❓新手常见问题解答

Q1:高并发和高性能有什么区别?

对比项 高并发 高性能
关注点 同时处理多少请求 单个请求处理有多快
举例 支持1000人同时访问 页面加载时间<1s

Q2:CPU密集型任务怎么处理更好?

  • 使用子线程处理(如 worker_threads)
  • 或者使用像 Go、Java 这类更适合多线程的语言
  • 把计算密集的任务移到后端服务中执行

Q3:缓存失效了怎么办?

  • 设置过期时间(TTL)
  • 使用缓存预热策略
  • 设置降级机制(比如缓存未命中时再去查询数据库)

🎯 学习建议:下一步该学什么?

恭喜你完成了第一个高并发项目的搭建和优化!

接下来你可以继续深入学习以下方向:

✅ 建议路线图:

  1. 学习更专业的架构模式:如微服务、分布式系统
  2. 学习使用消息队列(如 Kafka/RabbitMQ)
  3. 学习数据库优化(索引、分库分表)
  4. 学习服务注册与发现(Consul、Zookeeper)
  5. 掌握容器化部署(Docker + Kubernetes)

📚 总结

今天我们从零开始,实现了一个简单但具备初步高并发能力的 Web 服务。主要内容包括:

步骤 学习内容 工具/技术
第一步 搭建基础服务 Express
第二步 模拟并发请求 Artillery
第三步 异步处理任务 worker_threads
第四步 引入缓存机制 Redis
第五步 分布式部署 Nginx

通过这篇文章的学习,你应该对“高并发系统设计”已经有了感性认识,并且能够动手写出自己的并发服务。

如果你觉得这篇教程对你有帮助,欢迎点赞、分享给更多想入门的同学!我们下期再见 👋


📌 附录:完整代码下载地址

GitHub 示例仓库链接:https://github.com/example/high-concurrency-demo(虚拟链接供示意)

📌 推荐资源

  • 《Node.js 高并发编程》
  • B站视频合集:高并发系统从入门到实战
  • 极客时间专栏:高并发系统核心知识地图

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝