SpringCloud 学习笔记总结

Posted IT_Holmes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud 学习笔记总结相关的知识,希望对你有一定的参考价值。

文章目录

git代码地址:https://gitee.com/it-sherlock/java-project-template

1. OpenFeign 之 介绍


OpenFeign官方地址:https://spring.io/projects/spring-cloud-openfeign/

OpenFeign Github官方地址:https://github.com/spring-cloud/spring-cloud-openfeign

feign英文翻译:假装,佯装。

Feign是一个声明式WebService客户端,让编写Web服务客户端变得非常容易,只需要创建一个接口并在接口上添加注解即可。

之前是通过ribbon + restTemplate方式封装处理,形成一套模板化的调用方法。

现在,feign集成了ribbon,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。

现在OpenFeign已经取代了Feign:

2. OpenFeign 之 消费端的 服务调用


feign是定义在消费端的。

简单说就是,更加简便了:只需要 微服务调用接口 + @FeignClient注解,就能实现。


第一步:添加OpenFeign的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

第二步:主启动类,添加激活feign的注解@EnableFeignClients:

package com.itholmes.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients//使用feign,激活开启feign
public class OrderFeignMain80 
    public static void main(String[] args) 
        SpringApplication.run(OrderFeignMain80.class,args);
    


第三步:写一个service接口,配置好@FeignClient注解对应。

package com.itholmes.springcloud.service;

import com.itholmes.springcloud.entities.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService 
    /**
     * 这时候就是去注册中心找一个CLOUD-PAYMENT-SERVICE名称的微服务加上对应地址。
     */
    @GetMapping("/payment/get/id")
    public CommonResult getPaymentById(@PathVariable("id") Long id);

3. OpenFeign 之 超时控制


OpenFeign默认等待1秒钟,超过后就报错read time out。

# 设置feign 客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  # 指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  # 指的是进建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000

4. OpenFeign 之 日志增强


Feigon 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解Feign中Http请求的细节。对Feign接口的调用情况进行监控和输出。

OpenFeign的日志级别:


配置类设置日志级别:

package com.itholmes.springcloud.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig 

    //设置日志级别
    @Bean
    Logger.Level feignLoggerLevel()
        return Logger.Level.FULL;
    


feign日志以什么级别监控那个接口:

server:
  port: 80

eureka:
  client:
    # 表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    # 入驻地址是哪个
    service-url:
      #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      #defaultZone: http://localhost:7001/eureka #单机版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  #集群版

# 设置feign 客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  # 指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  # 指的是进建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000

logging:
  level:
    # feign日志以什么级别监控哪个接口
    com.itholmes.springcloud.service.PaymentFeignService: debug

日志如下:

5. Hystrix 之 重要概念


分布式系统面临的问题:

  • 相互之间都是微服务调用,一个过程,可能要走好多微服务系统,其中一个微服务系统出现问题,整个过程就相当于失败了。

服务雪崩:

  • 多个微服务相互依赖调用的时候,微服务A调用微服务B,微服务B调用微服务C,微服务C有调用其他微服务,这就是扇出效果(像一把扇子,不断张开)
  • 如果一个微服务出现了问题(超时,宕机等等),例如:微服务C宕机了,那么微服务B就会不断堆积请求(请求的线程阻塞),微服务B占用越来越多的系统资源,进而微服务B系统也崩溃了,微服务B崩溃了,同样A也会不断堆积进而崩溃掉,这就是雪崩效果。

为了解决上面的问题,就有了熔断降级的思想。

Hystrix是一个用于处理分布式系统的延迟 和 容错的开源库。

在分布式系统里,许多依赖不可避免的会调用失败,比如:超时,异常等。

Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。


断路器:(熔断保险丝)

官方地址:https://github.com/Netflix/Hystrix


服务降级:

  • 就是返回一个友好提示(fallback),例如:服务器忙,请稍后再试;不让客户端等待并且立刻返回一个友好提示(fallback)。

那些情况下会触发降级:

  • 程序运行异常。
  • 超时。
  • 服务熔断触发服务降级。
  • 线程池 / 信号量 打满也会导致服务降级。

服务熔断:

  • 类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示。
  • 熔断过程:服务降级 -》 进而熔断 -》 恢复调用链路

服务限流:

  • 像秒杀,高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行,这就是服务限流。

6. jmeter 普通服务测试


使用jmeter来测试。


在线程组里面,设定200个线程,1秒内发送请求,循环100次。之后,再次通过浏览器访问两个接口,都有严重的卡顿。

原因就是:tomcat的默认工作线程数被打满了,没有多余的线程来分担压力和处理。


这样就是雪崩效应。

7. Hystrix 之 服务提供 和 服务消费 环境搭建


第一步:导入hystrix依赖:

<!--添加eureka-client客户端-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--添加openFeign依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--添加hystrix依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

第二步:搭建好SpringBoot项目。

第三步:使用openFeign,链接好消费者和提供者之间的调用。

第四步:使用Jmeter来测试,高并发的请求。

  • 通过测试,不难看出,一旦高并发的请求进来,就会导致严重的卡顿。

解决思想:

如何解决上面问题:

8. Hystrix 之 服务降级 消费端和服务端


官方github文档使用方式是通过程序:


这里使用@HystrixCommand注解:

