总结spring-cloud-alibaba的基础使用方法

下载安装sentinel-dashboard

下载地址 文档地址

下载1.6.0的jar包,在centos7服务器上启动

java -Dserver.port=9001 -jar sentinel-dashboard-1.6.0.jar

# 后台启动
nohup java -Dserver.port=9001 -jar sentinel-dashboard-1.6.0.jar >> app.log 2>&1 &

# 常用java -jar启动参数
-Dsentinel.dashboard.auth.username=sentinel
-Dsentinel.dashboard.auth.password=sentinel
-Dserver.servlet.session.timeout=7200  # 单位s

打开http://192.168.237.128:9001使用sentinel/sentinel登陆

springcloud服务接入sentinel

应用接入

测试项目

pom依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--服务发现依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    <!--sentinel依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

入口类就是普通的springboot入口类,添加@EnableDiscoveryClient服务发现注解

@EnableDiscoveryClient
@SpringBootApplication
public class SentinelRateLimitApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinelRateLimitApplication.class,args);
    }
}

controller就是普通的controller,没有任何特殊的地方

@RestController
public class HiController {
    @GetMapping("/hi")
    public String hi(){
        return "hi world";
    }
}

配置文件中需要指定sentinel的地址

spring.application.name=sentinel-rate-limiting
server.port=8005
# sentinel地址
spring.cloud.sentinel.transport.dashboard=192.168.237.128:9001
# nacos注册中心地址
spring.cloud.nacos.discovery.server-addr=192.168.237.128:8848

测试

启动项目springcloud.alibaba.sentinel.rate-limit,要保证这个项目和sentinel-dashboard之间可以互相访问。访问http://192.168.237.128:8005/hi服务接口,观察sentinel-dashboar实时流量监控http://192.168.237.128:9001/#/dashboard/metric/sentinel-rate-limiting

接口级别限流

在sentinel控制台左侧菜单选择“簇点链路”菜单,可以看到访问的接口路径/hi,右侧有“流控”、“降级”、“热点”、“授权”4个按钮,点击“流控”可以针对接口设置QPS限制。

默认情况下,设置的限流策略存储在内存,如果重启sentinel服务器,这些规则就消失了。sentinel有4中存储规则的方式:

  • 文件
  • zookeeper
  • apollo
  • nacos

nacos存储限流规则

测试项目

改造springcloud应用

pom添加nacos存储依赖

<!--sentinel使用nacos存储规则时需要的nacos依赖-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.5.2</version>
</dependency>

本地配置文件添加配置

# sentinel使用nacos存储规则信息
spring.cloud.sentinel.datasource.ds.nacos.server-addr=192.168.237.128:8848
spring.cloud.sentinel.datasource.ds.nacos.dataId=${spring.application.name}-sentinel
spring.cloud.sentinel.datasource.ds.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds.nacos.rule-type=flow

在nacos配置中心添加配置

上一步配置文件中指定了使用dataId=${spring.application.name}-sentinel的配置来存储限流规则,我们打开nacos配置中心http://192.168.237.128:8848/nacos,使用nacos/nacos登陆,在配置中心默认public命名空间下面,添加配置,Data ID=sentinel-rate-limiting-sentinel不带后缀,Group默认,配置格式Json,配置内容如下:

