SpringCloudAlibaba简单运用

SpringCloudAlibaba简单运用

这篇文章就是简单介绍一下用SpringCloudAlibaba如何搭建一个微服务项目

项目基础搭建

1.父项目搭建

  • 导入依赖即可,父项目不需要有代码,只需要提供子类会用到的依赖
    <parent>
        <groupId> org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
        <spring-boot.version>2.2.5.RELEASE</spring-boot.version>
        <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
        <mysql.version>5.1.47</mysql.version>
        <mybatis.version>2.1.1</mybatis.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- springCloud-alibaba -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- mysql驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

2.搭建公共模块,可以放一些公用的domain

3.User服务搭建

  • user-server需要注册进Nacos中
  • 第一步:导入依赖
    <dependencies>
        <!--nacos客户端依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringBootWeb依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--公共模块依赖-->
        <dependency>
            <groupId>cn.lion</groupId>
            <artifactId>common-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
  • 第二步:编写启动类
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("cn.lion.mapper")
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class,args);
    }
}
  • 第三步:编写配置文件
server:
  port: 10010
spring:
  application:
    name: user-server # 应用名称
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_test?useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 指定nacos注册中心地址

  • 第四步:启动测试,在nacos注册中心进行查看

4.Order服务搭建

  • order-server需要注册进Nacos中
  • 第一步:导入依赖
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!--nacos客户端依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringBootWeb依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入OpenFeign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--公共模块依赖-->
        <dependency>
            <groupId>cn.lion</groupId>
            <artifactId>common-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--sentinel依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
  • 第二步:创建启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@MapperScan("cn.lion.mapper")
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class,args);
    }
}

  • 第三步:编写配置文件
server:
  port: 10000
spring:
  application:
    name: order-server # 应用名称
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_test?useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 指定nacos注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8090 # 指定sentinel服务端地址
user-server: # 针对user-server的服务开启随机算法的负载均衡
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
feign:
  sentinel:
    enabled: true #开启熔断功能
#mybatis:
#  type-aliases-package: cn.lion.order.domain # 数据库别名配置
#  configuration:
#    map-underscore-to-camel-case: true # 数据库表字段名和Java对象属性名之间的映射
#
#logging:
#  level:
#    cn.lion: debug
#  pattern:
#    dateformat: MM-dd HH:mm:ss:SSS
  • 第四步:启动测试,在nacos注册中心进行查看

6.服务通信

  • 在服务调用方我们可以使用Feign、OpenFeign、Dubbo,本次我们直接使用OpenFeign
  • 第一步:OrderServer中导入OpenFeign依赖
<!--引入OpenFeign依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 第二步:UserServer提供被调用接口
@RestController
@RequestMapping("/user")
public class UserController {
    @Value("${server.port}")
    private String port;

    @GetMapping("/getById/{id}")
    public User getById(@PathVariable("id") Long id){
        return new User(id, "HelloWorld", "你好,世界!,端口号:" + port);
    }
}
  • 第三步:OrderServer开启OpenFeign
@SpringBootApplication
// 开启Nacos客户端
@EnableDiscoveryClient
// 开启openfeign
@EnableFeignClients
public class OrderApp {
    public static void main(String[] args) {
        SpringApplication.run(OrderApp.class,args);
    }
}
  • 第四步:提供OpenFeign接口
@FeignClient("user-server")
public interface UserFeignClient {

    @GetMapping("/user/getById/{id}")
    public User getById(@PathVariable("id") Long id);

}
  • 第五步:提供OrderServer调用UserServer接口
@RestController
@RequestMapping("/order")
public class OrderController {
    /**
     * feign调用user服务的客户端组件
     */
    @Autowired
    private UserFeignClient feignClient;

    /**
     * 调用user服务接口并返回
     * @param id 用户id
     * @return
     */
    @GetMapping("/{id}")
    public User getById(@PathVariable("id") Long id){
        return feignClient.getById(id);
    }
}
  • 第六步:重启服务,访问OrderServer接口

