Spring Cloud Demo

2023年 8月 1日 27.3k 0

Spring Cloud Demo

本文介绍Spring Cloud 常用的组件的demo代码。gitee代码:gitee.com/Aes_yt/spri…

包括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引入:

    
    	org.springframework.cloud
        spring-cloud-starter-netflix-eureka-server
    
    
  • 代码:

    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引入:

    
    	org.springframework.cloud
    	spring-cloud-starter-netflix-eureka-client
    
    
  • 代码:

    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 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依赖。

    
        org.springframework.cloud
        spring-cloud-starter-netflix-eureka-client
    
    
        org.springframework.cloud
        spring-cloud-starter-openfeign
    
    
    
        org.springframework.cloud
        spring-cloud-starter-netflix-hystrix
    
    

    注意: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 testGet(@RequestParam("param") String param);
    }
    

    name = "demo-hello" 就是 demo 项目的 spring.application.name,contentxId 就相当于这个调用service的唯一id,path就是统一前缀。fallbackFactory 就是降级后的工厂。所以我们要实现这个工厂。

    我这边的逻辑,就是记录一下日志,然后返回统一的错误对象。

    @Slf4j
    @Component
    public class FeignHelloServiceHystrix implements FallbackFactory {
        @Override
        public FeignHelloService create(Throwable cause) {
            log.error("feign调用helloController报错", cause);
            return new FeignHelloService() {
                public BaseResp testGet(String param) {
                    return BaseResp.error(param);
                }
            };
        }
    }
    
  • 测试一下,

        @GetMapping("/testGet")
        public BaseResp 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中打印日志。

  • 附加

  • Feign 加日志打印

  • 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;
        }
    }
    
  • 效果如下:

    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.1
    2023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] Content-Length: 30
    2023-06-23 11:38:43.026 DEBUG 496 --- [ix-demo-hello-4] c.y.d.service.feign.FeignHelloService : [FeignHelloService#testPost] Content-Type: application/json
    2023-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]

  • 相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论