Skip to content

第 13 讲|常见技术栈

打开任意一个稍复杂的 Web 系统架构图,会看到一组组件名:Vue、React、FastAPI、Spring Boot、MySQL、Redis、Kafka、Nginx、Prometheus、Grafana……第一次接触很容易眼花。

这些组件不是平铺在一起的工具清单,而是各自占据系统的某一层:页面、接口、数据、入口、发布、观测。理解技术栈的关键是先看每个组件在系统里站哪一层——页面谁渲染、接口谁提供、数据放哪、异步任务怎么跑、外部请求从哪进、出问题去哪看。把这些位置关系理清,后面接触任何新组件都能快速归类。

本讲按系统的层次结构,梳理每一层的主流技术选择、适用场景、选型考量。

一、按层次理解技术栈

一个典型 Web 系统的完整技术栈分层:

技术栈要按页面接口数据入口观测等层次理解

接下来逐层讲清楚每一层的主流选择。

二、页面层(前端)

前端负责浏览器内的页面结构、样式、交互、调用后端接口。最终在浏览器中加载的就是 HTML、CSS、JavaScript、图片、字体。

主流技术分类

类型主流选择在系统中的位置
基础能力HTML、CSS、JavaScript浏览器原生支持,所有前端最终跑这三样
框架Vue、React、Angular组件化开发、状态管理、路由
构建工具Vite、Webpack、esbuild把 Vue/JSX/TS 编译为浏览器可执行的 JS
UI 组件库Element Plus、Ant Design、Naive UI、Tailwind现成的表单、表格、弹窗、布局
状态管理Pinia、Redux、Zustand跨组件共享状态
路由Vue Router、React RouterSPA 内部页面跳转

框架选择的现状

框架国内海外 / 国际
Vue国内主流(简洁、文档好、上手快)较少使用
React大厂主流(生态最庞大、招聘多)全球主流
Angular较少企业级项目较多
Svelte / Solid新兴,较少新兴,增长快

技术框架选择的现实考量:团队熟悉度 > 招聘市场 > 技术本身。各主流框架在能力上没有质的差距,Vue/React 都能胜任绝大多数业务,选哪个更多看团队基础。

何时不需要前端框架

简单场景下,原生 HTML/CSS/JS 完全够用,不必上框架:

  • 静态展示页面
  • 简单表单
  • 内部小工具
  • 静态文档站

引入 Vue/React 会增加构建复杂度、学习成本、首屏加载体积。框架是为复杂交互而设计的,不是为了"显得现代化"。

前后端的连接点:HTTP API

前端代码通过 fetchaxios 调用后端 API:

javascript
fetch('/api/users/me', {
  headers: { 'Authorization': `Bearer ${token}` }
})
  .then(res => res.json())
  .then(user => renderProfile(user));

后端返回 JSON,前端拿到后渲染页面。这就是前后端分离的核心交互模式。

前端的发布

前端构建后产出的静态文件(HTML / CSS / JS / 图片),可以部署在:

  • CDN:全球加速,主流选择
  • 对象存储 + CDN:OSS/S3 作为源站,CDN 缓存分发
  • Nginx:简单场景,适合内部系统
  • 边缘平台:Cloudflare Pages、Vercel、Netlify

三、接口层(后端)

后端负责HTTP 接口、业务逻辑、认证权限、数据库读写、调用外部系统

主流语言与框架

语言主流框架适用场景
JavaSpring Boot、Spring Cloud、Quarkus国内大厂核心业务、企业级微服务
PythonFastAPI、Django、Flask运维平台、内部工具、数据处理、AI 应用
GoGin、Echo、Fiber、net/http云原生组件、API 网关、高并发服务
Node.jsExpress、NestJS、Koa、FastifyBFF、轻量 API、与前端 JS 同栈
.NETASP.NET CoreWindows 生态、企业系统
RustActix、Axum极致性能、新兴选择
RubyRails国外创业公司、快速原型
PHPLaravel、Symfony传统 Web、内容管理系统