@HystrixCommand报异常后的处理过程:

  • 一旦调用服务方法失败,并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法。

服务端降级代码如下:

第一步:service层逻辑代码:

package com.itholmes.springcloud.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService 

    public String paymentInfo_OK(Integer id)
        return "线程池: " + Thread.currentThread().getName() + "paymentInfo_OK,id:"+id+"\\t"+"hello,world";
    

    //一旦调用服务方法失败,并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法。
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = 
        // 超过3秒走兜底的错误方法。
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    )
    public String paymentInfo_TimeOut(Integer id)
        int timeNumber = 5;
        //无论是异常还是其他的,都会引起指定的兜底方法执行。
		//int age = 10/0;
        try 
            TimeUnit.SECONDS.sleep(timeNumber);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        return "线程池: " + Thread.currentThread().getName() + "paymentInfo_OK,id:"+id+"\\t"+"hello,world。"+"耗时(秒)"+timeNumber+"秒钟";
    

	// 被上面指定兜底的方法
    public String paymentInfo_TimeOutHandler(Integer id)
        return "线程池: " + Thread.currentThread().getName() + "8001系统繁忙,请稍后再试,id:"+id+"\\t"+"GG.";
    
    

第二步:主启动类,添加注解@EnableCircuitBreaker。

package com.itholmes.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001 
    public static void main(String[] args) 
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    

这样,当我们访问这个服务提供者就会有兜底方法来帮我们处理超时,异常等情况。


客户端服务降级代码如下:

  • 一般我们在客户端进行服务降级!

第一步:因为客户端是通过openfeign来调用的,所以在feign要开启hystrix。

server:
  port: 80

eureka:
  client:
    # 表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    # 入驻地址是哪个
    service-url:
      #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka #单机版
      # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  #集群版
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000

# 在feign中开启hystrix
feign:
  hystrix:
    enabled: true

第二步:主启动类上面添加@EnableHystrix注解。

package com.itholmes.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80 
    public static void main(String[] args) 
        SpringApplication.run(OrderHystrixMain80.class,args);
    

第三步:对于消费端(客户端),一般采用openfeign调用服务端,注解@HystrixCommand也配置在了controller层中。

package com.itholmes.springcloud.controller;

import com.itholmes.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
public class PaymentHystrixController 
    @Resource
    private PaymentHystrixService paymentHystrixService;

    /**
     * 这里与服务端不同!
     *  服务端在service层添加的@HystrixCommand注解。
     *  在openfeign的消费端,是在controller层添加@HystrixCommand注解。
     */
    @GetMapping("/consumer/payment/hystrix/timeout/id")
    @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = 
            // 超过3秒走兜底的错误方法。
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")
    )
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    

    public String paymentTimeOutFallbackMethod(@PathVariable("id")Integer id)
        return "我是消费者80,对方支付系统繁忙或自身运行出错!";
    

9. Hystrix 之 全局服务降级@DefaultProperties


如果想要统一的有一个兜底的代码来处理,也就是全局服务降级的效果。

使用@DefaultProperties(defaultFallback = “”) 来实现。


@DefaultProperties(defaultFallback = “”) 注解的使用如下:

package com.itholmes.springcloud.controller;

import com.itholmes.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
//指名全局
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class PaymentHystrixController 

    @Resource
    private PaymentHystrixService paymentHystrixService;

    @GetMapping("/consumer/payment/hystrix/id")
    public String paymentInfo_OK(@PathVariable("id") Integer id)
        String result = paymentHystrixService.paymentInfo_OK(id);
        return result;
    

    @GetMapping("/consumer/payment/hystrix/timeout/id")
    //对于有@HystrixCommand注解指定的fallbackMethod,就走指定的服务降级兜底的方法。
    @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = 
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")
    )
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    

    @GetMapping("/consumer/payment/hystrix/timeout2/id")
    //使用全局的fallback
    @HystrixCommand
    public String paymentInfo_TimeOut2(@PathVariable("id") Integer id)
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    

    public String paymentTimeOutFallbackMethod(@PathVariable("id")Integer id)
        return "我是消费者80,对方支付系统繁忙或自身运行出错!";
    

    //全局fallback方法
    public String payment_Global_FallbackMethod()
        return "Global 全局的服务降级,返回信息。系统方法请稍后重试。";
    


10. Hystrix 之 通配服务降级


通过@FeignClient注解里面的fallback参数来配置。

第一步:创建一个实现 当前使用OpenFeign对应的service接口 的一个实现类。

package com.itholmes.springcloud.service;

import org.springframework.stereotype.Component;

//实现了PaymentHystrixService,该类就是使用的OpenFeign远程调用。
//不要忘记装配到ioc容器中。
@Component
public class PaymentFallbackService implements PaymentHystrixService
    @Override
    public String paymentInfo_OK(Integer id) 
        return "paymentInfo_OK fallback";
    

    @Override
    public String paymentInfo_TimeOut(Integer id) 
        return "paymentInfo_TimeOut fallback";
    

以上是关于SpringCloud 学习笔记总结的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud 学习笔记总结

SpringCloud 学习笔记总结

SpringCloud 学习笔记总结

SpringCloud 学习笔记总结

SpringCloud 学习笔记总结

SpringCloud 学习笔记总结