省略…
(1)新建maven模块: cloudalibaba-provider-payment9003
(2)改pom:
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.csp
sentinel-datasource-nacos
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
cn.hutool
hutool-core
5.6.5
(3)写yml:
server:
port: 9003
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery: #注册中心的地址
server-addr: 192.168.211.205:1111 #这里做了nginx的均衡负载
management: #springboot端点暴露,这里我们暴露所有端点
endpoints:
web:
exposure:
exclude: '*'
(4)主启动类:com.fan.springcloud.PaymentProviderMain9003
package com.fan.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentProviderMain9003 {
public static void main(String[] args) {
SpringApplication.run(PaymentProviderMain9003.class,args);
}
}
(5)业务类:controller.PaymentController:
package com.fan.springcloud.controller;
import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.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 HashMap hashMap = new HashMap();
//模拟数据库,存了三条记录
static{
hashMap.put(1L,new Payment(1L,"1234567890QWERTYUIOP1"));
hashMap.put(2L,new Payment(2L,"1234567890QWERTYUIOP2"));
hashMap.put(3L,new Payment(3L,"1234567890QWERTYUIOP3"));
}
@GetMapping(value = "/paymentSQL/{id}")
public CommonResult paymentSQL(@PathVariable("id") Long id ){
Payment payment = hashMap.get(id);
CommonResult paymentCommonResult =
new CommonResult<>(200, "来自数据库,端口号:" +
serverPort, payment);
return paymentCommonResult;
}
}
同理,新建一个提供者cloudalibaba-provider-payment9004:
测试:启动两个微服务9003和9004:
网页测试地址:localhost:9003/paymentSQL/1
(1)新建消费者模块:cloudalibaba-consumer-nacos-order84
(2)修改pom:
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.csp
sentinel-datasource-nacos
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
cn.hutool
hutool-core
5.6.5
(3)写yml:
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: 192.168.211.205:1111
sentinel:
transport:
dashboard: localhost:8080 #配置sentinel 的仪表盘地址
port: 8719 #默认仪表盘8719端口
#消费者将要去访问的微服务的名称(注册成功进nacos的微服务提供者
service-url:
nacos-user-service: http://nacos-payment-provider
(4)主启动类:com.fan.springcloud.OrderNacosMain84
package com.fan.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class OrderNacosMain84 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain84.class,args);
}
}
(5)业务类:
负载均衡配置类:config.ApplicationContextConfig:
package com.fan.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 {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
controller.CircleBreakerController类:分如下几种情况:
情况一:没有任何配置:给客户error页面,不友好
package com.fan.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
//依赖注入restTemplate
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}") //restful风格的路径参数
@SentinelResource(value = "fallback") //没有配置
public CommonResult fallback(@PathVariable("id") Long id){
log.info("测试fallback------");
CommonResult result =
restTemplate.getForObject("http://nacos-payment-provider/paymentSQL/"+id,CommonResult.class,id);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException:非法参数异常。。。。");
}else if(result.getData() == null){
throw new NullPointerException("NullPointerException:该id没有对应的记录,空指针异常!!!");
}
return result;
}
}
测试地址:localhost:84/consumer/fallback/1
多刷新几下地址:发现负载均衡到9003和9004端口:
当数据库没有查到数据的时候出现错误页面,不友好:
情况二:带fallback:
fallback只负责java业务逻辑异常:
package com.fan.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
//依赖注入restTemplate
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}") //restful风格的路径参数
//@SentinelResource(value = "fallback") //没有配置
@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责java业务逻辑异常
public CommonResult fallback(@PathVariable("id") Long id){
log.info("测试fallback------");
CommonResult result =
restTemplate.getForObject("http://nacos-payment-provider/paymentSQL/"+id,CommonResult.class,id);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException:非法参数异常。。。。");
}else if(result.getData() == null){
throw new NullPointerException("NullPointerException:该id没有对应的记录,空指针异常!!!");
}
return result;
}
//兜底应急fallback方法handlerFallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e){
Payment payment = new Payment(id,"null");
return new CommonResult(444,"兜底应急fallback方法handlerFallback," +
"异常内容"+e.getMessage(),payment);
}
}
测试:http://localhost:84/consumer/fallback/4
测试:http://localhost:84/consumer/fallback/5
情况三:带blockhandler:
blockHandler只负责sentinel控制台配置违规:
测试:
情况四:两种都配置:
package com.fan.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
//依赖注入restTemplate
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}") //restful风格的路径参数
//@SentinelResource(value = "fallback") //没有配置
//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责java业务逻辑异常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",blockHandler = "blockHandler",fallback = "handlerFallback") //blockHandler只负责sentinel控制台配置违规
public CommonResult fallback(@PathVariable("id") Long id){
log.info("测试fallback------");
CommonResult result =
restTemplate.getForObject("http://nacos-payment-provider/paymentSQL/"+id,CommonResult.class,id);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException:非法参数异常。。。。");
}else if(result.getData() == null){
throw new NullPointerException("NullPointerException:该id没有对应的记录,空指针异常!!!");
}
return result;
}
//兜底应急fallback方法handlerFallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e){
Payment payment = new Payment(id,"null");
return new CommonResult(444,"兜底应急fallback方法handlerFallback," +
"异常内容"+e.getMessage(),payment);
}
//blockHandler的限流异常处理
public CommonResult blockHandler(@PathVariable("id") Long id, BlockException blockException){
Payment payment = new Payment(id, "null");
return new CommonResult(445,"blockHandler-sentinel限流处理," +
"无此流水,blockException:"+blockException.getMessage());
}
}
忽略异常:
pom:
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.csp
sentinel-datasource-nacos
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
cn.hutool
hutool-core
5.6.5
yml:
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos: #nacos服务发现地址
discovery:
server-addr: 192.168.211.205:1111
sentinel: #sentinel监控端口和地址
transport:
dashboard: localhost:8080 #配置sentinel 的仪表盘地址
port: 8719 #默认仪表盘8719端口
#消费者将要去访问的微服务的名称(注册成功进nacos的微服务提供者
service-url:
nacos-user-service: http://nacos-payment-provider
#激活sentinel对openfeign的 支持
feign:
sentinel:
enabled: true
主启动类:
package com.fan.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;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderNacosMain84 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain84.class,args);
}
}
原先不使用openFeign时,我们是在controler中通过中间的restTemplate来进行远程调用,现在换成接口调用的形式,方便。
openfeign 接口:
package com.fan.springcloud.service;
import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.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 CommonResult paymentSQL(@PathVariable("id") Long id);
}
接口的实现类:这里也是兜底的类:
package com.fan.springcloud.service;
import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.Payment;
import org.springframework.stereotype.Component;
@Component
public class PaymentFallbackService implements PaymentService{
@Override
public CommonResult paymentSQL(Long id) {
return new CommonResult<>(4444,"服务降级返回,PaymentFallbackService" +
"",new Payment(id,"错误"));
}
}
controller:
package com.fan.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.fan.springcloud.entity.CommonResult;
import com.fan.springcloud.entity.Payment;
import com.fan.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
//依赖注入restTemplate
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}") //restful风格的路径参数
//@SentinelResource(value = "fallback") //没有配置
//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责java业务逻辑异常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",blockHandler = "blockHandler",fallback = "handlerFallback") //blockHandler只负责sentinel控制台配置违规
public CommonResult fallback(@PathVariable("id") Long id){
log.info("测试fallback------");
CommonResult result =
restTemplate.getForObject("http://nacos-payment-provider/paymentSQL/"+id,CommonResult.class,id);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException:非法参数异常。。。。");
}else if(result.getData() == null){
throw new NullPointerException("NullPointerException:该id没有对应的记录,空指针异常!!!");
}
return result;
}
//兜底应急fallback方法handlerFallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e){
Payment payment = new Payment(id,"null");
return new CommonResult(444,"兜底应急fallback方法handlerFallback," +
"异常内容"+e.getMessage(),payment);
}
//blockHandler的限流异常处理
public CommonResult blockHandler(@PathVariable("id") Long id, BlockException blockException){
Payment payment = new Payment(id, "null");
return new CommonResult(445,"blockHandler-sentinel限流处理," +
"无此流水,blockException:"+blockException.getMessage());
}
//openfeign
@Resource
private PaymentService paymentService;
@GetMapping(value = "consumer/paymentSQL/{id}")
public CommonResult paymentSQL(@PathVariable("id") Long id ){
return paymentService.paymentSQL(id);
}
}
测试:http://localhost:84/consumer/paymentSQL/1
看是否自动降级:关闭所有的微服务提供者9003和9004,然后测试:http://localhost:84/consumer/paymentSQL/1