Spring Cloud Alibaba 使用 Feign+Sentinel 完成熔断的示例
Feign的使用
Feign也是网飞开发的,SpringCloud使用Feign非常简单,我下边演示一下:
首先服务消费者这边肯定需要一个对应的依赖:
compile("org.springframework.cloud:spring-cloud-starter-openfeign")
需要启用Feign的话,也得在启动类上面加个注解@EnableFeignClients
然后,创建一个Feign的接口,像这样子
packagecom.skypyb.sc.feign; importcom.skypyb.sc.entity.User; importorg.springframework.cloud.openfeign.FeignClient; importorg.springframework.web.bind.annotation.PathVariable; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RequestMethod; @FeignClient("sc-demo-microservice-user") publicinterfaceUserFeignClient{ @RequestMapping(value="/user/{id}",method=RequestMethod.GET) publicUsergetUser(@PathVariable("id")Longid); }
@FeignClient注解里边的默认属性,也就是name属性是一个客户端的名字,如果使用了Eureka的话,会给他自动解析为EurekaServer服务注册表中的服务。
要是配了Ribbon,也会使用默认的负载均衡策略来执行请求。
Feign默认使用SpringMVC的注解声明请求,当然也可以用Feign自带的注解。不过没啥必要,还需要配置东西。
我上边这个例子写完了,实际使用的话只需要注入该类然后调用对应的方法就完事了。非常简便。
packagecom.skypyb.sc.controller; importcom.skypyb.sc.entity.User; importcom.skypyb.sc.feign.UserFeignClient; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.cloud.client.ServiceInstance; importorg.springframework.cloud.client.discovery.DiscoveryClient; importorg.springframework.cloud.client.loadbalancer.LoadBalancerClient; importorg.springframework.web.bind.annotation.GetMapping; importorg.springframework.web.bind.annotation.PathVariable; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController; importorg.springframework.web.client.RestTemplate; importjava.util.List; @RestController @RequestMapping("/movie") publicclassMovieController{ privateLoggerlogger=LoggerFactory.getLogger(MovieController.class); @Autowired privateUserFeignClientuserFeignClient; @GetMapping("/user/{id}") publicUsergetUser(@PathVariable("id")Longid){ returnuserFeignClient.getUser(id); } }
不过有几个点需要注意
在使用@FeignClient声明的Feign伪装类中:
使用@PathVariable注解,必须加上参数!
GET请求无法使用对象作为入参!要不有多少参数写多少参数(每个都要加@RequestParam(“参数名”)注解),要不就用接受一个Map对象,也得加@RequestParam
POST请求可以接收对象,需要加上@RequestBody注解
Feign论使用的话,其实已经差不多了。
但是还有一些相关的操作也比较重要。
Feign的请求都是使用的默认配置,我们其实可以实现自己的配置供Feign使用以实现编码、解码、日志记录、验证等等等等。
比如我可以这么定义一个配置类:
packagecom.skypyb.sc.config; importfeign.Logger; importfeign.auth.BasicAuthRequestInterceptor; importorg.springframework.context.annotation.Bean; publicclassFeignConfiguration{ @Bean publicLogger.LevelfeignLog(){ returnLogger.Level.FULL; } /** *使用指定的用户名和密码验证所有请求 *@return */ @Bean publicBasicAuthRequestInterceptorbasicAuthRequestInterceptor(){ returnnewBasicAuthRequestInterceptor("user","614"); } }
该类配置了对应的日志记录器,和一个简单的效验,以应对请求的验证。
在对应的Feign伪装类中,上边的@FeignClient注解改一下,就可以使用自己写的配置:
@FeignClient(name="sc-demo-microservice-user",configuration=FeignConfiguration.class)
之所以在@FeignClient注解中指定配置,是因为我的配置类是没有加@Configuration注解的,我想要实现细粒度的控制。推荐这样做。
如果加了@Configuration注解,则Spring会将其自动解析自动应用到全局,这样子就不方便为每个请求进行细粒度调整。
Alibaba的使用
首先肯定是要上pom.xml配置起来。加上对应的依赖。
com.alibaba.cloud spring-cloud-starter-alibaba-sentinel org.springframework.cloud spring-cloud-starter-openfeign
接着写个Feign接口
packagecom.skypyb.provider.feign; importcom.skypyb.provider.fallback.HelloServiceFallback; importorg.springframework.cloud.openfeign.FeignClient; importorg.springframework.web.bind.annotation.PathVariable; importorg.springframework.web.bind.annotation.RequestMapping; /** *Feign客户端 *指定调用sc-demo-alibaba-provider的服务 */ @FeignClient(value="sc-demo-alibaba-provider",fallback=HelloServiceFallback.class) publicinterfaceNacosHelloFeign{ @RequestMapping(value="/provider/hello/{msg}") Stringhello(@PathVariable("msg")Stringmsg); }
调用的话就是这样子调用:
packagecom.skypyb.provider.controller; importcom.skypyb.provider.feign.NacosHelloFeign; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.cloud.client.ServiceInstance; importorg.springframework.cloud.client.loadbalancer.LoadBalancerClient; importorg.springframework.web.bind.annotation.GetMapping; importorg.springframework.web.bind.annotation.PathVariable; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController; importorg.springframework.web.client.RestTemplate; importjavax.annotation.Resource; @RequestMapping("/consumer") @RestController publicclassNacosConsumerController{ @Autowired privateLoadBalancerClientloadBalancerClient; @Autowired privateRestTemplaterestTemplate; @Resource privateNacosHelloFeignnacosHelloFeign; @GetMapping(value="/hello/{msg}") publicStringhello(@PathVariable("msg")Stringmsg){ //使用LoadBalanceClient和RestTemplate结合的方式来访问 ServiceInstanceserviceInstance=loadBalancerClient.choose("sc-demo-alibaba-provider"); Stringurl=String.format("http://%s:%s/provider/hello/%s", serviceInstance.getHost(),serviceInstance.getPort(),msg); returnrestTemplate.getForObject(url,String.class); } @GetMapping(value="/hello/feign/{msg}") publicStringhelloFeign(@PathVariable("msg")Stringmsg){ returnnacosHelloFeign.hello(msg); } }
哎,观察我的NacosHelloFeign类,这里可以看到,我这用了一个fallback回退,这个回退指定的就是Sentinel的实现,其实写起来和特么的Hystrix一模一样。不得不说SpringCloud这一点是真的做得好。
packagecom.skypyb.provider.fallback; importcom.skypyb.provider.feign.NacosHelloFeign; importorg.springframework.stereotype.Component; /** *熔断类 *要是Feign的接口调用失败(或者被快速失败)就会走这个类的方法进行处理 */ @Component publicclassHelloServiceFallbackimplementsNacosHelloFeign{ @Override publicStringhello(Stringmsg){ return"触发熔断机制~"; } }
哎,观察我的NacosHelloFeign类,这里可以看到,我这用了一个fallback回退,这个回退指定的就是Sentinel的实现,其实写起来和特么的Hystrix一模一样。不得不说SpringCloud这一点是真的做得好。
packagecom.skypyb.provider.fallback; importcom.skypyb.provider.feign.NacosHelloFeign; importorg.springframework.stereotype.Component; /** *熔断类 *要是Feign的接口调用失败(或者被快速失败)就会走这个类的方法进行处理 */ @Component publicclassHelloServiceFallbackimplementsNacosHelloFeign{ @Override publicStringhello(Stringmsg){ return"触发熔断机制~"; } }
当然,配置肯定是得配置的,他也不会直接就给你用了。
Sentinel虽说是适配了Feign组件。但默认是关闭的。需要在配置文件中配置打开它,在配置文件增加以下代码:
feign: sentinel: enabled:true
其实到现在,整个Feign的使用+熔断限流机制就已经配完了。
不过Sentinel比起Hystrix真正优越的地方还没来呢。
那就是:控制台。
这个控制台功能丰富、UI好看,比Hystrix那是高到不知道哪里去了。
要是用控制台,又不得不下载代码、打包、编译、运行。
所幸,我们有神器docker。我在dockerhub上找了个镜像,直接用就可以了,镜像地址:https://hub.docker.com/r/bladex/sentinel-dashboard
直接执以下命令,将sentinel控制台起开绑到8858端口
dockerpullbladex/sentinel-dashboard dockerrun--namesentinel-d-p8858:8858-dbladex/sentinel-dashboard
然后自己的yml文件也得改一下,毕竟都上控制台了,也得把自己这个服务给注册进去。
全部的yml文件如下所示:
spring: application: name:sc-demo-alibaba-consumer cloud: nacos: discovery: server-addr:192.168.1.14:8848#注册进nacos sentinel: transport: port:18081#这个端口的意思是自己这个服务开个端口和sentinel控制台交互 dashboard:192.168.1.14:8858#sentinel控制台的端口 server: port:8081 feign: sentinel: enabled:true management: endpoints: web: exposure: include:"*"
可以看到配置里有一个sentinel.transport.port属性,这个属性的意思是在自己本体这个服务里边,在开个新的端口专门用来和Sentinel控制台交互
Sentinel控制台自身也有,默认端口则是8719
到这里就差不多了,所有东西打开,然后就可以访问http://ip:8858进入Sentinel控制台,默认账号密码都是sentinel
有一点还需要注意,那就是为了确保客户端有访问量,Sentinel会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。意思就是说你一个服务注册进我这来,首先还是看不到的。
你得先经过别人的请求,我才会去监控你,所以在服务刚启动的时候进入Sentinel控制台找不到自己的服务是很正常的,只要启动时没有报错就不会有问题。
以上就是SpringCloudAlibaba使用Feign+Sentinel完成熔断的示例的详细内容,更多关于SpringCloudAlibaba使用Feign+Sentinel完成熔断的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。