SpringCloud学习-2

SpringCloud学习第二天

Eureka相关配置
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10087/eureka  # 设置eureka服务注册的地址
    register-with-eureka: false # 不注册自己,自己不会显示在服务列表中
    registry-fetch-interval-seconds: 30 # 获取服务列表
  instance:
    prefer-ip-address: true # 写死ip地址为本机127.0.0.1
    ip-address: 127.0.0.1
    lease-renewal-interval-in-seconds: 30 # 心跳时长,30s发送一次
    lease-expiration-duration-in-seconds: 90  # 过期时长,90s没有响应表示挂了,标记需要剔除
  server:
    enable-self-preservation: false # 关闭自我保护模式(缺省为打开),自我保护:判断是否有网络问题,停止失效剔除
    eviction-interval-timer-in-ms: 60000 # 扫描失效服务的间隔时长,到时间后一次性剔除(缺省为60*1000ms)
Ribbon负载均衡

启动两台user-service tomcat服务,端口分别为8081,8082

![image-20230627102259943](/Users/zyh/Library/Application Support/typora-user-images/image-20230627102259943.png)

在consumer的pom文件中引入ribbon

<!-- 负载均衡 -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

实现user-service负载均衡

方法一:修改ConsumerController

@RestController
@RequestMapping("consumer")
public class ConsumerController {
  @Autowired
  private RestTemplate restTemplate;
  
  @Autowired
  private LoadBalancerClient client; // Ribbon
  
  @GetMapping("{id}")
  public String queryById(@PathVariable("id") Long id) {
    ServiceInstance instance = client.choose("user-service");	// 拿到一个经过负载均衡计算后的服务
    // 拼接url
    String url = "http://"+instance.getHost()+":"+instance.getPort()+"/user/" + id; 
    String user = restTemplate.getForObject(url, String.class);
    return user
  }
}  

启动访问,可以随机获取8081和8082的服务

方法二:

在启动类中的RestTemplate上添加@LoadBalanced

@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {

    @LoadBalanced   // 实现负载均衡
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();  // restTemplate获取到可以调用其他服务器接口的实例对象
    }

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class);
    }
}

修改ConsumerController

@RestController
@RequestMapping("consumer")
public class ConsumerController {
  @Autowired
  private RestTemplate restTemplate;
  
  @GetMapping("{id}")
  public String queryById(@PathVariable("id") Long id) {
    
    // 使用注解方式实现负载均衡
    String url = "http://user-service/user/"+id;
    String user = restTemplate.getForObject(url, String.class);
    return user
  }
}  

原理:底层通过LoadBalancerInterceptor拦截器,根据服务名动态获取服务ip地址,实现默认的轮徇调用可用服务

Ribbon配置

consumer application.yml

user-service:	# 要调用的服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  # 配置负载均衡方式为:随机
Hystrix保护机制

在分布式应用中有着许多的服务,某个服务可能存在调用失败的情况,在服务之间调用时会出现阻塞的情况,当访问过大时,问题会更加严重,导致许多请求无法响应,从而耗尽服务器资源,整个集群宕机,称为雪崩效应。

线程隔离和服务降级

服务调用方consumer使用Hystrix

<!-- hystrix -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

启动类

@EnableCircuitBreaker   // Hystrix熔断器
@EnableDiscoveryClient
@SpringBootApplication
// @SpringCloudApplication 等同于上面三个注解
public class ConsumerApplication {

    @LoadBalanced   // 实现负载均衡
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();  // restTemplate获取到可以调用其他服务器接口的实例对象
    }

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class);
    }
}

修改user-service项目 UserService

@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    public User queryById(Long id) {
    		// 模拟服务器超时,休眠2s
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        User user = userDao.selectByPrimaryKey(id);
        return user;
    }
}

修改ConsumerController

1、在单个方法上使用Hystrix

@RestController
@RequestMapping("consumer")
public class ConsumerController {
  @Autowired
  private RestTemplate restTemplate;
  
