随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel
以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
在前面我们通过以下章节对Sentinel
有了基础的了解:
Sentinel:分布式系统的流量防卫兵 | Spring Cloud 19
Sentinel:资源与规则定义 | Spring Cloud 20
Sentinel:原理深入浅出解读 | Spring Cloud 21
Sentinel:流量控制规则定义详解 | Spring Cloud 22
现在开始我们正式学习Sentinel
在Spring Boot/Cloud
中的集成使用。
Sentinel
提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。这里,我们将会详细讲述如何通过简单的步骤就可以使用这些功能。
Sentinel
控制台包含如下功能:
Sentinel
客户端发送的心跳包,用于判断机器是否在线。Sentinel
客户端暴露的监控 API
,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。您可以从 release 页面 下载最新版本的控制台 jar
包。
注意:启动
Sentinel
控制台需要JDK
版本为1.8
及以上版本。
使用如下命令启动控制台:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
其中
-Dserver.port=8080
用于指定Sentinel
控制台端口为8080
其中-Dcsp.sentinel.dashboard.server=consoleIp:port
用于指定Sentinel
控制的访问地址,用于客户端接入控制台
从 Sentinel 1.6.0
起,Sentinel
控制台引入基本的登录功能,默认用户名和密码都是 sentinel
。
确保客户端有访问量,Sentinel
会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。
注意:您还需要根据您的应用类型和接入方式引入对应的
适配依赖
,否则即使有访问量也不能被Sentinel
统计。
当您在机器列表中看到您的机器,就代表着您已经成功接入控制台;如果没有看到您的机器,请检查配置,并通过 ${user.home}/logs/csp/sentinel-record.log.xxx
日志来排查原因
注意:若接入 Sentinel 控制台不成功,可以参考 FAQ 排查问题。
模块sentinel-nacos-provider
用于演示自定义限流处理逻辑
模块sentinel-nacos-consumer
用于演示Sentinel
与 Feign
集成
用于演示Sentinel
与 RestTemplate
集成
用于演示Sentinel
链路流控模式
com.alibaba.cloud spring-cloud-starter-alibaba-sentinel
完整sentinel/sentinel-nacos-provider/pom.xml
:
com.gm sentinel 0.0.1-SNAPSHOT 4.0.0 sentinel-nacos-provider org.springframework.cloud spring-cloud-starter-bootstrap org.springframework.cloud spring-cloud-starter-loadbalancer com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator com.alibaba.cloud spring-cloud-starter-alibaba-sentinel org.springframework.boot spring-boot-maven-plugin src/main/resources true **/*.xlsx **/*.xls src/main/resources false **/*.xlsx **/*.xls
自定义限流处理逻辑可以有两种实现方式
BlockExceptionHandler
实现类覆盖默认的 DefaultBlockExceptionHandler
@SentinelResource
注解的 blockHandler
和 blockHandlerClass
两个参数指定限流处理逻辑方法本示例只演示方式一
限流默认处理类 DefaultBlockExceptionHandler
:
public class DefaultBlockExceptionHandler implements BlockExceptionHandler {public DefaultBlockExceptionHandler() {}public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {response.setStatus(429);PrintWriter out = response.getWriter();out.print("Blocked by Sentinel (flow limiting)");out.flush();out.close();}
}
新建com/gm/sentinel_nacos_provider/component/CustomUrlBlockHandler.java
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class CustomUrlBlockHandler implements BlockExceptionHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {String msg = null;if (e instanceof FlowException) {msg = "限流了,请稍后访问";} else if (e instanceof DegradeException) {msg = "降级了,返回默认数据";} else if (e instanceof ParamFlowException) {msg = "热点参数限流";} else if (e instanceof SystemBlockException) {msg = "系统规则(负载/...不满足要求)";} else if (e instanceof AuthorityException) {msg = "授权规则不通过";}// http状态码response.setStatus(500);response.setCharacterEncoding("utf-8");response.setHeader("Content-Type", "application/json;charset=utf-8");response.setContentType("application/json;charset=utf-8");JSONObject jsonObject = new JSONObject();jsonObject.put("msg", msg);response.getWriter().write(jsonObject.toJSONString());}
}
新建com/gm/sentinel_nacos_provider/controller/ProviderController.java
:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ProviderController {@Value("${server.port}")private int port;@RequestMapping(value = "sayHello", method = RequestMethod.GET)public String sayHello(@RequestParam String world) {return "当前服务端口为:" + port + ",请求参数:" + world;}
}
新建com/gm/sentinel_nacos_provider/SentinelNacosProviderApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication
@EnableDiscoveryClient
public class SentinelNacosProviderApplication {public static void main(String[] args) {SpringApplication.run(SentinelNacosProviderApplication.class, args);}
}
src/main/resources/bootstrap.yml:
server:port: 4000spring:application:name: @artifactId@cloud:nacos:username: @nacos.username@password: @nacos.password@discovery:server-addr: ${NACOS_HOST:nacos1.kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos2kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos3.kc}:${NACOS_PORT:8848}sentinel:transport:port: 8719dashboard: 127.0.0.1:8080
management:endpoints:web:exposure:include: '*'
先访问:http://127.0.0.1:4000/sayHello?world=hello%20world 测试功能是否正常访问:
进入Sentinel
控制台对/sayHello
新增流控规则:
再次访问:http://127.0.0.1:4000/sayHello?world=hello%20world 验证流控规则和自定义限流控制逻辑是否生效:
此时通过响应结果可知:流控规则和自定义限流控制逻辑均已生效。
上一篇:js中的new()到底做了些什么
下一篇:速通MySQL