【转】【Sentinel】sentinel 集成 apollo 最佳实践

原文:https://www.cnblogs.com/kiwifly/p/11569190.html

【Sentinel】sentinel 集成 apollo 最佳实践

sentinel

前言

在 sentinel 的控制台设置的规则信息默认都是存在内存当中的。所以无论你是重启了 sentinel 的客户端还是 sentinel 的控制台。你所设置的规则都会丢失。如果想要 sentinel 在线上环境使用,要么花钱用阿里云上的付费版本,要么自己去实现规则的持久化,如果你或你所在的公司不差钱,那么关掉这篇文章,直接用付费版吧,省掉了一大堆坑要踩。或者你是一个特立独行的人,那么我们接着往下说。
  首先说一下写这篇文章的原因,因为真得在与 apllo 集成时,踩坑踩到怀疑人生。另一点是,找了一大堆关于集成的 apollo 的文章,都清一色的都是仿照官方给的限流规则的 DEMO 做的。 但是 sentinel 规则还有熔断规则、参数限流、系统限流、黑白名单等很多规则,每个规则还有细节上的不一致,这些都没有提,还有一些客户端的坑就更没有了。踩了这么多坑,有了一点心得与体会,梳理与此,希望能帮助到读者。

拉取 sentinel 控制台源码进行修改

因为修改内容过多,本文不会详述,下面的截图是所有修改内容,并且因为写这篇文章时,1.7版本在 master 开发,有大量快照版本。所以是切到当前稳定的 1.6 分支进行修改的。我已经 fork sentinel 到我的 github,下面是修改的内容 地址

修改点1:实现所有规则的拉取与推送接口

添加与实现了所有的规则的 Provider 与 Publisher 的配置拉取的与推送。

修改点2:修改控制台使用的规则操作 api

规则在控制台的操作 controller 进行大量改造。

修改点3:修改 xxEntity

最后一点也是最坑的修改了大量的 xxEntity 类,这些类是规则的实体类,本身没什么,源码是直接 json 化保存的,但是用于客户端集成的 spring-cloud-alibaba 使用了 json 校验,如果 apollo 保存的 json 与客户端的实体类有一丁点不一样就报 convert 0 rules but there are 1 rules from datasource . RuleCLass: FlowRule 。是不是觉得很摸不着头脑,这报错跟 json 格式转换错误有什么,下面是 spring-cloud-alibaba json 转换的代码。

写这段代码的老哥,把这个异常吃了,并补上了一个 // won't be happen 的注释,你能理解我当时被这个报错坑的死去活来,后来发现是这里的问题吗?后来在 github 上找到两个同样的问题问题1问题2,按照方法把 xxEntity 中用不到的字段全部加上 @JSONField(serialize = false) 解决。

修改点4:抽离配置使得可以在启动的时传入

添加的配置在下面

使用修改的控制台版本

  1. 你可以fork sentinel 官方代码按上述的自行修改,然后打包
  2. 你可以拉取我 fork 的 sentinel 代码下来直接打包
  3. 你可以使用我已经打好的包 地址

自定义配置

配置名称 是否必填 默认值 作用
env DEV 指定 apollo 使用的环境
app.id sentinel-apollo 指定保存 sentinel 规则的 apollo 应用 ID
cluster.name default 指定保存 sentinel 使用的 apollo 集群
namespace.name application 指定保存 sentinel 使用的 apollo 命名空间
modify.user apollo 控制台显示的修改人账号,此账号务必要有此应用的权限
modify.comment modify by sentinel-dashboard apollo 控制台显示的修改备注
release.user apollo 控制台显示的发布人账号,此账号务必要有此应用的权限
release.comment release by sentinel-dashboard apollo 控制台显示的发布备注
apollo.portal.url apollo 控制台的地址
apollo.application.token 指定保存 sentinel 规则的 apollo 应用 openapi 的 token
authority.key.suffix authority 认证规则保存在 apollo 中的 key 的后缀
degrade.key.suffix degrade 熔断规则保存在 apollo 中的 key 的后缀
flow.key.suffix flow 限流规则保存在 apollo 中的 key 的后缀
param.key.suffix param_flow 参数限流规则保存在 apollo 中的 key 的后缀
system.key.suffix system 系统限流规则保存在 apollo 中的 key 的后缀
auth.username sentinel sentinel 控制台的登录用户名
auth.password sentinel sentinel 控制台的登录密码
server.port 8080 sentinel 控制台的启动端口

Apollo 配置

创建用于保存 sentinel 的项目

  1. 点击创建项目按钮


  2. 输入项目信息


    1. 应用 ID 对应 上面表格中的 app.id
    2. 应用负责人 对应 上面表格中的 modify.userrelease.user
  3. 创建一个公共命名空间

    1. 点击右下角添加 Namespace 按钮


    2. 创建 Namespace


      1. 名称对应上面表格中的 namespace.name,注意名称是要包含部门名的,这里脱敏了
      2. 类型一定要选择 public ,原因后面会说
  4. 发布 Namespace


    1. 私有的空间是不能被继承的,application 没有用,可以删除
      1. 这里的用意是我们独立出一个单独的用于保存规则的 apollo 应用,因为是公共的,所以其它apollo 应用可以继承,这样对于已经集成 apollo 的项目来说,改动最小
      2. 注意红色的提示,我们建的公共空间要首先发布一次,否则 api 无法访问到
  5. 创建此项目的开放平台授权

    1. 点击右上角的开放平台授权管理

    2. 创建应用


      1. 第三方应用 ID 就是你上面创建的项目的 appId
      2. 第三方应用名称 随便写
    3. 赋权


      1. token 你点击创建应用后自动生成的
      2. 被管理的 Appid 就是你上面创建的项目的 appId
      3. 授权类型 一定要选 App

