提示:本网站现在为维护调试状态

GraphQL vs REST:从 7 个维度深度对比

Choyeon
Choyeon
2026年9月19日 1 分钟阅读 408 阅读
710 字 2,123 字符 更新于 2026年11月8日
GraphQL vs REST:从 7 个维度深度对比
目录

GraphQL 常被宣传为 REST 的终结者,但实际两者各有适合场景。盲目选择 GraphQL 会带来 N+1 查询、复杂度爆炸、缓存失效等坑;只用 REST 又有过取/欠取问题。理性对比再做选择。

典型架构与复杂度防护

GraphQL 单端点接收查询,前端声明式指定字段结构,解决 REST 常见的 20 个接口拼数据或大接口返回 80% 不用字段的问题。但必须在网关层加上查询复杂度分析、字段级权限、深度限制。

import express, { Request, Response } from "express";
import { graphqlHTTP } from "express-graphql";
import { buildSchema, parse, visit, Kind } from "graphql";

const app = express();
app.use(express.json());

const schema = buildSchema(`
  type User { id: ID!; username: String!; orders(limit: Int = 10): [Order!]! }
  type Order { id: ID!; total: Float!; items(limit: Int = 20): [OrderItem!]! }
  type OrderItem { productId: ID!; qty: Int!; price: Float! }
  type Query { user(id: ID!): User; users(limit: Int = 20): [User!]! }
  schema { query: Query }
`);

class ComplexityGuard {
    private costs: Record<string, number> = { orders: 5, items: 2, users: 10 };
    private readonly MAX = 150;
    analyze(query: string): { total: number; exceeded: boolean } {
        const doc = parse(query); let total = 1;
        visit(doc, {
            Field: (node) => {
                const base = this.costs[node.name.value] || 1;
                const args = Object.fromEntries((node.arguments || []).map(a => [a.name.value, (a.value as any).value]));
                const mult = args.limit ? Math.ceil(Number(args.limit) / 10) : 1;
                total += base * mult;
            },
        });
        return { total, exceeded: total > this.MAX };
    }
}

const root = {
    user: ({ id }: { id: string }) => ({
        id, username: `u${id}`,
        orders: ({ limit = 10 }: any) => Array.from({ length: limit }, (_, i) => ({
            id: `o${i}`, total: 99.5 + i,
            items: ({ limit = 20 }: any) => Array.from({ length: limit }, (_, k) => ({ productId: `p${k}`, qty: k + 1, price: 9.9 })),
        })),
    }),
    users: ({ limit = 20 }: any) => Array.from({ length: limit }, (_, i) => root.user({ id: String(i + 1) })),
};

const guard = new ComplexityGuard();
app.get("/rest/users/:id", (req: Request, res: Response) => {
    res.json({ data: { id: req.params.id, username: `u${req.params.id}` }, _links: { orders: { href: `/rest/users/${req.params.id}/orders` } } });
});
app.use("/graphql", (req: Request, res: Response, next) => {
    const q = (req.body?.query) || (req.query.query as string) || "";
    const r = guard.analyze(q);
    if (r.exceeded) return res.status(400).json({ error: `Complexity ${r.total} exceeds cap 150` });
    res.setHeader("X-GraphQL-Complexity", String(r.total));
    next();
}, graphqlHTTP({ schema, rootValue: root, graphiql: process.env.NODE_ENV !== "production" }));

app.listen(3000, () => console.log("[compare] REST+GraphQL on :3000"));

七大维度横向对比

对比维度 REST (JSON:API风格) GraphQL 胜者
网络传输效率 多请求过取欠取 单请求精确字段POST不利CDN 简单REST赢/复杂视图GraphQL赢
前端开发体验 新字段等后端加接口 自助取字段+内省生成类型 GraphQL
后端演进成本 版本化管理/v1/v2 字段弃用平滑但resolver复杂度涨 REST
HTTP缓存 天然支持Get请求 需持久化查询ID+自定义层 REST
类型安全 需OpenAPI代码生成 Schema强类型+内省生成SDK GraphQL
安全风险 普通CRUD鉴权易做 深度/复杂度/批注入要防护 REST安全面更小
生态工具链 OpenAPI/Postman成熟 Apollo Studio/GraphiQL完善 打平

