使用sentinel实现熔断限流和降级。
服务雪崩
服务提供者不可用导致 服务调用的不可用,并将不可用现象放大
服务雪崩三个阶段
- 服务提供者不可用
- 硬件故障
- 程序bug
- 缓存击穿
- 用户大量请求
- 重试加大请求流量
- 用户重试
- 代码逻辑重试
- 服务调用者不可用
- 同步等待造成资源耗尽。
应对的策略
- 应用库容
- 增加机器数量
- 升级规格
- 流控 不至于让服务挂掉
- 限流
- 关闭重试
- 缓存
- 缓存预加载
- 服务降级 当前访问用户过多,请稍后重试
- 服务接口拒绝服务
- 页面拒绝服务
- 延迟持久化
- 随机拒绝
- 服务熔断 调用方调用都超时?保险丝
服务限流
shop\api\user-api\initialize\sentinel.go
1package initialize
2
3import (
4 sentinel "github.com/alibaba/sentinel-golang/api"
5 "github.com/alibaba/sentinel-golang/core/flow"
6 "go.uber.org/zap"
7
8 "github.com/jimyag/shop/api/user/global"
9)
10
11func InitSentinel() {
12 err := sentinel.InitDefault()
13 if err != nil {
14 global.Logger.Fatal("初始化 sentinel 失败 .....", zap.Error(err))
15 }
16
17 _, err = flow.LoadRules([]*flow.Rule{
18 {
19 Resource: "get-user-list",
20 TokenCalculateStrategy: flow.Direct,
21 ControlBehavior: flow.Reject,
22 Threshold: 100, // 通过几个
23 StatIntervalInMs: 1, // 多少秒
24 },
25 })
26 if err != nil {
27 global.Logger.Fatal("加载 sentinel 配置失败....", zap.Error(err))
28 }
29 global.Logger.Info("加载 sentinel 配置成功....", zap.Error(err))
30}
shop\api\user-api\api\user.go
1func GetUserList(ctx *gin.Context) {
2 pageNum := ctx.DefaultQuery("pageNum", "1")
3 pageNumInt, err := strconv.Atoi(pageNum)
4 if err != nil {
5 global.Logger.Info("pageNum invalid")
6 }
7 pageSize := ctx.DefaultQuery("pageSize", "5")
8 pageSizeInt, err := strconv.Atoi(pageSize)
9 if err != nil {
10 global.Logger.Info("pageNum invalid")
11 }
12 // 增加的开始
13 e, b := sentinel.Entry("get-user-list", sentinel.WithTrafficType(base.Inbound))
14 if b != nil {
15 // block le
16 response.FailWithMsg("请求频率过快,请稍后重试", ctx)
17 return
18 }
19 // 增加的结束
20 rsp, err := global.UserSrvClient.GetUserList(ctx, &proto.PageIngo{
21 PageNum: uint32(pageNumInt),
22 PageSize: uint32(pageSizeInt),
23 })
24 if err != nil {
25 handle_grpc_error.HandleGrpcErrorToHttp(err, ctx)
26 return
27 }
28 // 增加的开始
29 e.Exit()
30 // 增加的结束
31 // ....
32}