各语言的适用边界

  • Java — 生态最完整,招人最容易,大厂核心业务首选。劣势:启动慢、内存占用高、入门曲线陡
  • Python — 开发快、可读性好,数据处理与 AI 生态独一无二。劣势:运行性能中等
  • Go — 编译为单个二进制,部署极简,适合云原生(K8s、Docker、Prometheus 全家桶都是 Go)。劣势:错误处理冗长、泛型较新
  • Node.js — 与前端 JS 同语言,前端团队能顺手做后端。劣势:CPU 密集型不擅长
  • Rust — 性能与安全极致,新兴增长。劣势:学习曲线陡

语言选择的决定性因素是团队基础,不是语言本身的"优劣"

后端不只是几个路由函数

新手容易以为"后端就是写几个路由 + SQL"。真实生产级后端要处理的非业务代码往往比业务代码还多:

模块作用
配置管理多环境、热更新、敏感信息加密
数据库连接池连接复用、健康检查、连接数控制
HTTP 客户端超时、重试、连接池、TLS
统一错误处理异常 → 标准响应格式
中间件认证、限流、日志、CORS
优雅关闭收到信号后处理完已有请求再退出
健康检查Liveness / Readiness
Metrics 暴露/metrics 端点
日志规范结构化日志、Trace ID 透传
链路追踪OpenTelemetry SDK 集成
配置中心客户端动态拉取配置
服务注册客户端启动时注册、停止时注销

成熟的框架(Spring Boot、FastAPI、Gin)会把大部分基础设施做成开箱即用,但理解每一块在做什么,才能真正排查问题。

四、数据层

数据库保存系统的所有状态——用户、订单、权限、审计、配置、任务记录,所有"持久数据"都要落到某种存储。

数据层选型要按数据形态和访问模式决定

按数据特性选存储类型

类型主流选择适合存什么
关系型数据库MySQL、PostgreSQL、Oracle用户、订单、权限、审计、配置等结构化数据
文档数据库MongoDB、CouchDB字段变化多、嵌套结构、文档型数据
缓存/键值Redis、Memcached热点数据、会话、计数器、分布式锁
列式数据库ClickHouse、Cassandra大数据分析、时序聚合
搜索引擎Elasticsearch、OpenSearch全文检索、日志检索
时序数据库InfluxDB、TimescaleDB、Prometheus监控指标、IoT
图数据库Neo4j、JanusGraph社交关系、推荐
向量数据库Milvus、Qdrant、pgvectorAI/向量检索

MySQL vs PostgreSQL

国内传统业务系统 MySQL 用得最多——稳定、生态成熟、运维资料多。PostgreSQL 在以下场景上比 MySQL 强:

  • 复杂 SQL(CTE、窗口函数、递归查询)
  • JSON/JSONB 字段(原生支持索引和查询)
  • GIS 地理数据(PostGIS 扩展)
  • 全文检索(原生支持)
  • 扩展能力(自定义类型、函数、操作符)

新项目选型时,PostgreSQL 是越来越被推荐的选择——除非有特别原因(MySQL 团队经验深、强依赖某 MySQL 特性)。

多数据库共存:是常态

业务系统同时使用多种数据库是常态:

MySQL/PostgreSQL → 核心业务数据(用户、订单、权限)
Redis            → 缓存、会话、限流、锁
Elasticsearch    → 全文搜索、日志检索
ClickHouse       → 数据分析、报表
MongoDB          → 内容型数据、配置
S3/OSS           → 文件、备份

不同数据各回各家,每种存储用在它最擅长的场景。

数据库选型的真实考量

数据库选型不只看"能不能存",还要看:

  • 运维生态:监控、备份恢复、迁移工具是否成熟
  • 团队熟悉度:运维难度,故障时谁能修
  • 索引能力:能否覆盖业务的查询模式
  • 权限模型:是否能满足合规要求
  • 社区活跃度:遇到问题能找到答案
  • 云厂商托管:是否有 RDS 形式的托管服务

一个团队没人能运维的数据库,再先进也不能上生产——出问题时无人能修,损失可能比不上的"先进性"大得多。

五、缓存与消息队列

缓存加速读取,消息队列削峰异步处理

缓存