[
    {
        "resource": "/hi",
        "limitApp": "default",
        "grade": 1,
        "count": 2,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

配置项说明:

  • resource:资源名,即限流规则的作用对象
  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
  • count:限流阈值
  • strategy:调用关系限流策略
  • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
  • clusterMode:是否为集群模式

这个配置就跟上一个章节直接在sentinel控制台“簇点链路”手动添加“流控”这种方式是一样的效果,都是限制/hi接口的QPS=2。这样nacos中修改了配置也会即时同步到sentinel,即使服务重启也不会丢失。但是反过来如果修改sentinel中的规则不会同步回nacos配置中心,如果想实现sentinel控制台修改限流策略也同步到nacos配置中心的话,需要对sentinel-dashboard服务器端源码做扩展,参考翟永超这篇教程

测试

1.启动项目springcloud.alibaba.sentinel.rate-limit,要保证这个项目和sentinel-dashboard之间可以互相访问。观察一下输出日志,确定nacos中配置的限流规则是否被加载

o.s.c.a.s.c.SentinelDataSourceHandler    : [Sentinel Starter] DataSource ds-sentinel-nacos-datasource load 1 FlowRule

2.访问http://192.168.237.128:8005/hi,观察sentinel控制台http://192.168.237.128:9001流控规则,会发现nacos中的流控配置已经同步到sentinel

方法级别限流、熔断降级

测试项目

应用中使用AOP进行方法级别的拦截

方法级别的限流和熔断降级需要使用到SentinelResourceAspect这个切面,所以先注入这个切面

/**
 * 用于方法级别的流控、熔断降级
 * @return
 */
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
    return new SentinelResourceAspect();
}

添加一个内部service类,用来模拟方法级别的限流和降级,并创建controller来调用这个service,配置什么的不用动。

@Slf4j
@Service
public class HelloService {

    //模拟限流处理
    @SentinelResource(value = "helloServiceMethod1", blockHandler = "hello1BlockHandler")
    public String hello1(String name){
        return "hello"+name;
    }
    //被限流之后的动作
    public String hello1BlockHandler(String name, BlockException blockException){
        log.error("hello1BlockedException, name="+name,blockException);
        return "oops, blockException!!!";
    }



    //模拟发生异常后降级处理
    @SentinelResource(value = "helloServiceMethod2", fallback = "hello2Fallback")
    public String hello2(String name){
        throw new RuntimeException("发生异常");
    }
    //被降级之后的动作
    public String hello2Fallback(String name){
        log.error("hello2Fallback, name="+name);
        return "oops, fallback!!!";
    }
}




/**
 * 测试方法级别的限流和熔断降级
 */
@Slf4j
@RestController
public class HelloController {
    @Autowired
    HelloService helloService;

    @GetMapping("/hello1")
    public String hello1(){
        return helloService.hello1("zhangsan "+ new Date());
    }

    @GetMapping("/hello2")
    public String hello2(){
        return helloService.hello2("lisi "+ new Date());
    }
}

测试

1.重启springcloud.alibaba.sentinel.rate-limit应用,访问http://192.168.237.128:8005/hello1,观察sentinel-dashboard控制台http://192.168.237.128:9001簇点链路,会发现多了刚才HelloService中的方法helloServiceMethod1,可以在上面添加限流和降级的规则。同样的这个规则默认是保存在应用内存的,如果应用重启规则就消失了。需要修改sentinal-dashboard源码支持规则同步到nacos配置中心,参考翟永超这篇教程

2.在sentinel-dashboard中给helloServiceMethod1方法添加一个限流规则,设置QPS=1,连续访问http://192.168.237.128:8005/hello1,会发现被限流之后会直接返回限流消息,而不是429错误,blockHandler方法起作用了。

3.访问http://192.168.237.128:8005/hello2方法,直接抛出500异常,观察sentinel-dashboard上的簇点链路,会发现多了helloServiceMethod2

4.给helloServiceMethod2添加一个降级规则,设置降级策略=异常比例,异常比例=0.5,时间窗口=5,代表如果服务发生异常的比例超过50%了就自动降级,返回fallback信息,5s之后才会恢复。持续访问http://192.168.237.128:8005/hello2会发现开始返回500错误页面,后来自动被降级返回fallback信息,过5s之后再次访问,又恢复了500错误页面。

结合sentinel使用feign客户端

服务提供方

示例项目就是一个普通的springcloud服务,注册到nacos,提供的接口里面我们模拟一下超时和异常情况。

@Slf4j
@RestController
public class HiController {
    @Value("${server.port}")
    String port;

    private static Random random = new Random();

    @GetMapping("/hi")
    public String hi(@RequestParam String name) throws InterruptedException {
        log.info("invoked name = " + name);

        //模拟随机超时和异常
        int sleepSecs=random.nextInt(5);

        log.info("本次调用超时时间:{}", sleepSecs);

        if(sleepSecs==3){
            throw new RuntimeException("出现问题了,赶紧查一下");
        }

        TimeUnit.SECONDS.sleep(sleepSecs);

        return String.format("hi %s, i'm from port %s",name,port);
    }
}

服务调用方

示例项目开启feign功能,使用sentinel组件来实现熔断降级功能,当调用的服务出现超时或者是异常的情况,执行指定的fallback方法。这里仅仅使用了sentinel的组件,但是不会去连接sentinel-dashboard,熔断降级通过项目中的配置文件或者java代码的配置方式来实现,跟标准的springcloud中的feign的使用方式一样。

pom依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!--使用feign的依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <!--sentinel依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
</dependencies>

入口类开启feign客户端扫描

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class SentinelServiceHiClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinelServiceHiClientApplication.class,args);
    }
}