7.网关模块搭建

  • 第一步:导入依赖
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!--引入gateway依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--nacos客户端依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--公共模块依赖-->
        <dependency>
            <groupId>cn.lion</groupId>
            <artifactId>common-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--nacos配置中心客户端依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--sentinel依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
	</dependencies>
  • 第二步:编写启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class GateWayApplication {
        public static void main(String[] args) {
            SpringApplication.run(GateWayApplication.class,args);
        }
    }
    
  • 第三步:添加配置文件

    server:
      port: 10086
    spring:
      application:
        name: gateway-server
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8090 # 指定sentinel服务端地址
        gateway:
          discovery:
            locator:
              enabled: false #禁用服务名直接访问,但是还是可以通过主机地址和端口号进行访问
              lower-case-service-id: true #服务名小写
          routes: #路由配置
            - id: application-user #指定服务名
              uri: lb://user-server #去注册中心找这个服务名
              predicates: #断言,匹配访问的路径
                - Path=/user-server/**    #服务访问路径
              filters:
                - StripPrefix=1
            - id: application-order #指定服务名
              uri: lb://order-server #去注册中心找这个服务名
              predicates: #断言,匹配访问的路径
                - Path=/order-server/**    #服务访问路径
            filters:
                - StripPrefix=1
    

SpringCloudAlibaba-Nacos做配置中心

Nacos添加配置

  • 第一步:打开Nacos监控面板,进入配置列表,新增一个user服务的配置文件

  • 第二步:填写配置文件参数,这里定义了一个名字为application-user-dev.yaml的配置,使用的是YAML格式

    • DataID : 非常重要,可以看做是配置的文件的名字,在程序中拉取配置文件的时候需要指定Data ID。
    • Group : 分组,默认 DEFAULT_GROUP , 可以针对不同的项目指定不同的配置组

客户端接入配置中心

1.导入依赖

  • 修改工程 user-server ,添加配置中心依赖nacos-config
<dependencies>
    <!--nacos配置中心客户端依赖-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
</dependencies>

2.动态刷新配置

  • nacos提供了@RefreshScope注解来刷新配置文件,除了项目环境,可以使用此注解来刷新我们在配置文件中的属性值

需求:在配置文件中定义一个dynamicRefreshTest参数,在代码中通过注解获取,测试是否能够动态刷新

  • 第一步:修改注册中心中UserServer服务的配置,新增一个属性值
server:
  port: 1010 # user服务端口号

spring:
  application:
    name: user-server # 应用名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 指定nacos注册中心地址
username: hello!
  • 第二步:在UserServer中获取dynamicRefreshTest属性值,后续动态改变配置的值,观察是否改变
/**
 * @Description 用户相关接口请求处理
 * @Author Raymon
 * @Date 2023/4/14 11:07
 * @Version 1.0
 */
@RestController
@RequestMapping("/user")
@RefreshScope // 动态刷新配置注解
public class UserController {
    @Value("${server.port}")
    private String port;

    @Value("${username}")
    private String username;

    @GetMapping("/getById/{id}")
    public User getById(@PathVariable("id") Long id){
        return new User(id, "helloworld", "你好世界!,端口号:" + port+ ", username:" + username);
    }
}

3.编写bootstrap.yml

  • 跟springcloud-config一样,我们的配置也需要写在bootstrap.yml中
    • 如何查找配置文件:application-user + dev + yaml=application-user-dev.yaml 正好和Nacos配置的DataId一致
spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848 
        prefix: application-gateway 
        file-extension: yaml 
        group: DEFAULT_GROUP 
        namespace: 8b705cca-86ef-40dd-8f00-a84a19ea2e48
  profiles:
    active: dev 

4.测试

  • 启动Nacos,启动 springcloudalibaba-user-server微服务 , 修改Nacos中的配置文件内容,然后访问 http://localhost:10001/user/2,观察控制台打印的 “username”的值会发生变化

SpringCloudAlibaba-Sentinel限流

Sentinel介绍

Sentinel是阿里巴巴开源的一款微服务流量控制组件。官网地址:https://sentinelguard.io/zh-cn/index.html

