Appearance
能力明细
高并发能力
- 限流(令牌桶、漏桶、滑动窗口)
- 高并发缓存设计(Redis 缓存穿透/击穿/雪崩)
- MQ 解耦削峰(Kafka / RabbitMQ)
- goroutine 生命周期、调度、泄露排查
- GMP 模型、队列化 worker、负载均衡策略
稳定性
- 熔断、降级、限流的具体策略
- 分布式链路追踪(trace id、context 透传)
- pprof 性能分析(CPU、mem、阻塞、goroutine)
- Prometheus 指标 + Grafana 告警
- 海量日志可观测性(ELK / Loki)
高可用设计
- 多副本部署、无状态服务
- 健康检查 + 重试 + 超时
- 避免单点(db、redis、mq)
- 数据隔离(冷热数据分离、读写分离、分库分表)
- 灾备与回滚方案
缓存体系
- Redis 缓存模型设计
- 本地缓存 + 分布式缓存协同
- 加锁防击穿
- BigKey、热 Key 检测与应对
- Redis 持久化、LRU 策略、集群模式
网络 IO & 性能调优
- goroutine 泄露检测
- GC 调优、逃逸分析、内存池
- epoll + Go netpoll 模型理解
- 大对象、零拷贝、复用缓冲区
限流、熔断和降级
限流是入口,熔断是调用链,降级是兜底输出。
限流:防止自己的服务被流量冲死。 熔断:防止被别人“拖死”。 降级:别人挂了之后,我要怎么给用户一个“兜底结果”。
限流:控制入口流量
- 令牌桶(
golang.org/x/time/rate)
go
limiter := rate.NewLimiter(rate.Limit(100), 200) // 每秒 100 请求、最多突发 200
if limiter.Allow() {
handleRequest()
} else {
return errors.New("too many requests")
}- goroutine 并发数限流,limitChan
- redis 限流;分布式限流、滑动窗口
- Nginx 限流 / 网关限流
熔断:保护自己不被下游“慢 / 抖动 / 爆炸”拖死
- gobreaker
go
cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "userService",
MaxRequests: 3, // Half-Open 放行数量
})
result, err := cb.Execute(func() (interface{}, error) {
return callUserService()
})- 实现简单熔断器:三态模型 + 失败率统计
- 结合超时控制 context
go
ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
defer cancel()
req, err := client.Do(ctx)降级:即使依赖挂了,也要正常返回(兜底);熔断之后你要返回什么
- 返回默认值
- 走本地缓存 or Redis
- 关闭非关键功能,例如保留支付服务,暂时关闭评论和点赞服务的入口
- 静态化页面
- 队列降级
| 策略 | 目的 | Go 常用实现 |
|---|---|---|
| 限流 | 控制 QPS / 并发 | rate.Limiter、semaphore、Redis 限流、Nginx |
| 熔断 | 防下游异常拖死 | gobreaker、Hystrix-go、自写失败率状态机 |
| 降级 | 下游挂掉时兜底 | 默认值、本地缓存、关闭功能、静态化、队列 |
分布式链路追踪
- trace_id 和 span_id 的区别:trace_id 标识一次完整请求,span_id 则是链路中的一个步骤
- 在一个完整请求链里,每个服务、每个关键步骤都会生成独立的 span。span_id 是唯一的,parent_span_id 用来构建树结构。想知道哪个 span 来自哪个服务,可以从 span 的 metadata 中查看 service.name 字段
- trace_id 统一,span 分段,这样才能在 Jaeger / Zipkin 中正确展示链路拓扑和性能瓶颈