做网站干什么用,网站所有者查询,网站界面设计简单,wordpress cenos一、前言 接下来是开展一系列的 SpringCloud 的学习之旅#xff0c;从传统的模块之间调用#xff0c;一步步的升级为 SpringCloud 模块之间的调用#xff0c;此篇文章为第十六篇#xff0c;即使用 Sentinel 实现熔断功能。
二、 Ribbon 系列 首先我们新建两个服务的提供者…一、前言 接下来是开展一系列的 SpringCloud 的学习之旅从传统的模块之间调用一步步的升级为 SpringCloud 模块之间的调用此篇文章为第十六篇即使用 Sentinel 实现熔断功能。
二、 Ribbon 系列 首先我们新建两个服务的提供者模块 cloudalibaba-provider-payment9003 和 cloudalibaba-provider-payment9004这两个模块除了配置文件里面的端口号和主启动类不一样其他的都一样我这里只介绍其中一个模块的创建过程pom.xml 内容如下
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.springcloud/groupIdartifactIdSpringCloud/artifactIdversion1.0-SNAPSHOT/version/parentartifactIdcloudalibaba-provider-payment9003/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!--SpringCloud ailibaba nacos --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependencydependency!-- 引入自己定义的api通用包可以使用Payment支付Entity --groupIdcom.springcloud/groupIdartifactIdcloud-api-commons/artifactIdversion${project.version}/version/dependency!-- SpringBoot整合Web组件 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!--日常通用jar包配置--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies
/project application.yml 内容如下所示
server:port: 9003spring:application:name: nacos-payment-providercloud:nacos:discovery:server-addr: localhost:8848 #配置Nacos地址management:endpoints:web:exposure:include: * 主启动类代码如下
package com.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;SpringBootApplication
EnableDiscoveryClient
public class PaymentMain9003
{public static void main(String[] args) {SpringApplication.run(PaymentMain9003.class, args);}
} 对外提供的 controller 代码如下
package com.springcloud.controller;import com.springcloud.entities.CommonResult;
import com.springcloud.entities.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;RestController
public class PaymentController {Value(${server.port})private String serverPort;public static HashMapLong, Payment hashMap new HashMap();static{hashMap.put(1L,new Payment(1L,28a8c1e3bc2742d8848569891fb42181));hashMap.put(2L,new Payment(2L,bba8c1e3bc2742d8848569891ac32182));hashMap.put(3L,new Payment(3L,6ua8c1e3bc2742d8848569891xt92183));}GetMapping(value /paymentSQL/{id})public CommonResultPayment paymentSQL(PathVariable(id) Long id){Payment payment hashMap.get(id);CommonResultPayment result new CommonResult(200,from mysql,serverPort: serverPort,payment);return result;}
} 创建一个服务的消费者模块 cloudalibaba-consumer-nacos-order84pom.xml 内容如下所示
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.springcloud/groupIdartifactIdSpringCloud/artifactIdversion1.0-SNAPSHOT/version/parentartifactIdcloudalibaba-consumer-nacos-order84/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!--SpringCloud openfeign --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency!--SpringCloud ailibaba nacos --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!--SpringCloud ailibaba sentinel --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId/dependency!-- 引入自己定义的api通用包可以使用Payment支付Entity --dependencygroupIdcom.springcloud/groupIdartifactIdcloud-api-commons/artifactIdversion${project.version}/version/dependency!-- SpringBoot整合Web组件 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!--日常通用jar包配置--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies
/project application.yml 代码如下所示
server:port: 84spring:application:name: nacos-order-consumercloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:#配置Sentinel dashboard地址dashboard: localhost:8080#默认8719端口假如被占用会自动从8719开始依次1扫描,直至找到未被占用的端口port: 8719#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:nacos-user-service: http://nacos-payment-provider# 激活Sentinel对Feign的支持
feign:sentinel:enabled: true 主启动类代码如下
package com.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;EnableDiscoveryClient
SpringBootApplication
EnableFeignClients
public class OrderNacosMain84
{public static void main(String[] args) {SpringApplication.run(OrderNacosMain84.class, args);}
} 配置类代码如下使其支持负载均衡
package com.springcloud.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;Configuration
public class ApplicationContextConfig
{BeanLoadBalancedpublic RestTemplate getRestTemplate(){return new RestTemplate();}
} 业务类 controller 代码如下
Slf4j
RestController
public class CircleBreakerController {public static final String SERVICE_URL http://nacos-payment-provider;Resourceprivate RestTemplate restTemplate;RequestMapping(/consumer/fallback/{id})SentinelResource(value fallback) //没有配置public CommonResultPayment fallback(PathVariable Long id){CommonResultPayment result restTemplate.getForObject(SERVICE_URL /paymentSQL/id,CommonResult.class,id);if (id 4) {throw new IllegalArgumentException (IllegalArgumentException,非法参数异常....);}else if (result.getData() null) {throw new NullPointerException (NullPointerException,该ID没有对应记录,空指针异常);}return result;}
} 分别启动两个服务提供者和一个消费者启动完成后访问 http://localhost:84/consumer/fallback/1进行测试多刷新几次可以看到服务之间的调用没有任何问题且负载均衡好用。 当我们访问第四条和第五条数据时由于我们人为的配置了抛出异常给用户展示了 error 的界面效果并不是很好如下图 2.1 只配置 fallback 为了解决上面返回给客户不友好的界面我们可以配置 fallback 属性来解决这个问题它可以对业务的异常进行兜底修改 CircleBreakerController 类加上 fallback 属性和其对应的方法如下
Slf4j
RestController
public class CircleBreakerController {public static final String SERVICE_URL http://nacos-payment-provider;Resourceprivate RestTemplate restTemplate;RequestMapping(/consumer/fallback/{id})// SentinelResource(value fallback) //没有配置SentinelResource(value fallback, fallback handlerFallback) // fallback 只负责业务异常public CommonResultPayment fallback(PathVariable Long id) {CommonResultPayment result restTemplate.getForObject(SERVICE_URL /paymentSQL/ id, CommonResult.class, id);if (id 4) {throw new IllegalArgumentException(IllegalArgumentException,非法参数异常....);} else if (result.getData() null) {throw new NullPointerException(NullPointerException,该ID没有对应记录,空指针异常);}return result;}public CommonResult handlerFallback(PathVariable Long id, Throwable e) {Payment payment new Payment(id, null);return new CommonResult(444, 兜底异常handlerFallback,exception内容 e.getMessage(), payment);}
} 重启模块当我们再次访问第四条和第五条数据时效果就很好了如下图 2.2 只配置 blockHandler 修改 CircleBreakerController 类加上 blockHandler 属性和其对应的方法如下
Slf4j
RestController
public class CircleBreakerController {public static final String SERVICE_URL http://nacos-payment-provider;Resourceprivate RestTemplate restTemplate;RequestMapping(/consumer/fallback/{id})// SentinelResource(value fallback) //没有配置// SentinelResource(value fallback, fallback handlerFallback) // fallback 只负责业务异常SentinelResource(value fallback,blockHandler blockHandler) //blockHandler 只负责sentinel控制台配置违规public CommonResultPayment fallback(PathVariable Long id) {CommonResultPayment result restTemplate.getForObject(SERVICE_URL /paymentSQL/ id, CommonResult.class, id);if (id 4) {throw new IllegalArgumentException(IllegalArgumentException,非法参数异常....);} else if (result.getData() null) {throw new NullPointerException(NullPointerException,该ID没有对应记录,空指针异常);}return result;}public CommonResult blockHandler(PathVariable Long id, BlockException blockException) {Payment payment new Payment(id,null);return new CommonResult(445,blockHandler-sentinel限流,无此流水: blockException blockException.getMessage(),payment);}
} 配置完毕后打开 sentinel 的管理界面配置降级规则如下 在浏览器访问 http://localhost:84/consumer/fallback/4如果点击一次返回的还是 java 的运行时异常信息如下图 如果多点击几次则显示的是 blockHandler 指定的返回信息如下图 2.3 配置 fallback 和 blockHandler 若既配置了 fallback又配置了 blockHandler又会出现什么效果呢修改 CircleBreakerController 类代码如下
Slf4j
RestController
public class CircleBreakerController {public static final String SERVICE_URL http://nacos-payment-provider;Resourceprivate RestTemplate restTemplate;RequestMapping(/consumer/fallback/{id})// SentinelResource(value fallback) //没有配置// SentinelResource(value fallback, fallback handlerFallback) // fallback 只负责业务异常// SentinelResource(value fallback,blockHandler blockHandler) //blockHandler 只负责sentinel控制台配置违规SentinelResource(value fallback,fallback handlerFallback,blockHandler blockHandler)public CommonResultPayment fallback(PathVariable Long id) {CommonResultPayment result restTemplate.getForObject(SERVICE_URL /paymentSQL/ id, CommonResult.class, id);if (id 4) {throw new IllegalArgumentException(IllegalArgumentException,非法参数异常....);} else if (result.getData() null) {throw new NullPointerException(NullPointerException,该ID没有对应记录,空指针异常);}return result;}// 本例是 fallbackpublic CommonResult handlerFallback(PathVariable Long id,Throwable e) {Payment payment new Payment(id,null);return new CommonResult(444,兜底异常handlerFallback,exception内容 e.getMessage(),payment);}// 本例是 blockHandlerpublic CommonResult blockHandler(PathVariable Long id,BlockException blockException) {Payment payment new Payment(id,null);return new CommonResult(445,blockHandler-sentinel限流,无此流水: blockException blockException.getMessage(),payment);}
} 在 sentinel 中配置一个限流规则如下 在浏览器访问 http://localhost:84/consumer/fallback/1如果点击一次返回结果如下 频繁点击效果如下可以看到限流效果出现了。 在浏览器访问 http://localhost:84/consumer/fallback/4点击一次返回结果如下是 fallback 生效了。 频繁点击效果如下可以看到限流效果出现了。 2.4 结论 若 blockHandler 和 fallback 都进行了配置则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。
2.5 忽略属性 假如我有一个异常我不想让 fallback 方法帮我兜底我就可以通过配置 exceptionsToIgnore 属性来实现修改 CircleBreakerController 类的代码添加 exceptionsToIgnore 属性如下
Slf4j
RestController
public class CircleBreakerController {public static final String SERVICE_URL http://nacos-payment-provider;Resourceprivate RestTemplate restTemplate;RequestMapping(/consumer/fallback/{id})// SentinelResource(value fallback) //没有配置// SentinelResource(value fallback, fallback handlerFallback) // fallback 只负责业务异常// SentinelResource(value fallback,blockHandler blockHandler) //blockHandler 只负责sentinel控制台配置违规SentinelResource(value fallback,fallback handlerFallback,blockHandler blockHandler,exceptionsToIgnore {IllegalArgumentException.class})public CommonResultPayment fallback(PathVariable Long id) {CommonResultPayment result restTemplate.getForObject(SERVICE_URL /paymentSQL/ id, CommonResult.class, id);if (id 4) {throw new IllegalArgumentException(IllegalArgumentException,非法参数异常....);} else if (result.getData() null) {throw new NullPointerException(NullPointerException,该ID没有对应记录,空指针异常);}return result;}// 本例是 fallbackpublic CommonResult handlerFallback(PathVariable Long id,Throwable e) {Payment payment new Payment(id,null);return new CommonResult(444,兜底异常handlerFallback,exception内容 e.getMessage(),payment);}// 本例是 blockHandlerpublic CommonResult blockHandler(PathVariable Long id,BlockException blockException) {Payment payment new Payment(id,null);return new CommonResult(445,blockHandler-sentinel限流,无此流水: blockException blockException.getMessage(),payment);}
} 在 sentinel 中配置降级规则如下图 在浏览器中访问 http://localhost:84/consumer/fallback/4如下图可以发现fallback 方法并没有生效但是限流方法方法生效了 三、Feign 系列
3.1 maven 依赖 首先确保消费者模块 cloudalibaba-consumer-nacos-order84 的 pom.xml 中引入了 openFegin 的依赖如下
!--SpringCloud openfeign --
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId
/dependency
3.2 修改配置文件 接下来需要在 application.yml 中激活 sentinel 对 Feign 的支持如下 3.3 相关业务类 编写带有 FeignClient 注解的业务接口如下
package com.springcloud.service;import com.springcloud.entities.CommonResult;
import com.springcloud.entities.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;FeignClient(value nacos-payment-provider,fallback PaymentFallbackService.class)
public interface PaymentService
{GetMapping(value /paymentSQL/{id})public CommonResultPayment paymentSQL(PathVariable(id) Long id);
}然后编写 fallback 参数指定的的兜底方法的类代码如下
package com.springcloud.service;import com.springcloud.entities.CommonResult;
import com.springcloud.entities.Payment;
import org.springframework.stereotype.Component;Component
public class PaymentFallbackService implements PaymentService
{Overridepublic CommonResultPayment paymentSQL(Long id){return new CommonResult(44444,服务降级返回,---PaymentFallbackService,new Payment(id,errorSerial));}
} 修改 CircleBreakerController 类在里面添加如下的方法 Resourceprivate PaymentService paymentService;GetMapping(value /consumer/paymentSQL/{id})public CommonResultPayment paymentSQL(PathVariable(id) Long id){return paymentService.paymentSQL(id);} 不要忘了在启动类上添加启用 Feign 的注解如下图 3.4 测试 分别启动 cloudalibaba-provider-payment9003 模块和 cloudalibaba-consumer-nacos-order84 模块在浏览器输入http://localhost:84/consumer/paymentSQL/1如下图可以正常的访问 此时故意关闭 9003 微服务提供者看 84 消费侧自动降级会不会被耗死如下图可以看到自动进入到了我们指定的兜底方法里面了。 四、熔断框架比较