创建feign客户端代理类,以及对应的fallback实现类

@FeignClient(value = "sentinel-service-hi", fallback = ServiceHiFallback.class)
public interface ServiceHi {
    @GetMapping("/hi")
    String hi(@RequestParam(name = "name") String name);
}


@Component
public class ServiceHiFallback implements ServiceHi {
    @Override
    public String hi(String name) {
        return "Oops, this is a fallback message!!!";
    }
}

controller中使用feign客户端来调用服务

@Slf4j
@RestController
public class HiController {

    @Autowired
    ServiceHi serviceHi;

    @GetMapping("/hi")
    public String hi(){
        return serviceHi.hi("john");
    }
}

配置文件中需要显示的开启feign客户端的sentinel熔断降级功能,否则不起效果。负载策略,超时时间,重试次数等都跟普通springcloud中使用feign客户端的配置一样

spring.application.name=sentinel-service-hi-client
server.port=8863
# 指定nacos注册中心地址
spring.cloud.nacos.discovery.server-addr=192.168.237.128:8848

# 当feign使用sentinel来进行熔断降级的时候,这个配置很重要,必须打开
# 不需要设置sentinel-dashboard地址,只需要依赖pom组件即可
feign.sentinel.enabled=true

# 以配置的方式来定义ribbon的负载均衡策略,超时时间等,这个是为某个服务单独配置的
# 修改服务的负载均衡策略
sentinel-service-hi.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.BestAvailableRule
# 请求连接超时时间
sentinel-service-hi.ribbon.ConnectTimeout=3000
# 请求处理超时时间
sentinel-service-hi.ribbon.ReadTimeout=3000
# 对所有请求都进行重试,false代表只对GET请求重试,对于写数据接口必须做幂等才行,谨慎配置!
sentinel-service-hi.ribbon.OkToRetryOnAllOperations=false
# 切换实例的重试次数,不包括首次调用
sentinel-service-hi.ribbon.MaxAutoRetriesNextServer=0
# 对当前实例的重试次数,不包括首次调用
sentinel-service-hi.ribbon.MaxAutoRetries=1

测试

1.开启nacos

2.开启服务提供方springcloud.alibaba.sentinel.service-hi

3.开启服务调用方springcloud.alibaba.sentinel.service-hi-client

4.通过http://localhost:8863/hi调用服务,服务随机超时和异常的时候,可以看到fallback内容

总结

  • springcloud项目添加sentinel组件后,默认支持针对接口进行限流、熔断降级功能,sentinel-dashboard上提供可视化支持,流控规则可以配置在nacos配置中心

  • 项目中同时也支持AOP的方式进行方法级别的限流、熔断降级功能,需要添加sentinel组件,sentinel-dashboard上提供可视化支持,流控规则可以配置在nacos配置中心

  • 使用feign客户端加上sentinel的组件也可以实现服务调用之间的接口级别熔断降级功能

参考

spring-cloud-alibaba-wiki

spring-cloud-alibaba-examples

Spring-Cloud-Alibaba 系列

阿里云ahas