  @GetMapping("{id}")
  @HystrixCommand(fallbackMethod = "queryByIdFallback") // 开启服务的线程隔离和服务降级处理(熔断处理)
  public String queryById(@PathVariable("id") Long id) {
    
    // 使用注解方式实现负载均衡
    String url = "http://user-service/user/"+id;
    String user = restTemplate.getForObject(url, String.class);
    return user
  }
  
  // 服务降级方法,两个方法的返回值和参数必须一致
  public String queryByIdFallback(Long id) {
    return "服务器拥挤,请稍后再试";
  }
} 

2、在类上统一使用

@DefaultProperties(defaultFallback = "defaultFallback")  // 统一的降级逻辑处理
@RestController
@RequestMapping("consumer")
public class ConsumerController {
  @Autowired
  private RestTemplate restTemplate;
  
  @GetMapping("{id}")
  @HystrixCommand // 统一处理,此处不需要fallbackMethod,只需要加@HystrixCommand注解
  public String queryById(@PathVariable("id") Long id) {
    
    // 使用注解方式实现负载均衡
    String url = "http://user-service/user/"+id;
    String user = restTemplate.getForObject(url, String.class);
    return user
  }
  
  // 统一服务降级逻辑方法,不能再写参数,返回值不用一样
  public String defaultFallback() {
    return "服务器拥挤,请稍后再试";
  }
} 

以上两个方法都可以实现服务降级,在接口异常时返回服务器异常错误提示。

熔断器相关配置
@HystrixCommand(commandProperties = {
  // 定义单个方法请求的超时时长,全局需要在配置文件中配置
  @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="3000")
})

@HystrixCommand(commandProperties = {
  // 触发熔断最小请求次数
  @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value="10"),
  // 熔断器恢复close状态的时间(休眠时长),缺省为5s
  @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value="10000"),
  // 触发熔断的失败请求错误占比,超过百分之60出发熔断器开启
  @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value="60")
})

yml全局配置

hystrix:
  command:
    default:  #全局配置服务降级处理时长
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000 # 默认是1s
    user-service: #配置某个服务或方法(写方法名)的服务降级处理时长
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000
Feign

consumer调用方-引入依赖

<!-- feign依赖 -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

启动类添加注解

@EnableCircuitBreaker   // Hystrix熔断器
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients // 启用feign注解
// @SpringCloudApplication 等同于上面三个注解
public class ConsumerApplication {

    /* RestTemplate不再需要
    @LoadBalanced   // 实现负载均衡
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();  // restTemplate获取到可以调用其他服务器接口的实例对象
    }
    */

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class);
    }
}

新增client/UserClient接口

@FeignClient("user-service") // 请求的服务名称
public interface UserClient {
    @GetMapping("user/{id}")
    User queryById(@PathVariable("id") Long id);
}

ConsumerController

@DefaultProperties(defaultFallback = "defaultFallback")  // 统一的降级逻辑处理
@RestController
@RequestMapping("consumer")
public class ConsumerController {
  
  ...
    
    @Autowired
    private UserClient userClient; // feign
  
    public User queryById(@PathVariable("id") Long id) {
        return userClient.queryById(id);
    }
} 
Feign实现Hystrix

feign框架实现了ribbon负载均衡;Hystrix熔断,默认关闭,需要手动配置开启feign.hystrix.enabled: true

consumer application.yml

feign:
  hystrix:
    enabled: true # 开启feign的熔断功能

UserClient

@FeignClient(value = "user-service", fallback = UserClientFallback.class) // 配置熔断报错实现类 UserClientFallback
public interface UserClient {
    @GetMapping("user/{id}")
    User queryById(@PathVariable("id") Long id);
}

UserClientFallback

@Component
public class UserClientFallback implements UserClient {
    @Override
    public User queryById(Long id) {
        User user = new User();
        user.setName("异常");
        return user;
    }
}

另外yml全局的hystrix配置也会生效。

posted @   Meer_zyh  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示