最佳实践

决策树:团队以 BFF 形态存在且前端迭代快 → GraphQL;微服务间调用或纯资源 CRUD → REST;混合架构:BFF 用 GraphQL 组合多个 REST 微服务是目前大厂主流方案。

X微博Telegram

本文作者

投票

你最希望 Rosetta 优先加入哪项功能?

社区投票(演示数据,可后台删除)

评论 (6)

0 / 3000
测试小瓢虫
测试小瓢虫2026年9月11日

好文!但是我觉得第三部分那个消息队列选型对比表有点偏向 Kafka 了,RocketMQ 在事务消息这块其实优势挺明显的。

自由撰稿人阿秋
自由撰稿人阿秋qiuwrites.blog2026年9月11日

建议加一下关于幂等性的讨论,现在的分布式系统里这个真的太重要了,很多坑都是没处理好幂等导致的。

东京留学僧
东京留学僧2026年9月11日

补充一点:实际使用中如果遇到 MySQL 的 8 小时超时问题,可以在连接串里加 autoReconnect=true 参数,虽然官方不推荐但挺好用的。

机器学习萌新
机器学习萌新2026年9月11日

有个小问题:你文中用的是 @Async 注解,这个默认用的是 SimpleAsyncTaskExecutor,生产环境是不是最好手动配一个线程池?

奶茶味程序媛
奶茶味程序媛2026年9月11日

代码示例里那个 SQL 查询是不是应该加个 LIMIT?不然数据量大的时候全表扫描会很慢哦。

咖啡与代码
咖啡与代码2026年9月10日

受益匪浅,感谢大佬分享!

相关文章

JWT 认证安全最佳实践 + OAuth2 vs SAML

JWT 认证安全最佳实践 + OAuth2 vs SAML

系统性归纳 JWT 常见安全漏洞防护:算法混淆攻击(none/RS256→HS256)、密钥爆破、KID注入、重放攻击防御,再从多个维度对比 OAuth2(授权码+PKCE)、OIDC、SAML 2.0 三种主流认证协议选型。

1 分钟阅读
Prompt Engineering 入门:Few-Shot + CoT + 结构化输出

Prompt Engineering 入门:Few-Shot + CoT + 结构化输出

系统入门 Prompt Engineering 三大核心技术:Few-Shot 示例学习注入专业领域风格、Chain-of-Thought (CoT) 思维链引导复杂推理、JSON Schema 强制结构化输出对接下游系统。附真实 prompt 模板和避坑指南。

1 分钟阅读
CQRS + Event Sourcing 架构模式解析

CQRS + Event Sourcing 架构模式解析

透彻解析两种高复杂度分布式架构模式:CQRS 读写模型分离实现查询极致性能、Event Sourcing 以事件作为唯一真相源实现全量审计与时间回溯,讨论一致性/快照/幂等难点与反模式。

1 分钟阅读
快速上手 FastAPI - 构建高性能 REST API

快速上手 FastAPI - 构建高性能 REST API

FastAPI 是现代 Python Web 框架中的佼佼者,基于类型提示自动生成文档、支持异步操作、性能媲美 Node.js。本文将通过实战项目带你从零构建一个完整的 CRUD API,涵盖路由定义、请求验证、依赖注入、数据库集成等核心特性,让你在 30 分钟内掌握 FastAPI 的精髓。

这篇文章需要访问密码 4 分钟阅读
Astro 静态站点深度:群岛架构 & 内容集合

Astro 静态站点深度:群岛架构 & 内容集合

深入理解 Astro 核心创新:群岛架构实现最小化 JS 注入,仅交互组件按需水合;内容集合提供类型安全的 Markdown/MDX 管理,构建零 JS 的高性能静态站点。

1 分钟阅读
测试金字塔:单元/集成/E2E 测试比例与落地

测试金字塔:单元/集成/E2E 测试比例与落地

系统解析测试金字塔架构:从底层单元测试(大量快速、Mock 隔离依赖)、中层集成测试(服务/数据库/消息协作真实交互)、顶层 E2E 测试(真实用户路径少量精测)的推荐比例 70% / 20% / 10%,附项目覆盖率指标与落地实践。

1 分钟阅读