Spring Cloud Demo
本文介绍Spring Cloud 常用的组件的demo代码。gitee代码:https://gitee.com/Aes_yt/spring-cloud-demo
包括Spring Cloud Eureka,Spring Cloud Feign,Spring Cloud Hystrix,Spring Cloud Ribbon,Spring Cloud Zuul,Spring Cloud Config,Spring Cloud Sleuth。
Spring Cloud Eureka
Server
- pom引入:
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
- </dependency>
复制代码 - 代码:
SpringBootApplication 启动类加入 @EnableEurekaServer注解。
- 配置:
- server:
- port: 8761
- eureka:
- instance:
- hostname: localhost
- client:
- register-with-eureka: false
- fetch-registry: false
- service-url:
- defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
- server:
- wait-time-in-ms-when-sync-empty: 0
- enable-self-preservation: false
复制代码 Client
- pom引入:
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
复制代码 - 代码:
SpringBootApplication 启动类加入 @EnableDiscoveryClient注解。
- 配置:
- server:
- port: 8081
- spring:
- application:
- name: demo-client1
- eureka:
- client:
- service-url:
- defaultZone: http://localhost:8761/eureka/
复制代码 TIPS. 非java语言也可使用Eureka提供的REST API接口接入Server。 wiki
常见问题
- 为什么服务上线了,Eureka Client 不能及时获取到。
Eureka Server 的 REST API 有response cache,需要等缓存过期后才能更新数据。
- 为什么服务下线了,Eureka Server 接口返回的信息还会存在。
应用实例异常挂掉,没有在挂掉之前告知Server 要下线。这个就需要依赖Eureka Server的EvictionTask 去剔除。
- 其他:
springcloud对springboot的版本是有要求的,如果不一致,会启动不起来的。详细可以看官网的版本要求。
Spring Cloud Feign + Spring Cloud Hystrix
demo-hello
- 首先先创建一个 demo 的 module,接入Eureka配置(eureka-client )。设置端口8082,里面只有一个get方法,我们用postman调用 http://localhost:8082/hello/testGet?param=hello,能够正常返回。
- @RestController
- @RequestMapping("/hello")
- @Slf4j
- public class HelloController {
- @GetMapping("/testGet")
- public BaseResp<String> testGet(@RequestParam("param") String param) {
- log.info("[demo-hello] testGet:{}", param);
- return BaseResp.success(param);
- }
- }
复制代码 yml:- server:
- port: 8082
- spring:
- application:
- name: demo-hello
- eureka:
- client:
- service-url:
- defaultZone: http://localhost:8761/eureka/
复制代码 feign-client
- 创建一个新module。引入Eureka-client依赖,feign依赖和hystrix依赖。
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
- </dependency>
复制代码 注意:hystrix 在 spring-cloud 2020.0.x 版本废弃,之后的版本推荐使用 Resilience4j 进行服务的熔断。
- yaml 配置
- server:
- port: 8083
- spring:
- application:
- name: feign-client
- eureka:
- client:
- service-url:
- defaultZone: http://localhost:8761/eureka/
- feign:
- # hystrix熔断开关
- hystrix:
- enabled: true
- # feign-client的超时时间
- client:
- config:
- default:
- connect-timeout: 3000
- read-timeout: 3000
- logger-level: basic
- # 设置hystrix服务降级超时时间
- hystrix:
- command:
- default:
- execution:
- isolation:
- thread:
- timeoutInMilliseconds: 15000
复制代码 - Application 注解
@EnableFeignClients:@EnableFeignClients 是一个 Spring Cloud 注解,用于启用 Feign 客户端的功能。
@EnableCircuitBreaker:@EnableCircuitBreaker 是 Spring Cloud 提供的一个注解,用于启用熔断器(Circuit Breaker)的功能。- @SpringBootApplication
- @EnableDiscoveryClient
- @EnableFeignClients
- @EnableCircuitBreaker
- public class FeignClientApplication {
- public static void main(String[] args) {
- SpringApplication.run(FeignClientApplication.class, args);
- }
- }
复制代码 - 建立Feign调用Service
- @FeignClient(name = "demo-hello", contextId = "feign-hello", path = "/hello", fallbackFactory = FeignHelloServiceHystrix.class)
- public interface FeignHelloService {
- @RequestMapping(value = "/testGet", method = RequestMethod.GET)
- BaseResp<String> testGet(@RequestParam("param") String param);
- }
复制代码 name = "demo-hello" 就是 demo 项目的 spring.application.name,contentxId 就相当于这个调用service的唯一id,path就是统一前缀。fallbackFactory 就是降级后的工厂。所以我们要实现这个工厂。
我这边的逻辑,就是记录一下日志,然后返回统一的错误对象。- @Slf4j
- @Component
- public class FeignHelloServiceHystrix implements FallbackFactory<FeignHelloService> {
- @Override
- public FeignHelloService create(Throwable cause) {
- log.error("feign调用helloController报错", cause);
- return new FeignHelloService() {
- public BaseResp<String> testGet(String param) {
- return BaseResp.error(param);
- }
- };
- }
- }
复制代码 - 测试一下,
- @GetMapping("/testGet")
- public BaseResp<String> testGet(@RequestParam("param") String param) {
- // try {
- // Thread.sleep(6000);
- // } catch (InterruptedException e) {
- // throw new RuntimeException(e);
- // }
- // if(!param.isEmpty()){
- // throw new RuntimeException("error...");
- // }
- log.info("[demo-hello] testGet:{}", param);
- return BaseResp.success(param);
- }
复制代码 testGet 6秒钟才响应或者直接抛出异常,都是会进入FeignHelloServiceHystrix中打印日志。
附加
<ol>Feign 加日志打印
<ol>xml配置Feign客户端- # Feign 日志配置
- logging:
- level:
- com.yt.demo.service.feign: debug
复制代码 Feign 配置- /**
- * Feign 配置
- */
- @Slf4j
- @Configuration
- public class FeignConfig {
- /**
- * NONE:不记录任何信息
- * BASIC:仅记录请求方法、URL以及响应状态码和执行时间.
- * HEADERS:除了记录BASIC级别的信息外,还会记录请求和响应的头信息
- * FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据
- */
- @Bean
- Logger.Level feignLoggerLevel() {
- return Logger.Level.FULL;
- }
- }
复制代码 效果如下:
[code]2023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] ---> POST http://demo-hello/hello/testPost HTTP/1.12023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] Content-Length: 302023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] Content-Type: application/json2023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] 2023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] {"param":"Post method: hello"}2023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] ---> END HTTP (30-byte body)2023-06-23 11:38:43.029 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] |