WEBKT

Spring Cloud 微服务治理:从注册发现到熔断降级,保姆级教程

235 0 0 0

大家好,我是你们的 IT 邻居,老王。

今天咱们来聊聊微服务架构下的服务治理。微服务架构将单体应用拆分成多个小型、独立的服务,每个服务负责特定的业务功能。这种架构带来了诸多好处,比如更高的灵活性、可扩展性和可维护性。但同时,也引入了新的挑战:如何管理这些数量众多的服务?

这就是服务治理要解决的问题。服务治理涵盖了一系列活动,旨在确保微服务的健康、可靠和高效运行。今天,咱们就以 Spring Cloud 为例,深入探讨微服务治理的各个方面,包括服务注册与发现、负载均衡、服务监控、服务熔断、服务降级等。

为什么要进行服务治理?

在单体应用时代,服务之间的调用都在同一个进程内完成,相对简单。但在微服务架构下,服务之间的调用变成了跨进程、跨网络的远程调用。这带来了许多新的问题:

  • 服务发现: 服务消费者如何找到服务提供者?
  • 负载均衡: 如何将请求分发到多个服务提供者实例?
  • 服务容错: 如何处理服务调用失败?
  • 服务监控: 如何了解服务的运行状态?
  • 服务安全: 如何保证服务调用的安全性?

服务治理就是为了解决这些问题,确保微服务架构的稳定运行。

Spring Cloud 与服务治理

Spring Cloud 为微服务治理提供了一套完整的解决方案。它基于 Spring Boot,提供了各种组件,可以轻松实现服务注册与发现、负载均衡、服务熔断、服务降级等功能。

接下来,咱们就详细介绍 Spring Cloud 中的几个核心组件,以及它们在服务治理中扮演的角色。

1. 服务注册与发现:Eureka

1.1. 什么是服务注册与发现?

想象一下,你要给朋友打电话,你得先知道他的电话号码。服务注册与发现也是同样的道理。服务提供者将自己的信息(比如 IP 地址、端口号)注册到服务注册中心,服务消费者从服务注册中心查询服务提供者的信息,然后才能发起调用。

1.2. Eureka 简介

Eureka 是 Spring Cloud 中的服务注册与发现组件。它包含两个核心角色:

  • Eureka Server: 服务注册中心,负责管理服务实例的信息。
  • Eureka Client: 服务提供者和消费者,通过 Eureka Client 与 Eureka Server 交互,完成服务注册和发现。

1.3. Eureka 工作原理

  1. 服务注册: 服务提供者启动时,将自己的信息注册到 Eureka Server。
  2. 服务续约: 服务提供者定期向 Eureka Server 发送心跳,表明自己还活着。
  3. 服务下线: 服务提供者正常关闭时,会向 Eureka Server 发送下线请求,将自己从服务列表中移除。如果 Eureka Server 长时间没有收到某个服务实例的心跳,也会将其从服务列表中移除。
  4. 服务发现: 服务消费者从 Eureka Server 获取服务提供者的信息,然后发起调用。

1.4. Eureka 实战

咱们通过一个简单的例子,演示如何使用 Eureka 实现服务注册与发现。

1. 创建 Eureka Server

创建一个 Spring Boot 项目,添加以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

在启动类上添加 @EnableEurekaServer 注解:

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

application.yml 中配置 Eureka Server:

server:
  port: 8761

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:8761/eureka/

2. 创建服务提供者

创建一个 Spring Boot 项目,添加以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

在启动类上添加 @EnableEurekaClient 注解:

@SpringBootApplication
@EnableEurekaClient
@RestController
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
    @Value("${server.port}")
    String port;

    @RequestMapping("/hello")
    public String home() {
        return "hello world from port " + port;
    }

}

application.yml 中配置 Eureka Client:

spring:
  application:
    name: provider-service
server:
  port: 8081

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

3. 创建服务消费者

创建一个 Spring Boot 项目,添加以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

在启动类上添加 @EnableEurekaClient 注解:

@SpringBootApplication
@EnableEurekaClient
@RestController
public class ConsumerApplication {
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
    @RequestMapping("/hi")
    public String hi(@RequestParam(value = "name", defaultValue = "forezp") String name) {
        ServiceInstance serviceInstance = loadBalancerClient.choose("provider-service");
        String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/hello";
        System.out.println(url);
        return new RestTemplate().getForObject(url, String.class);
    }
}

application.yml 中配置 Eureka Client:

spring:
  application:
    name: consumer-service
server:
  port: 8082

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

启动 Eureka Server、服务提供者和服务消费者,访问 http://localhost:8082/hi,可以看到服务消费者成功调用了服务提供者的接口。

2. 负载均衡:Ribbon

2.1. 什么是负载均衡?

当有多个服务提供者实例时,我们需要将请求分发到不同的实例上,这就是负载均衡。负载均衡可以提高系统的吞吐量、可用性和可靠性。

2.2. Ribbon 简介

Ribbon 是 Spring Cloud 中的客户端负载均衡组件。它可以与 Eureka 结合使用,从 Eureka Server 获取服务提供者列表,然后根据一定的负载均衡策略,选择一个服务实例发起调用。

2.3. Ribbon 负载均衡策略

Ribbon 提供了多种负载均衡策略,比如:

  • RoundRobinRule: 轮询,按顺序依次选择服务实例。
  • RandomRule: 随机,随机选择一个服务实例。
  • BestAvailableRule: 选择并发量最小的服务实例
  • WeightedResponseTimeRule: 加权响应时间,响应时间越短的服务实例权重越高,被选中的概率越大。