缓存放在数据库前面,挡住重复查询。Redis 是最主流的选择——除了缓存,经常顺手承担:

  • 会话存储(Session)
  • 限流计数器
  • 分布式锁
  • 排行榜(zset)
  • 实时排重(set)
  • 简单队列(list / stream)

一个 Redis 实例能解决一组小问题,所以几乎所有 Web 系统的技术栈里都有 Redis。

消息队列

消息队列放在服务之间,主要解决两个问题:

场景价值
异步执行用户请求不用等待耗时操作完成
削峰填谷突发流量被缓冲,后端按自己节奏消费
解耦生产者和消费者互不感知,可独立扩展
广播一条消息多个下游消费

主流消息队列

消息系统特点适用场景
RabbitMQAMQP 协议,功能丰富,可靠投递任务分发、传统业务队列
Kafka高吞吐、日志型设计、分区有序日志流、事件流、数据管道
RocketMQ阿里出品,事务消息、延迟消息国内电商、金融业务
Pulsar计算存储分离新兴选择,云原生
Redis Stream/List轻量,与 Redis 共用内部小任务,不想新增组件
NATS轻量、低延迟微服务通信、IoT

异步处理的标准模式

典型场景:用户点击"导出报表"

同步方案的问题:接口同步等待生成,可能需要数十秒到数分钟,用户体验差,超时风险高。

异步方案:

1. 用户请求导出 → 接口立即返回任务 ID
2. 生成任务推入消息队列
3. 后台 worker 消费队列,真正生成报表
4. 生成完毕,更新任务状态,通知用户
5. 用户通过任务 ID 查询状态、下载结果

关键认知:"请求已接收"(接口成功)≠ "任务已完成"(报表已生成)

排查这类问题时,要看:

  • 任务状态机:任务当前处于什么状态
  • 队列积压:有没有消息没被消费
  • 消费失败:重试次数、失败原因
  • 消费者实例:是否在运行、有没有崩溃

六、文件存储

上传的文件(头像、附件、图片)、备份包、日志归档、构建产物——这些不适合长期绑在某台应用服务器的本地目录上

对象存储:主流方案

按 bucket(桶)和 object key(对象键)组织文件,通过 HTTP API 访问。主流选择:

方案类型
AWS S3云厂商(行业标准)
阿里云 OSS云厂商
腾讯云 COS云厂商
MinIO自建,兼容 S3 API
Ceph RGW自建,大规模

文件元数据与对象解耦

后端数据库里只保存文件元数据,不直接存文件本身:

字段含义
file_name用户看到的原始文件名
size文件大小
mime_typeMIME 类型
owner_id归属用户/对象
object_key对象存储中的真实路径
upload_time上传时间
etag文件指纹,校验完整性

数据库存元数据,对象存储存实际文件,各自负责擅长的部分。

为什么不能放本地目录

应用扩为多实例时本地存储立即失效:

  • 用户上传头像到 app-01,文件保存在 app-01:/data/uploads/
  • 下次访问头像,请求被分到 app-02
  • app-02 本地没有这个文件 → 404

对象存储让多个实例访问同一份文件,根本解决这个问题。同时:

  • 对象存储自身有副本和容灾,可靠性高
  • 与应用实例解耦,实例随时可重建
  • 公网访问可直接走 CDN,加速分发

七、入口层

入口层负责接收外部请求,转发到正确的内部服务。这一层组件较多,各司其职。

入口层组件

组件主要职责
CDN静态资源全球分发、缓存、抗 DDoS
WAF安全过滤(SQL 注入、XSS、爬虫)
云负载均衡(SLB/ALB)公网入口、四层/七层转发
Nginx反向代理、TLS 终止、限流、静态资源
HAProxy高性能负载均衡(四层/七层)
IngressK8s 集群 HTTP/HTTPS 入口
API 网关(Kong/APISIX/Higress)认证、路由、限流、协议转换、API 管理

完整入口链路

用户 → DNS → CDN → WAF → 云 LB → Ingress/Nginx → 后端服务

每一层都可能成为问题源,出现 502、504、403、证书错误时,入口层是第一处检查点