Sentinel限流应用

运行

java -Dserver.port=8090 -jar sentinel-dashboard-1.8.2.jar

访问
访问http://localhost:8090页面,就可以看到sentinel的控制台了:

需要输入账号和密码,默认都是:sentinel
登录后,发现一片空白,什么都没有:
请求进来才会有东西

2.Sentinel客户端接入

2.1.导入依赖
  • 在需要使用Sentinel微服务中导入依赖,本次导入在user-server服务中
<!--sentinel依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.2.配置Sentinel
  • 在nacos的配置中心修改user-server微服务配置文件,指定sentinel服务端地址

如果是放入了配置中心,就去配置中心修改

server:
  port: 10001 # user服务端口号

spring:
  application:
    name: user-server # 应用名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 指定nacos注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8090 # 指定sentinel服务端地址

username: helloworld
2.3.测试
  • 启动user-server,访问接口,再查看sentinel控制面板

3.Sentinel设置限流策略

  • 我们可以针对某个接口在控制面板处设置限流规则,比如此处我们设置QPS每秒钟只能进来一个请求

  • 第一步:设置接口限流规则

  • 第二步:浏览器访问user-server服务设置了限流规则的接口,疯狂刷新下是否触发限流

4.资源限流

  • Sentinel为我们提供了 @SentinelResource注解标记需要限流的资源,并设置降级方法,以userserver微服务为例
4.1.本类降级方法
  • 设置限流接口,并指定降级方法
    • value:给当前接口取一个资源名称
    • blockHandler:指定降级方法名称,blockHandler方法访问范围需要是 public,返回类型需要与接口相匹配,参数类型必须和接口一致并且最后加一个类型为 BlockException 的异常参数
@RestController
@RequestMapping("/user")
@RefreshScope // 动态刷新配置注解
public class UserController {
    @Value("${server.port}")
    private String port;

    @Value("${dynamicRefreshTest}")
    private String dynamicRefreshTest;

    @GetMapping("/{id}")
    @SentinelResource(value="user-server-getById", blockHandler = "degradationMethod")
    public User getById(@PathVariable("id") Long id){
        return new User(id, "helloworld", "你好世界!,端口号:" + port+ ", username:" + username);
    }

    /**
     * 服务降级方法
     * @param e 服务降级方法必须接收的异常参数
     */
    public User degradationMethod(@PathVariable("id") Long id, BlockException e){
        e.printStackTrace();
        return new User(-1L, "服务降级触发!", "当前服务流量过大,请稍后重试!");
    }
}
4.2.降级类
  • 创建降级类、静态降级方法
public class DowngradeUtil {
    public static User degradationMethod(@PathVariable("id") Long id, BlockException e){
        e.printStackTrace();
        return new User(-1L, "服务降级触发!", "当前服务流量过大,请稍后重试!");
    }
}
  • 接口指定降级类,与降级方法
    • value:给当前接口取一个资源名称
    • blockHandlerClass:指定降级方法类
    • blockHandler:指定降级方法名称,blockHandler方法访问范围需要是 public,返回类型需要与接口相匹配,参数类型必须和接口一致并且最后加一个类型为 BlockException 的异常参数
@GetMapping("/{id}")
@SentinelResource(value="user-server-getById", blockHandler ="degradationMethod",blockHandlerClass = DowngradeUtil.class)
public User getById(@PathVariable("id") Long id){
    return new User(id, "helloworld", "你好世界!,端口号:" + port+ ", dynamicRefreshTest:" + dynamicRefreshTest);
}
4.3.测试
  • 设置限流规则,浏览器访问接口进行测试

Sentinel流控模式

在添加限流规则时,点击高级选项,可以选择三种流控模式

  • 直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式
  • 关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
  • 链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流

Gateway使用Sentinel限流

  • SpringCloudGateway作为微服务的网关,它是微服务的访问入口,当请求的流量洪峰时可以在Gateway网关层通过Sentinel对请求进行流控

1.导入依赖