spring boot 集成 sentinel

源码地址

引入依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>0.9.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-apollo</artifactId>
            <version>1.5.2</version>
        </dependency>

测试 controller

package cn.coder4j.study.example.sentinel;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author buhao
 * @version TestController.java, v 0.1 2019-09-19 20:53 buhao
 */
@RequestMapping("/test")
@Controller
public class TestController {

    /**
     * 没有注解通过自适应的限流
     * @return
     */
    @GetMapping("/flowRule")
    @ResponseBody
    public String flowRule(){
        return "success";
    }

    /**
     * 通过手动注解的限流
     * @return
     */
    @GetMapping("/flowRuleWithAnno")
    @ResponseBody
    @SentinelResource("flowRuleWithAnno")
    public String flowRuleWithAnno(){
        return "success";
    }

    /**
     * 参数限流规则测试
     * @param param
     * @return
     */
    @GetMapping("/paramFlowRule")
    @ResponseBody
    @SentinelResource("paramFlowRule")
    public String paramFlowRule(String param){
        return "success";
    }

    /**
     * 熔断规则测试
     * @return
     */
    @GetMapping("/degradeRule")
    @ResponseBody
    @SentinelResource("degradeRule")
    public String degradeRule(){
        throw new RuntimeException("服务器异常");
    }
}

配置 application.yml

apollo:
  bootstrap:
    enabled: true # 开启 apollo
  meta: xxx       # 指定 apollo 注册地址
app:
  id: sentinel-apollo  # 指定规则项目在 apollo 的app.id,要与 sentinel 控制台启动参数一致
spring:
  application:
    name: study-sentinel-example  # 应用名称,不同项目要唯一,会把他做为规则 Key 的前缀
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8989  # sentinel 控制台的地址
      datasource:
        ds1:
          apollo:
            namespace-name: {部门名}.sentinel-rule  # 保存规则的 apollo 应用的公共 namespace, 要与 sentinel 控制台启动参数一致
            rule-type: flow   # 指定该数据源是限流规则
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds1.apollo.rule-type} # 指定该规则在 apollo 应用中 key 名称
        ds2:
          apollo:
            namespace-name: {部门名}.sentinel-rule
            rule-type: degrade # 指定该数据源是熔断规则
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds2.apollo.rule-type} # 指定该规则在 apollo 应用中 key 名称
        ds3:
          apollo:
            namespace-name: {部门名}.sentinel-rule
            rule-type: param_flow # 指定该数据源是参数限流规则
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds3.apollo.rule-type} # 指定该规则在 apollo 应用中 key 名称
        ds4:
          apollo:
            namespace-name: {部门名}.sentinel-rule
            rule-type: system  # 指定该数据源是系统限流规则
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds4.apollo.rule-type} # 指定该规则在 apollo 应用中 key 名称
        ds5:
          apollo:
            namespace-name: {部门名}.sentinel-rule
            rule-type: authority # 指定该数据源是认证限流(黑白名单)规则
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds5.apollo.rule-type} # 指定该规则在 apollo 应用中 key 名称

sentinel 控制台配置

  1. 第一次启动时 sentinel 是没有应用数据,只要请求几次你应用的接口就可以了


  2. 请求之后可以看到我们的应用在右侧列表了


  3. 首先点击簇点监控,如果是空白的话说明,接口还没有被请求过,通过上面提供的 jmeter 脚本,可以快速访问所有接口,访问后如下图所示


    1. 可以看到除了我们手动通过注解定义的资源名,还多了一些是通过我们的 controller 路径的资源名,这些都是我们客户端集成 spring-cloud-starter-alibaba-sentinel 包后,自动适配的。这两种其实在使用上有区别的
      1. 自动适配的限流后会返回 Blocked by Sentinel (flow limiting)
      2. 通过注解的是会抛出 UndeclaredThrowableException 异常,我们可以通过 文章 说的方法转成我们想的限流异常处理。
    2. 右边的操作就是添加各种规则,这里修改后会实时同步到客户端并同步保存到 apollo

jmeter 配置

jmeter 是用于测试与验证规则使用的,因为可以设置线程数,所以可以很好的测试限流情况。测试脚本下载

  1. 线程组要把线程设置成 100,方便后面的统计,另外为了在一秒内执行完,Ramp-Up 时间设为0


  2. 请求默认值就是填写你本地的启的测试项目的地址


  3. xx 规则填写测试接口地址,参数限流因为要做对照实验所以写了两个


  4. 查看结果树可以看到你每次请求的内容与结果


  5. 可以看到上张图片内有红色的有绿色的,红色说明断言失败,绿色说明断言成功,断言的内容就是包含 success


  6. 聚合统计,这个可以统计出100个线程请求后的总体结果,我们只要看 Error% 的失败率就可以了。图中可以看到除了熔断限流,其它限流失败率是 0


测试步骤

  1. 在簇点链路中找到 /test/flowRule,并点击流控按钮

  2. 单机阈值填入 10,点击新增


  3. 新增后会跳转到流程规则页面


  4. 运行jemter,可以看到失败率为90%,这代表你的限流成功了


    1. 上面说了失败是因为断言没有成功,也就是说没有返回 success,那他现在返回的是什么呢?

    2. 察看结果树,随便找一条红包的记录,看响应数量


    3. 可以看到返回的是 "Blocked by Sentinel (flow limiting)",这个就是集成后配置的限流页面的返回值,可以通过 spring.cloud.sentinel.servlet.block-page 指定成你自己的页面

  5. 另外打开 apollo 可以看到,多了一个规则,这就是你刚刚添加的限流规则


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容