入口日志能看到:请求是否进入、转发到哪个后端、后端返回状态、耗时分布。80% 的"用户访问异常"问题,从入口日志开始查最快

API 网关 vs Nginx

维度NginxAPI 网关(Kong/APISIX)
主要用途反向代理 + 静态资源API 管理 + 服务路由
配置方式配置文件控制台 / API
插件能力较少(需要 Lua)丰富(认证、限流、转换、日志等几十种)
动态路由不支持热更新(reload 切换)实时更新
服务发现集成较少原生支持
适用场景简单代理、静态资源微服务 API 管理

简单场景用 Nginx 足够;微服务架构、API 管理需求复杂的场景才需要 API 网关。

八、可观测与发布

可观测组件

可观测组件负责"看见"系统状态,出问题时能定位:

能力主流选择
指标采集和存储Prometheus、VictoriaMetrics、Mimir
指标看板Grafana(几乎是标准)
告警Alertmanager、Nightingale(夜莺)
日志收集Filebeat、Fluentd、Promtail、Vector
日志存储 / 查询Loki、Elasticsearch、OpenSearch、ClickHouse
链路追踪OpenTelemetry、Jaeger、SkyWalking、Tempo
APM(应用性能管理)SkyWalking、Datadog、New Relic

发布组件

发布组件负责把代码变成线上版本:

能力主流选择
代码仓库GitLab、GitHub、Gitea、Bitbucket
CI(持续集成)GitLab CI、Jenkins、GitHub Actions、Drone、Tekton
镜像仓库Harbor、阿里云 ACR、Docker Hub
CD / GitOpsArgo CD、Flux、Spinnaker
配置管理Ansible、Terraform、Pulumi

九、一套典型的内部技术栈

把所有层串起来,一套典型的中型公司内部技术栈大概是:

前端       Vue 或 React + Vite + Element Plus / Ant Design
后端       Spring Boot(Java)或 FastAPI(Python)或 Gin(Go)
数据库     MySQL 或 PostgreSQL + Redis 缓存
搜索       Elasticsearch(可选)
文件       MinIO 或 云 OSS
消息       RabbitMQ 或 Kafka(可选)
入口       Nginx + 云 SLB
容器       Docker
编排       Kubernetes
监控       Prometheus + Grafana + Alertmanager
日志       Loki + Grafana,或 ELK
追踪       Jaeger 或 SkyWalking
CI/CD      GitLab CI + Harbor + Argo CD
配置       Apollo 或 Nacos
注册中心   Nacos 或 Consul(微服务场景)

这不是唯一答案,只是常见的位置关系。换其中任何一个组件(Vue → Svelte、MySQL → TiDB、Prometheus → VictoriaMetrics),只要功能定位相同,其他部分基本不需要变。

选型时的核心问题

接触任意新技术栈时,问自己这几个问题:

  1. 它解决什么问题? — 在系统的哪一层?
  2. 它替代什么? — 与已有组件的关系?
  3. 它的运维成本? — 谁能维护、出问题谁能修?
  4. 它的故障域? — 挂了影响范围多大?
  5. 它的退出成本? — 如果不合适,迁出去难不难?

能跑起来是一回事,出问题能排查、能演进、能替换是另一回事——后者才是技术选型的真正考验。

十、技术栈的演进规律

技术栈不是一成不变的——业务规模、团队能力、流量特点都在变化,技术栈也要跟着演进。常见演进路径:

技术栈随着问题规模从简单到分层演进

启动期       单机部署 + 单数据库 + 简单 Web 框架
成长期       负载均衡 + 多实例 + Redis 缓存 + CDN
扩张期       数据库主从 + 消息队列 + 监控告警 + 日志聚合
成熟期       微服务 + K8s + 完整可观测 + CI/CD
大型化       服务网格 + 多机房 + 分库分表 + 流量治理

每一步演进都要解决"业务真实痛点"——不要为了"看起来现代化"提前引入复杂度。Kubernetes 不是必需,微服务不是必需,服务网格更不是必需。架构演进的核心原则:业务驱动技术演进,而不是技术驱动架构升级