<!--sentinel与gateway整合依赖包-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!--sentinel依赖包-->
<dependency>	
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2.配置Sentinel地址

  • 指定Sentinel地址
spring:
	cloud:
      sentinel:
          transport:
            dashboard: localhost:8090

3.配置限流规则

  • 启动Gateway,登录Sentinel控制台,对Url资源进行流控限制,配置方式和前面的配置方式一样

4.限流降级

  • Gateway并没有实际的接口方法,那么就需要使用配置的形式进行限流控制
@Configuration
public class SentinelConfig {
    public SentinelConfig(){
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                return ServerResponse.ok().body(Mono.just("当前流量过高,触发限流!"),String.class);
            }
        });
    }
}

Nacos存储限流规则

  • 在之前的使用中,Sentinel的限流规则在服务启动时就已经被清除,那是因为之前的限流规则是存储在内存中,这样肯定不服务实际开发,所以我们需要进行限流规则持久化
  • Sentinel中支持5种持久化的方式:file、redis、nacos、zk和apollo,本片文章针对于Nacos进行持久化配置
    • nacos限流规则持久化:其实就是使用配置进行限流规则存储,在微服务中指定需要读取的限流规则

1.整合Nacos持久化限流规则

  • 以user-server微服务为例,使用Nacos做限流持久化
  • 第一步:在user-server服务中导入依赖
<!--Sentinel使用Nacos持久化限流规则依赖包-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.5.2</version>
</dependency>
  • 第二步:在Nacos中新增限流规则配置,用于服务启动时读取限流规则,要配置在public命名空间下
    • resource:对那个资源进行限流
    • limitApp:这个是流控的调用者,default 代表不区分调用者
    • grade:限流方式0是根据并发数量限流,1表示根据QPS来限流
    • count:限流阈值,达到这个阈值就被限流,触发降级。
    • strategy:基于调用链的流控制策略。0 直接,1 关联 2 链路
    • controlBehavior:流控效果,0 直接拒绝,1是Warm Up,2是匀速排队
    • clusterMode:是否为集群