可以在配置文件中指定负载均衡策略:

provider-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

2.4. Ribbon 实战

在上面的例子中,服务消费者已经使用了 Ribbon。通过 LoadBalancerClient 接口的 choose 方法,可以获取一个服务实例,然后发起调用。我们也可以使用@LoadBalanced注解简化操作。

修改消费者:

@SpringBootApplication
@EnableEurekaClient
@RestController
public class ConsumerApplication {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return  new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
    @RequestMapping("/hi")
    public String hi(@RequestParam(value = "name", defaultValue = "forezp") String name) {
        String url = "http://provider-service/hello";
        System.out.println(url);
        return new RestTemplate().getForObject(url, String.class);
    }
}

启动多个服务提供者实例,再次访问 http://localhost:8082/hi,可以看到 Ribbon 会将请求分发到不同的服务实例上。

3. 服务熔断:Hystrix

3.1. 什么是服务熔断?

在微服务架构下,服务之间存在依赖关系。如果某个服务出现故障,可能会导致其他服务也受到影响,甚至引发雪崩效应。服务熔断就是为了解决这个问题。当某个服务出现故障时,熔断器会打开,阻止请求继续发送到该服务,从而避免雪崩效应。

3.2. Hystrix 简介

Hystrix 是 Spring Cloud 中的服务熔断组件。它可以监控服务调用的状态,当服务调用失败率达到一定阈值时,熔断器会打开,阻止请求继续发送到该服务。一段时间后,熔断器会进入半开状态,尝试发送少量请求,如果请求成功,则关闭熔断器,恢复服务调用;如果请求仍然失败,则继续保持打开状态。

3.3. Hystrix 工作原理

Hystrix 的核心是熔断器。熔断器有三种状态:

  • Closed: 关闭状态,请求可以正常发送到服务。
  • Open: 打开状态,请求被阻止,直接返回错误或执行 fallback 逻辑。
  • Half-Open: 半开状态,尝试发送少量请求,根据请求结果决定是否关闭熔断器。

3.4. Hystrix 实战

在服务消费者中添加 Hystrix 支持。

添加依赖:

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

在启动类增加注解@EnableHystrix,开启 Hystrix。

改造消费者:

@SpringBootApplication
@EnableEurekaClient
@RestController
@EnableHystrix
public class ConsumerApplication {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return  new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
    @RequestMapping("/hi")
    @HystrixCommand(fallbackMethod = "hiError")
    public String hi(@RequestParam(value = "name", defaultValue = "forezp") String name) {
        String url = "http://provider-service/hello";
        System.out.println(url);
        return new RestTemplate().getForObject(url, String.class);
    }

     public String hiError(String name) {
        return "hi," + name + ",sorry,error!";
    }
}

当服务提供者不可用时,会执行 hiError 方法,返回错误信息。

4. 服务降级

4.1. 什么是服务降级?

服务降级是指当服务出现问题或者资源不足时,为了保证核心服务的可用性,主动关闭一些非核心服务,或者返回一些默认值。服务降级是一种牺牲部分功能来保证整体系统可用性的策略。

4.2. 服务降级与服务熔断的区别

  • 服务熔断: 是应对服务雪崩的一种保险措施,是应对服务调用故障的,相当于保险丝。
  • 服务降级: 从整体负荷考虑,当某个服务熔断后,服务器将不再被调用,客户端可以自己准备一个本地的 fallback 回调,返回一个缺省值,这样做虽然服务水平下降,但好歹可用,比直接挂掉要强。

4.3. Hystrix 实现服务降级

在上面的 Hystrix 示例中,我们已经演示了如何使用 Hystrix 实现服务降级。当服务调用失败时,会执行 fallbackMethod 指定的方法,返回一个默认值。

5. 服务监控

5.1. 为什么需要服务监控?

服务监控可以帮助我们了解服务的运行状态,及时发现问题,并进行处理。服务监控通常包括以下几个方面:

  • 性能指标: 比如 CPU 使用率、内存使用率、请求响应时间、吞吐量等。
  • 健康检查: 检查服务是否正常运行。
  • 日志: 记录服务的运行日志,方便排查问题。

5.2. Spring Boot Actuator

Spring Boot Actuator 提供了各种监控端点,可以暴露服务的各种信息。比如:

  • /health:健康检查端点,可以查看服务的健康状态。
  • /metrics:性能指标端点,可以查看各种性能指标。
  • /loggers:日志端点,可以查看和修改日志级别。

5.3. Spring Cloud Sleuth 与 Zipkin

Spring Cloud Sleuth 提供了分布式链路追踪功能,可以跟踪请求在多个服务之间的调用过程。Zipkin 是一个分布式链路追踪系统,可以收集和展示 Sleuth 生成的追踪数据。

总结

本文介绍了微服务架构下的服务治理,以及 Spring Cloud 中的几个核心组件:Eureka、Ribbon、Hystrix。通过这些组件,我们可以轻松实现服务注册与发现、负载均衡、服务熔断、服务降级等功能,保证微服务架构的稳定运行。当然,Spring Cloud 提供的服务治理能力远不止这些,例如还有配置中心 কনফিগারেশন সেন্টার Config Server、服务网关 Zuul 等,这些内容我们将在后续的文章中继续探讨。

希望这篇文章能帮助你更好地理解微服务治理,如果你有任何问题或建议,欢迎在评论区留言。

IT老王 Spring Cloud微服务服务治理

评论点评