sentinel即哨兵,相比hystrix断路器而言,它的功能更丰富。hystrix仅支持熔断,当服务消费方调用提供方发现异常后,进入熔断;sentinel不仅支持异常熔断,也支持响应超时熔断,另外还支持限流,以及针对网关的熔断和限流。此外,它还有过载处理、监控控制台(Sentinel Dashboard)等。hystrix作为组件集成到微服务中,sentinel也是如此,但它的控制台需要独立部署。
先下载Sentinel Dashboard(下载地址https://github.com/alibaba/Sentinel/releases),目前最新版本是1.6.3,下载到本地(我的是E盘download目录下)后启动jar包:
C:\Users\wulf>e: E:\>cd download E:\download>java -jar sentinel-dashboard.jar SLF4J: The requested version 1.7.16 by your slf4j binding is not compatible with [1.6] SLF4J: See http://www.slf4j.org/codes.html#version_mismatch for further details. . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.6.3.RELEASE) 2019-08-21 15:58:42 [main] INFO c.t.c.sentinel.dashboard.Application - Starting Application on wulf00 with PID 35648 (E:\download\sentinel-dashboard.jar started by wulf in E:\download) 2019-08-21 15:58:42 [main] INFO c.t.c.sentinel.dashboard.Application - No active profile set, falling back to default profiles: default 2019-08-21 15:58:43 [main] INFO o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext - Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3d012ddd: startup date [Wed Aug 21 15:58:43 CST 2019]; root of context hierarchy 2019-08-21 15:58:50 [main] INFO o.s.b.c.e.t.TomcatEmbeddedServletContainer - Tomcat initialized with port(s): 8080 (http) 2019-08-21 15:58:50 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat] 2019-08-21 15:58:50 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet Engine: Apache Tomcat/8.5.23 2019-08-21 15:58:50 [localhost-startStop-1] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext 2019-08-21 15:58:51 [localhost-startStop-1] INFO o.s.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 7875 ms 2019-08-21 15:58:51 [localhost-startStop-1] INFO c.t.c.s.dashboard.config.WebConfig - sentinelFilterRegistration(), add CommonFilter 2019-08-21 15:58:51 [localhost-startStop-1] INFO o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'characterEncodingFilter' to: [/*] 2019-08-21 15:58:51 [localhost-startStop-1] INFO o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2019-08-21 15:58:51 [localhost-startStop-1] INFO o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'httpPutFormContentFilter' to: [/*] 2019-08-21 15:58:51 [localhost-startStop-1] INFO o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'requestContextFilter' to: [/*] 2019-08-21 15:58:51 [localhost-startStop-1] INFO o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'sentinelFilter' to urls: [/*] 2019-08-21 15:58:51 [localhost-startStop-1] INFO o.s.b.w.s.ServletRegistrationBean - Mapping servlet: 'dispatcherServlet' to [/] 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3d012ddd: startup date [Wed Aug 21 15:58:43 CST 2019]; root of context hierarchy 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/app/names.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<java.util.List<java.lang.String>> com.taobao.csp.sentinel.dashboard.view.AppController.queryApps(javax.servlet.http.HttpServletRequest) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/app/briefinfos.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<java.util.List<com.taobao.csp.sentinel.dashboard.discovery.AppInfo>> com.taobao.csp.sentinel.dashboard.view.AppController.queryAppInfos(javax.servlet.http.HttpServletRequest) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/app/{app}/machines.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<java.util.List<com.taobao.csp.sentinel.dashboard.view.vo.MachineInfoVo>> com.taobao.csp.sentinel.dashboard.view.AppController.getMachinesByApp(java.lang.String) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/degrade/new.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.DegradeController.add(java.lang.String,java.lang.String,java.lang.Integer,java.lang.String,java.lang.String,java.lang.Double,java.lang.Integer,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/degrade/delete.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.DegradeController.delete(java.lang.Long) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/degrade/save.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.DegradeController.updateIfNotNull(java.lang.Long,java.lang.String,java.lang.String,java.lang.String,java.lang.Double,java.lang.Integer,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/degrade/rules.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<java.util.List<com.taobao.csp.sentinel.dashboard.datasource.entity.DegradeRuleEntity>> com.taobao.csp.sentinel.dashboard.view.DegradeController.queryMachineRules(java.lang.String,java.lang.String,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/demo/loop],produces=[application/json]}" onto public java.lang.String com.taobao.csp.sentinel.dashboard.view.DemoController.loop(java.lang.String,int) throws com.alibaba.csp.sentinel.slots.block.BlockException 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/demo/link],produces=[application/json]}" onto public java.lang.String com.taobao.csp.sentinel.dashboard.view.DemoController.link() throws com.alibaba.csp.sentinel.slots.block.BlockException 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/demo/greeting],produces=[application/json]}" onto public java.lang.String com.taobao.csp.sentinel.dashboard.view.DemoController.greeting() 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/demo/slow],produces=[application/json]}" onto public java.lang.String com.taobao.csp.sentinel.dashboard.view.DemoController.slow(java.lang.String,int) throws com.alibaba.csp.sentinel.slots.block.BlockException 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/flow/new.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.FlowController.add(java.lang.String,java.lang.String,java.lang.Integer,java.lang.String,java.lang.String,java.lang.Integer,java.lang.Double,java.lang.Integer,java.lang.String,java.lang.Integer,java.lang.Integer,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/flow/delete.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.FlowController.delete(java.lang.Long) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/flow/save.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.FlowController.updateIfNotNull(java.lang.Long,java.lang.String,java.lang.String,java.lang.String,java.lang.Integer,java.lang.Double,java.lang.Integer,java.lang.String,java.lang.Integer,java.lang.Integer,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/flow/rules.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<java.util.List<com.taobao.csp.sentinel.dashboard.datasource.entity.FlowRuleEntity>> com.taobao.csp.sentinel.dashboard.view.FlowController.queryMachineRules(java.lang.String,java.lang.String,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/health],methods=[GET]}" onto public java.lang.String com.taobao.csp.sentinel.dashboard.view.HealthCheck.checkPreload() 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/registry/machine],produces=[application/json]}" onto public com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.MachineRegistryController.receiveHeartBeat(java.lang.String,java.lang.Long,java.lang.String,java.lang.String,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/metric/queryTopResourceMetric.json],produces=[application/json]}" onto public com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.MetricController.queryTopResourceMetric(java.lang.String,java.lang.Integer,java.lang.Integer,java.lang.Boolean,java.lang.Long,java.lang.Long,java.lang.String) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/metric/queryByAppAndResource.json],produces=[application/json]}" onto public com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.MetricController.queryByAppAndResource(java.lang.String,java.lang.String,java.lang.Long,java.lang.Long) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/resource/machineResource.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.ResourceController.fetchIdentityOfMachine(java.lang.String,java.lang.Integer,java.lang.String,java.lang.String) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/system/new.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.SystemController.add(java.lang.String,java.lang.String,java.lang.Integer,java.lang.Double,java.lang.Long,java.lang.Long,java.lang.Double) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/system/delete.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.SystemController.delete(java.lang.Long) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/system/save.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<?> com.taobao.csp.sentinel.dashboard.view.SystemController.updateIfNotNull(java.lang.Long,java.lang.String,java.lang.Double,java.lang.Long,java.lang.Long,java.lang.Double) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/system/rules.json],produces=[application/json]}" onto com.taobao.csp.sentinel.dashboard.view.Result<java.util.List<com.taobao.csp.sentinel.dashboard.datasource.entity.SystemRuleEntity>> com.taobao.csp.sentinel.dashboard.view.SystemController.queryMachineRules(java.lang.String,java.lang.String,java.lang.Integer) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2019-08-21 15:58:53 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2019-08-21 15:58:53 [main] INFO o.s.w.s.h.SimpleUrlHandlerMapping - Root mapping to handler of type [class org.springframework.web.servlet.mvc.ParameterizableViewController] 2019-08-21 15:58:53 [main] INFO o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2019-08-21 15:58:53 [main] INFO o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2019-08-21 15:58:53 [main] INFO o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2019-08-21 15:58:53 [main] WARN o.s.b.a.t.AbstractTemplateResolverConfiguration - Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) 2019-08-21 15:58:55 [main] INFO o.s.j.e.a.AnnotationMBeanExporter - Registering beans for JMX exposure on startup 2019-08-21 15:58:55 [main] INFO o.s.b.c.e.t.TomcatEmbeddedServletContainer - Tomcat started on port(s): 8080 (http) 2019-08-21 15:58:55 [main] INFO c.t.c.sentinel.dashboard.Application - Started Application in 13.731 seconds (JVM running for 16.72) 2019-08-21 15:58:55 [http-nio-8080-exec-1] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring FrameworkServlet 'dispatcherServlet' 2019-08-21 15:58:55 [http-nio-8080-exec-1] INFO o.s.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization started 2019-08-21 15:58:55 [http-nio-8080-exec-1] INFO o.s.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization completed in 65 ms
默认端口号是8080,我们在浏览器输入localhost:8080即可打开监控面板
接下来我们让服务提供方lxytrans-provider这个应用(原三板斧参见0.9.0.RELEASE版本的spring cloud alibaba nacos实例)接入到哨兵,只需在原三板斧的基础上给前面两板斧加上sentinel相关内容:
1、pom引入sentinel依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
2、application引入sentinel dashboard地址:
#哨兵
spring.cloud.sentinel.transport.dashboard=localhost:8080
打完收工。启动应用后,再访问localhost:8080,发现微服务已经接入,只不过啥都木有而已:
我们需要先访问一次接口,才能在sentinel dashboard上看到。那就先跑一把/hello和/hey吧:
再回去刷新下实时监控,hello出来了:
我们点下“簇点链路”,在对应的资源右边点击流控进行流控规则设置,点击降级则是设置降级规则:
先试下流控。上面可以看到hello有3级资源,随便选一个点击流控:
这里我们配置流控规则是每秒并发请求数为3,超过了就直接拒绝。点击新增按钮后跳到流控规则页面:
流控规则页面的右上角也可以直接添加规则的。现在我们通过jmeter来跑一个,jmeter设置线程数为4(具体设置参见jmeter使用经历):
我们看到并发调用了4次hello接口,其中一次失败了,日志打印如下:
2019-08-22 13:02:14.651 |-ERROR [http-nio-8282-exec-10] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] [175] -| Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause com.alibaba.csp.sentinel.slots.block.flow.FlowException: null
接下来我们再另一个/hey接口,然后在“簇点链路”去设置降级规则:
这里我们配置/hey接口如果时延超过100毫秒,那么接下来的10秒内,我们讲拒绝请求。点击“新增”按钮后跳往降级规则页面:
同样的,在这个页面右上角可以直接新增降级规则。我们在jmeter中新增一个/hey接口,禁用原来的/hello,再将线程数改为5,循环次数改为4,跑一把:
/hey接口的时延是2秒,仔细看下这20个接口的请求时间,分4批请求,每批间隔2秒。可以发现第一批5个是正常通过的,接下第2批前4个也是正常通过的,后面11个全被拒绝了。日志打印:
2019-08-22 13:12:03.245 |-ERROR [http-nio-8282-exec-2] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] [175] -| Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause com.alibaba.csp.sentinel.slots.block.degrade.DegradeException: null