[
    {
        "resource": "user-server-getById",
        "limitApp": "default",
        "grade": 1,
        "count": 10,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

  • 第三步:修改微服务在Nacos中的配置文件,增加读取Nacos中刚才配置的限流规则配置
server:
  port: 1010 # user服务端口号

spring:
  application:
    name: user-server # 应用名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 指定nacos注册中心地址
    sentinel:
      transport:
        dashboard: localhost:1111 # 指定sentinel服务端地址
      datasource:
        flow:
          nacos: #限流持久配置
            server-addr: localhost:8848	#使用nacos的持久
            dataId: application-user-dev	#获取限流的数据源的dataId
            groupId: DEFAULT_GROUP
            rule-type: flow #类型:限流

  • 第四步:测试
    • 重启user-server微服务,访问接口,查看Sentinel中是否有刚才设置的限流规则,并且查看动态修改限流规则是否会生效

SpringCloudAlibaba-Sentinel熔断

服务熔断降级

  • 修改user-server微服务,通过@SentinelResource注解的fallback 属性指定降级方法
①本类降级方法
  • 设置熔断接口,并设置降级方法
    • fallback:方法的返回值类型必须与接口返回值类型一致,方法参数列表需要和接口一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常
@RestController
@RefreshScope // 动态刷新配置注解
public class UserController {

    @Value("${server.port}")
    private String port;

    @Value("${dynamicRefreshTest}")
    private String dynamicRefreshTest;


    @GetMapping("/getById/{id}")
    @SentinelResource(value="user-server-getById", fallback = "fuseDegradation")
    public User getById(@PathVariable("id") Long id){
        try {
            // 用于让服务慢响应
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new User(id, "源码时代", "我在源码时代学习Java!,端口号:" + port + ", dynamicRefreshTest:" + dynamicRefreshTest);
    }

    /*
     * @Description: 熔断降级方法
     * @param id:
     * @param e: 降级异常
     * @return: cn.itsource.domain.User
     **/
    public User fuseDegradation(@PathVariable("id") Long id, Throwable  e){
        e.printStackTrace();
        return new User(-1L, "熔断服务降级触发!", "服务不可用,请稍后重试!");
    }

}
②降级类
  • 设置熔断接口,并设置降级方法
    • fallbackClass:指定熔断类字节码
    • fallback:方法的返回值类型必须与接口返回值类型一致,方法参数列表需要和接口一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常
  • 熔断降级类
public class FuseDowngradeUtil {
    /*
     * @Description: 熔断降级方法
     * @param id:
     * @param e: 降级异常
     * @return: cn.itsource.domain.User
     **/
    public static User fuseDegradation(@PathVariable("id") Long id, Throwable  e){
        e.printStackTrace();
        return new User(-1L, "熔断服务降级触发!", "服务不可用,请稍后重试!");
    }

}
  • 熔断接口
@RestController
@RefreshScope // 动态刷新配置注解
public class UserController {

    @Value("${server.port}")
    private String port;

    @Value("${dynamicRefreshTest}")
    private String dynamicRefreshTest;

    /*
     * @Description: 提供一个根据Id返回User对象的接口,给order服务调用
     * @param id:
     * @return: cn.itsource.domain.User
     **/
    @GetMapping("/getById/{id}")
    @SentinelResource(value="user-server-getById", fallback = "fuseDegradation", fallbackClass = FuseDowngradeUtil.class)
    public User getById(@PathVariable("id") Long id){
        try {
            // 用于让服务慢响应
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new User(id, "源码时代", "我在源码时代学习Java!,端口号:" + port + ", dynamicRefreshTest:" + dynamicRefreshTest);
    }

}

2.设置熔断降级规则

  • 重启user-server服务后,在Sentinel中设置熔断降级规则,以慢调用比例规则为例
    • 最大RT:请求平均响应时长
    • 比例阈值:每秒请求次数的百分比,多少百分比触发
    • 熔断时长:该熔断接口停止提供服务的时长
    • 最小请求数:每秒请求数量

3.测试

  • 访问user-server服务接口,疯狂刷新,就会看到触发熔断降级方法,并且10S内无法继续访问成功

OpenFeign整合Sentinel熔断

  • Spring Cloud Alibaba是Spring Cloud的一个子项目,OpenFeign是Spring Cloud的客户端负载均衡器,使用Spring Cloud Alibaba依然可以很方便的集成OpenFeign,如果要使用OpenFeign作为服务客户端负载均衡,那么我们需要考虑OpenFeign开启Sentinel进行服务熔断降级

1.导入依赖

  • OpenFeign整合Sentinel熔断那么就需要微服务导入OpenFeign依赖与Sentinel依赖
<!--引入OpenFeign依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--sentinel依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2.开启OpenFeignSentinel熔断

server:
  port: 1020 # order服务端口号

spring:
  application:
    name: order-server # 应用名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 指定nacos注册中心地址
    sentinel:
      transport:
        dashboard: localhost:1111 # 指定sentinel服务端地址
feign:
  sentinel:
    enabled: true #开启熔断功能

3.OpenFeign接口降级

  • 这里跟OpenFeign开启Hystrix降级一样,还是可以使用fallback属性
@FeignClient(value = "user-server", fallbackFactory = UserFeignClientFallbackFactory.class) // 表示是feign接口
public interface UserFeignClient {

    @GetMapping("/getById/{id}")
    User getById(@PathVariable("id") Long id);

}

4.编写降级类

@Component
public class UserFeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
    /*
     * @Description: 熔断托底方法
     * @param throwable: 
     * @return: cn.itsource.feigenClients.UserFeignClient
     **/
    @Override
    public UserFeignClient create(Throwable throwable) {
        return new UserFeignClient() {
            @Override
            public User getById(Long id) {
                return new User(-1L, "触发熔断", "服务不可用,请稍后重试!");
            }
        };
    }
}

5.测试

  • 第一步:正常启动order-server、user-server服务,访问order-server服务接口

  • 第二步:关闭user-server服务,触发熔断

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值