1.RESTful API 基础概念
REST 基本定义
1.REST(Representational State Transfer)是一种基于 HTTP 的软件架构风格,强调 “资源”(Resource)和 “状态转移”。 2.核心原则:资源定位(URI 标识资源)、统一接口(HTTP 方法操作资源)、无状态(Stateless)、可缓存(Cacheable)等。
资源与 URI 设计
1.资源是 REST 的核心,如 /users(用户集合)、/users/1(单个用户)。 2.URI 设计规范: 2.1 用名词表示资源(避免动词),如 GET /orders(获取订单列表)、POST /orders(创建订单)。 2.2 使用复数形式表示集合资源(如 /users 而非 /user)。 2.3 版本化:如 api/v1/users 或通过请求头 Accept: application/vnd.app.v1+json。 2.4 避免层级过深,合理使用路径参数(如 /users/{id}/orders)。
HTTP 方法与语义
GET:获取资源(幂等)。 POST:创建资源(非幂等)。 PUT:更新资源(全量更新,幂等)。 PATCH:部分更新资源(幂等性需保证)。 DELETE:删除资源(幂等)。 面试常问:PUT 和 PATCH 的区别、如何设计幂等的接口。
维度 PUT PATCH 更新方式 完全替换资源(客户端需提供完整数据) 部分更新资源(仅发送需修改的字段) 幂等性 ✅ 幂等(多次调用结果一致) ❌ 非幂等(多次调用可能导致不一致) 请求数据量 较大(需传输完整资源) 较小(仅传输变更字段) 典型场景 整体覆盖资源(如替换用户全部信息) 增量更新(如仅修改邮箱或订单状态) 资源影响 未包含字段会被重置为默认值(如null) 未包含字段保持原值不变 数据库操作类比 UPDATE table SET col1=val1, col2=val2
UPDATE table SET col1=val
幂等接口设计方法 1. 唯一请求标识(Token/ID) 客户端生成唯一标识(如 UUID)放入请求头(如 Idempotency-Key)。 服务端缓存该标识与结果,重复请求直接返回缓存响应 2. 乐观锁(版本控制) 资源增加版本号字段(如 version)。 更新时校验版本号匹配性 3.数据库唯一索引 对业务唯一字段(如订单号)建唯一索引。 重复插入时捕获 DuplicateKeyException 并返回幂等响应 4.分布式锁 高并发场景下使用 Redis 或 ZooKeeper 分布式锁,确保单次请求处理
状态码(Status Codes)
2xx(成功):如 200(OK)、201(Created,创建资源后返回)。 3xx(重定向):如 301(永久重定向)。 4xx(客户端错误):如 400(请求参数错误)、401(未认证)、403(禁止访问)、404(资源不存在)。 5xx(服务器错误):如 500(内部错误)。 面试常问:如何自定义状态码含义、401 和 403 的区别。
维度 401 Unauthorized 403 Forbidden 核心含义 未提供有效身份认证凭据(需登录) 身份认证通过,但权限不足拒绝访问 触发场景 • 未提交用户名/密码或 Token
• 凭证失效(如过期 Token)• 用户角色无权访问资源(如普通用户访问管理员接口)
• IP 或区域受限响应行为 返回 WWW-Authenticate
头,指示认证方式(如Basic
)无认证引导信息,直接拒绝 错误本质 认证问题(Authentication) 授权问题(Authorization) 典型修复操作 重新登录获取有效凭证 联系管理员提升权限或调整资源策略
2.什么是 Protobuf?
Protobuf(Protocol Buffers)是 Google 开发的高效数据序列化协议,用于结构化数据的序列化(编码)和反序列化(解码),类似 JSON/XML,但具有以下核心优势:
体积小:二进制格式,序列化后数据量通常比 JSON 小 3-10 倍。 速度快:解析效率比 JSON 高 20-100 倍,适合高并发、低延迟场景。 跨语言:支持 Java、C++、Python、Go 等多种语言,且接口定义一次可多语言共享。 强类型约束:通过 .proto 文件定义数据结构,编译时生成强类型代码,避免运行时类型错误。
3.面试中常见的 Protobuf 问题
1. 基础概念与原理
Protobuf 与 JSON/XML 的区别?
Protobuf 是二进制格式,JSON/XML 是文本格式;Protobuf 需编译生成代码,JSON/XML 解析灵活但性能较低。 场景对比:Protobuf 适合对性能、体积敏感的场景(如 RPC 通信、日志存储),JSON 适合前端交互或动态数据。
Protobuf 的核心组件有哪些?
.proto 文件:定义消息结构(字段类型、编号)。 protoc 编译器:将 .proto 编译为各语言的代码(如 Java 类)。 运行时库:提供序列化、反序列化接口(如 Java 中的 GeneratedMessage)。
Protobuf 如何实现版本兼容?
新增字段时需使用 optional 或 default 值,避免旧版本解析失败。 字段编号不可修改(修改会导致协议不兼容),删除字段需标记为 reserved。
2. 性能与使用场景
Protobuf 的性能优势体现在哪里?
二进制编码无冗余字段名(如 JSON 中的键名),空间利用率高。 解析时无需动态类型转换(如 JSON 的字符串转数字),直接按二进制结构读取。
哪些场景适合用 Protobuf?
RPC 框架(如 gRPC)、微服务通信、分布式系统数据传输。 日志存储、配置文件(需高效读写)。 移动端通信(减少流量消耗)
- 3.面试高频问题总结
Protobuf 相比 JSON 的核心优势?(体积、性能、类型安全) 如何处理 Protobuf 协议的版本升级?(字段编号、reserved 关键字、默认值) 在 Java 中,Protobuf 生成的代码结构是怎样的?(Builder 模式、序列化方法) Protobuf 中的 repeated 和 map 字段在 Java 中对应什么类型?(List、Map) Protobuf 如何实现跨语言通信?(统一的 .proto 定义和编译器)
4.gRPC 基础概念
gRPC 是 Google 开源的高性能 RPC 框架,基于 HTTP/2 和 Protobuf 实现,主要特点:
高性能:HTTP/2 二进制分帧、多路复用,传输效率高于 HTTP/1.1。 强类型接口:通过 .proto 文件定义服务接口和消息结构,编译后生成强类型代码。 多语言支持:支持 Java、Python、Go、C++ 等十多种语言,自动生成客户端和服务端代码。 流式通信:支持双向流式传输(Bidirectional Streaming),适合实时数据传输
面试常见问题
gRPC 与 REST 的区别是什么? gRPC 基于 HTTP/2 和 Protobuf,性能更高、二进制格式更紧凑; REST 基于 HTTP/1.1 和 JSON/XML,更灵活但性能较低。 gRPC 适合服务间通信; REST 适合 B2C 接口(如 Web API)
模式 请求流 响应流 适用场景 性能优势 一元 RPC ❌ ❌ 简单请求响应 低延迟 服务器流式 ❌ ✅ 服务端推送/大数据分块 减少客户端轮询 客户端流式 ✅ ❌ 客户端上传/批量处理 减少连接开销 双向流式 ✅ ✅ 实时双向通信 全双工高效复用连接 gRPC 为什么选择 HTTP/2? HTTP/2 支持二进制分帧、多路复用(同一连接并行处理多个请求)、头部压缩,解决了 HTTP/1.1 的队头阻塞问题。
特性 HTTP/2 优势 gRPC 受益场景 连接效率 单连接多路复用 vs. 多连接串行 减少微服务间 TCP 握手开销 数据传输 二进制分帧 vs. 文本传输 高效传输 Protobuf 二进制数据 头部开销 HPACK 压缩 vs. 冗余文本头部 高频调用时降低带宽占用 gRPC 如何与 Spring Boot 集成? 使用 grpc-spring-boot-starter 简化配置。 通过 @GrpcService 注解服务实现类,@GrpcClient 注入客户端。
什么是 gRPC Gateway? 将 gRPC 服务转换为 RESTful API 的工具,允许前端通过 HTTP/JSON 调用 gRPC 服务,适合混合架构。