Sentinel+Feign+Nacos

一.Feign+Nacos实现服务间远程调用

背景:

服务提供方:sms-center

服务调用方:user-center

1.启动Nacos服务

2.服务提供方:sms-center

添加Nacos相关依赖

(不指定版本号可能出现依赖报错,服务注册不上去的情况)

		<!-- 选用nacos时打开-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>	

启动类添加服务发现注解

@EnableDiscoveryClient

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

3.服务调用方:user-center

添加Nacos和OpenFeign相关依赖

		<!-- 选用nacos时打开-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
            <version>2.2.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

        <!--OpenFeign RPC调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

在服务调用方下编写服务提供方sms-center的service

@FeignClient("sms-center")
@Component
public interface SmsService {

    /**
     * Sms-center服务发送消息的接口
     * @param
     * @return
     */
    @RequestMapping("/sms/send")
    String sendMsg();

    @RequestMapping("/sms/send2")
    String sendMsg2(String msg);
}

@FeignClient注解指定Nacos中服务提供方的名字

@Component注解将该类作为bean交给Spring管理,方便服务调用方的controller注入

@RequestMapping指定需要调用的服务提供方的接口

服务调用方的Controller注入SmsService

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private SmsService smsService;
    
    @GetMapping("/sendMsg")
    public String sendUserMsg(){
        System.out.println("用户服务收到请求");
        return smsService.sendMsg();
    }

    @PostMapping("/sendMsg2")
    public String sendUserMsg2(@RequestBody String msg){
        System.out.println("用户服务收到请求");
        return smsService.sendMsg2(msg);
    }
}

服务调用方的controller就像调用自己的service一样,但其实是service去调用了服务提供方的相关接口

启动类添加FeignClient和服务发现注解

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

访问服务调用方相关接口,能正确返回。

二.使用 Sentinel Dashboard进行流量控制

现假设sms-center的发送消息接口/sms/sendUser容易产生拥堵,需要对其进行流量控制

1.启动Sentinel Dashboard

方式一:下载Sentinel的控制台jar包并运行java -jar sentinel-dashboard.jar

方式二:拉取Sentinel代码,编译运行dashboard

具体操作此处不再赘述,默认运行端口是:8080

2.本地代码接入Sentinel dashboard

1)引入Sentinel相关依赖

		<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
<!--下面这些依赖没有也不影响,列在这儿备用-->
<!--        <dependency>-->
<!--            <groupId>com.alibaba.csp</groupId>-->
<!--            <artifactId>sentinel-core</artifactId>-->
<!--            <version>1.8.1</version>-->
<!--        </dependency>-->

<!--        <dependency>-->
<!--            <groupId>com.alibaba.csp</groupId>-->
<!--            <artifactId>sentinel-annotation-aspectj</artifactId>-->
<!--            <version>1.8.0</version>-->
<!--        </dependency>-->

<!--        <dependency>-->
<!--            <groupId>com.alibaba.csp</groupId>-->
<!--            <artifactId>sentinel-datasource-nacos</artifactId>-->
<!--        </dependency>-->

<!--        <dependency>-->
<!--            <groupId>com.alibaba.csp</groupId>-->
<!--            <artifactId>sentinel-web-servlet</artifactId>-->
<!--        </dependency>-->

<!--        <dependency>-->
<!--            <groupId>com.alibaba.csp</groupId>-->
<!--            <artifactId>sentinel-transport-simple-http</artifactId>-->
<!--            <version>1.8.0</version>-->
<!--        </dependency>-->

2)编写yml或properties配置文件

以sms-center的application.yml文件为例:

server:
  port: 8002
spring:
  application:
    name: Sms-center
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址

3)接入限流埋点

  • HTTP埋点:

    Sentinel starter 默认为所有的 HTTP 服务提供了限流埋点,如果只想对 HTTP 服务进行限流,那么只需要引入依赖,无需修改代码。

  • 自定义埋点:

    1.使用原始的SphU.entry(xxx)方法进行埋点,使用这种方法需要结合try catch finally代码块,并且最后必须entry.exit()

    2.使用@SentinelResource注解对需要保护的资源进行限流埋点

我采用@SentinelResource注解进行埋点:

/**
     * 发送用户消息(用于测试Feign远程调用以及Sentinel流量控制)
     *
     * @param user
     * @return
     */
    @SentinelResource(value = "sendUser", blockHandler = "sendMsgBlockHandler")
    @PostMapping("/sendUser")
    public String sendMsgTest(@RequestBody User user) {
        String result = smsService.sendUserMsg(user);
        return result;
    }

    public String sendMsgBlockHandler(User user, BlockException e) {
        log.warn("该接口被限流了:" + e);
        return "该接口被限流了";
    }

@SentinelResource

  • value:资源名称-必填
  • blockHandler:触发流控后调用的方法,public修饰,返回值和参数必须和原方法相同,且添加BlockException的参数
  • blockHandlerClass:触发流控处理的类,里面的方法必须是static的(适用于建一个类来专门编写限流处理的方法,避免放在controller里面)

Smscontroller:

@SentinelResource(value = "sendUser", blockHandlerClass = {SmsBlockHandler.class}, blockHandler = "sendMsgBlockHandler")
@PostMapping("/sendUser")
public String sendMsgTest(@RequestBody User user) {
	String result = smsService.sendUserMsg(user);
    return result;
}

SmsBlockHandler:

@Slf4j
public class SmsBlockHandler {

    public static String sendMsgBlockHandler(User user, BlockException e) {
        log.warn("该接口被限流了:" + e);
        return "该接口被限流了";
    }
}

3.启动服务提供方和调用方

**访问服务调用方的接口

注意,Sentinel是Lazy Load策略的,服务虽然配置了Sentinel Dashboard的地址,但在第一次调用前,Sentinel的控制台的菜单是不会有相关组件的。

这个超级坑,我一直以为是自己服务没能正确接入Sentinel。

访问受到保护的接口,观察Sentinel控制台 > 簇点链路
在这里插入图片描述

为相应资源添加流控策略:

为了方便效果演示,我设置QPS=1
在这里插入图片描述
疯狂访问刚才添加了限流策略的接口,观察返回结果和控制台:
在这里插入图片描述

可以看到,流控成功了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值