Spring Cloud & Alibaba 基础知识

Spring Cloud

Spring Cloud 是一个基于 Spring Boot 实现的微服务架构开发工具集。主要的组件有:

一、服务治理

Eureka:

  • 作用:实现服务注册与发现。各个微服务启动时会向 Eureka 服务器注册自己的信息,同时也可以从 Eureka 服务器获取其他服务的信息,从而实现服务之间的调用。
  • 特点:具备高可用、可容错等特性。当服务出现故障时,Eureka 能够及时将故障服务从服务列表中剔除,避免其他服务调用到故障服务。

在 Eureka 中,节点健康检查机制主要是通过服务实例定期向 Eureka Server 发送心跳(heartbeat)来实现的。

心跳机制

服务实例启动时,会向 Eureka Server 注册自己的信息,包括服务名称、IP 地址、端口号等。同时,服务实例会启动一个定时任务,每隔一段时间(默认 30 秒)向 Eureka Server 发送一次心跳,以表明自己仍然处于活跃状态。

Eureka Server 在接收到服务实例的心跳后,会更新该服务实例在注册表中的状态信息,将其标记为 “UP”(可用状态)。如果 Eureka Server 在一段时间内(默认 90 秒)没有收到某个服务实例的心跳,就会将该服务实例从注册表中剔除,并将其状态标记为 “DOWN”(不可用状态)。

自我保护机制

Eureka Server 还具有自我保护机制,以防止在网络分区等情况下错误地剔除服务实例。当 Eureka Server 检测到在一定时间内(15 分钟内)收到的心跳次数低于一个阈值(85%)时,就会进入自我保护模式。在自我保护模式下,Eureka Server 不会剔除任何服务实例,即使这些服务实例没有按时发送心跳。自我保护机制的目的是为了避免在网络不稳定等情况下,由于误判而导致大量服务实例被剔除,从而影响整个系统的可用性。

客户端的健康检查

除了服务实例向 Eureka Server 发送心跳外,Eureka 客户端也会对注册到它的服务实例进行健康检查。客户端可以通过调用服务实例的某个端点(通常是 /health 端点)来检查服务实例的健康状态。如果服务实例的健康状态为 “DOWN”,客户端会将该服务实例从本地缓存中剔除,不再向其发送请求。

总的来说,Eureka 的节点健康检查机制通过心跳机制和自我保护机制来确保服务注册表中的服务实例信息的准确性和可用性,同时客户端也会对服务实例进行健康检查,以提高整个系统的可靠性和稳定性。

在 Spring Cloud 中,可以通过以下方式配置 Eureka 客户端的健康检查:

添加依赖

确保你的项目中已经引入了相关的依赖,通常情况下,如果使用了 Spring Boot 和 Spring Cloud 的依赖管理,以下依赖会自动包含:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

这个依赖提供了 /actuator/health 端点用于健康检查。

配置文件设置

application.propertiesapplication.yml 配置文件中进行以下配置:

对于 application.properties

eureka.client.healthcheck.enabled=true
  1. 对于 application.yml
eureka:
  client:
    healthcheck:
      enabled: true

开启这个配置后,Eureka 客户端会定期调用 /actuator/health 端点来检查自身的健康状态,并将结果上报给 Eureka Server。

自定义健康检查逻辑

如果默认的 /actuator/health 端点不能满足你的需求,你可以自定义健康检查逻辑。可以通过实现 HealthIndicator 接口来创建自己的健康检查器:

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class CustomHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        // 进行自定义的健康检查逻辑
        boolean isHealthy = // 检查条件判断
        if (isHealthy) {
            return Health.up().build();
        } else {
            return Health.down().build();
        }
    }
}

这样,Eureka 客户端在进行健康检查时,会调用你自定义的健康检查器来确定自身的健康状态

二、客户端负载均衡

Ribbon:

  • 作用:在客户端实现负载均衡,当一个服务有多个实例时,Ribbon 可以根据一定的负载均衡策略从多个实例中选择一个进行调用。
  • 特点:支持多种负载均衡策略,如轮询、随机、加权轮询等,可以根据实际需求进行配置。

三、服务调用

Feign:

  • 作用:基于 Ribbon 和 Hystrix 实现声明式的服务调用。通过定义接口并添加注解的方式,即可轻松调用其他微服务,无需手动编写 HTTP 请求代码。
  • 特点:简化了服务调用的代码编写,提高了开发效率。同时,Feign 还支持多种请求方式,如 GET、POST、PUT、DELETE 等。

四、断路器

Hystrix:

  • 作用:当某个服务出现故障时,Hystrix 能够快速熔断该服务的调用,避免故障扩散,同时提供降级机制,返回备用的响应结果。
  • 特点:具备强大的容错能力,可以设置超时时间、熔断阈值等参数,根据实际情况进行调整。在服务出现故障时,能够快速响应,保证系统的稳定性和可靠性。

五、网关

Zuul:

  • 作用:作为微服务架构的统一入口,负责请求的路由和过滤。可以将外部请求转发到内部的各个微服务,同时可以对请求进行安全验证、日志记录、流量控制等操作。
  • 特点:易于使用和扩展,可以通过配置文件或代码进行路由规则的定义。支持多种过滤器类型,如前置过滤器、后置过滤器、路由过滤器等,可以满足不同的业务需求。

六、配置中心

Spring Cloud Config:

  • 作用:集中管理微服务的配置文件,实现配置的动态更新。各个微服务可以从配置中心获取自己的配置信息,当配置发生变化时,微服务能够自动感知并更新配置。
  • 特点:支持多种配置存储方式,如 Git、SVN、本地文件等。可以通过 Spring Cloud Bus 实现配置的实时更新,提高了系统的灵活性和可维护性。

七、服务总线

Spring Cloud Bus:

  • 作用:用于在微服务架构中传播状态变化,实现配置的动态更新和服务的自动发现。可以将配置中心的配置变化通知到各个微服务,使微服务能够及时获取最新的配置信息。
  • 特点:基于消息代理(如 RabbitMQ、Kafka 等)实现,具有高效、可靠的消息传递机制。可以与 Spring Cloud Config 结合使用,实现配置的自动更新。

以下是 Spring Cloud 中各个主要组件的示例代码:

一、Eureka 服务注册与发现

Eureka 简介

Eureka 是 Netflix 开发的一款服务注册与发现工具,在微服务架构中扮演着重要的角色。它主要用于管理微服务实例的注册信息,并提供服务发现的功能,使得各个微服务之间能够相互找到并进行通信。

工作原理

服务注册

  • 当一个微服务启动时,它会向 Eureka Server 发送一个注册请求,将自己的服务名称、IP 地址、端口号等信息注册到 Eureka Server 的服务注册表中。

  • Eureka Server 接收到注册请求后,将该服务的信息存储在注册表中,并返回一个确认信息给服务实例。

    服务发现

  • 当一个微服务需要调用另一个微服务时,它会向 Eureka Server 发送一个查询请求,请求获取目标服务的实例信息。

  • Eureka Server 根据服务名称在注册表中查找对应的服务实例信息,并返回给请求的微服务。

  • 请求的微服务根据返回的实例信息,选择一个合适的服务实例进行调用。

心跳机制

  • 为了保持服务注册表中的信息准确,服务实例会定期向 Eureka Server 发送心跳请求,表明自己仍然处于活跃状态。
  • Eureka Server 如果在一段时间内没有收到某个服务实例的心跳请求,就会将该服务实例从注册表中剔除。

使用步骤

添加依赖

在需要使用 Eureka 的项目中添加以下依赖:

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

创建 Eureka Server

创建一个 Spring Boot 项目作为 Eureka Server,在启动类上添加 @EnableEurekaServer 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

application.propertiesapplication.yml 配置文件中配置 Eureka Server 的相关信息:

server:
  port: 8761

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

服务注册到 Eureka

在需要注册到 Eureka 的微服务项目中添加以下依赖:

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

在微服务的启动类上添加 @EnableDiscoveryClient 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceApplication {

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

在微服务的配置文件中配置 Eureka Server 的地址:

server:
  port: 8080

spring:
  application:
    name: service-name
  cloud:
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/

注意事项:

  • Eureka Server 本身也应该是高可用的,可以通过部署多个 Eureka Server 实例并相互注册来实现高可用。
  • 配置合理的心跳时间和服务剔除时间,避免误剔除正常的服务实例。
  • 在生产环境中,应该考虑使用更可靠的服务注册与发现工具,如 Consul 或 Nacos。

二、Ribbon 客户端负载均衡

Ribbon 简介

Ribbon 是一个基于客户端的负载均衡器,它可以与服务注册中心(如 Eureka)配合使用,在微服务架构中实现客户端对服务端的负载均衡调用。当一个微服务有多个实例时,Ribbon 可以根据一定的负载均衡策略从多个实例中选择一个进行调用,从而提高系统的可用性和性能。

工作原理

  1. 服务发现:Ribbon 从服务注册中心获取可用的服务实例列表。
  2. 负载均衡策略选择:根据配置的负载均衡策略,从服务实例列表中选择一个实例。
  3. 服务调用:使用选择的服务实例进行远程调用。

使用步骤

添加依赖

在需要使用 Ribbon 的项目中添加以下依赖:

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

配置 Ribbon

可以在配置文件中对 Ribbon 进行配置,例如设置服务名称、负载均衡策略等。

spring:
  application:
    name: service-consumer
  cloud:
    loadbalancer:
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 设置负载均衡策略为随机
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/

使用 Ribbon 进行服务调用

在代码中使用 @LoadBalanced 注解修饰 RestTemplate,使其具备负载均衡的能力。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@RestController
public class ServiceConsumerApplication {

    @Autowired
    private RestTemplate restTemplate;

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

    @GetMapping("/callService")
    public String callService() {
        return restTemplate.getForObject("http://service-provider/service", String.class);
    }

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

注意事项:

  • 确保服务注册中心(如 Eureka)正常运行,并且服务提供者已正确注册到服务注册中心。
  • 根据实际情况选择合适的负载均衡策略,例如轮询、随机、加权轮询等。
  • 可以通过自定义 IRule 接口实现来扩展 Ribbon 的负载均衡策略。

三、Feign 服务调用

Spring Cloud Feign 是一个声明式的 HTTP 客户端,它使得在微服务架构中进行服务调用变得更加简单和高效。

主要特点

  1. 声明式编程:通过定义接口并添加注解的方式来描述服务调用,无需手动编写大量的 HTTP 请求代码,提高了开发效率。
  2. 集成 Ribbon:默认集成了 Ribbon 实现客户端负载均衡,能够从多个服务实例中选择合适的实例进行调用。
  3. 可插拔的编码器和解码器:支持多种编码器和解码器,如 JSON、XML 等,可以根据需要进行扩展和定制。
  4. 与 Spring Cloud 生态系统集成良好:可以与其他 Spring Cloud 组件(如 Eureka、Hystrix 等)无缝集成,实现服务注册与发现、断路器等功能。

使用步骤

添加依赖

在项目的 pom.xml 文件中添加 Spring Cloud Feign 的依赖:

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

开启 Feign

在服务的启动类上添加 @EnableFeignClients 注解,开启 Feign 功能:

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

@SpringBootApplication
@EnableFeignClients
public class YourServiceApplication {

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

定义服务接口

定义一个接口来描述对其他服务的调用,使用 @FeignClient 注解指定要调用的服务名称:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("other-service")
public interface OtherServiceClient {

    @GetMapping("/endpoint")
    String callOtherService();
}

在这个例子中,定义了一个名为 OtherServiceClient 的接口,用于调用名为 other-service 的服务的 /endpoint 端点。

使用服务接口

在服务的代码中注入服务接口,并调用其中的方法:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class YourService {

    @Autowired
    private OtherServiceClient otherServiceClient;

    public String doSomething() {
        return otherServiceClient.callOtherService();
    }
}

注意事项

服务名称和端点路径要正确配置,确保 Feign 能够正确找到目标服务。

如果目标服务的接口发生变化,需要及时更新 Feign 接口的定义,以保证服务调用的正确性。

可以配置 Feign 的日志级别,以便在开发和调试过程中查看请求和响应信息。例如,在配置文件中添加以下配置:

logging:
  level:
    org.springframework.cloud.openfeign: DEBUG

当使用 Feign 与其他组件(如 Hystrix)集成时,要注意配置的正确性,以确保断路器等功能能够正常工作。

四、Hystrix 断路器

Hystrix 简介

Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在微服务架构中,它主要用于实现断路器模式,当某个服务出现故障时,能够快速熔断该服务的调用,避免故障扩散,同时提供降级机制,返回备用的响应结果。

工作原理

监控服务调用:Hystrix 会监控服务调用的情况,包括请求数量、错误率、响应时间等指标。

触发熔断:当服务调用的错误率超过一定阈值或者响应时间过长时,Hystrix 会触发熔断,将该服务的调用快速失败,不再进行实际的服务调用。

降级处理:在服务熔断后,Hystrix 会执行降级逻辑,返回一个预设的备用响应结果或者执行一个备用的本地方法,以保证系统的可用性。

使用步骤

添加依赖

在项目中添加 Hystrix 的依赖:

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

开启 Hystrix

在服务的启动类上添加@EnableCircuitBreaker注解,开启 Hystrix 断路器功能:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;

@SpringBootApplication
@EnableCircuitBreaker
public class YourServiceApplication {

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

使用 Hystrix 命令

在服务的方法上使用@HystrixCommand注解来定义 Hystrix 命令,指定降级方法和熔断策略等参数:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@Service
public class YourService {

    @Autowired
    private RemoteService remoteService;

    @HystrixCommand(fallbackMethod = "fallbackMethod")
    public String callRemoteService() {
        return remoteService.doSomething();
    }

    public String fallbackMethod() {
        return "Fallback response";
    }
}

在这个例子中,当callRemoteService方法调用远程服务出现故障时,会执行fallbackMethod方法作为降级处理。

注意事项:

  • 合理设置熔断阈值和超时时间,根据实际业务情况进行调整。
  • 降级方法应该尽可能简单快速,避免引入新的故障点。
  • 监控 Hystrix 的指标,以便及时了解系统的健康状况和调整参数。

五、Zuul 网关

Zuul 简介

Zuul 是 Netflix 开源的微服务网关,它可以作为微服务架构中的统一入口,负责请求的路由和过滤。Zuul 可以将外部请求转发到内部的各个微服务,同时可以对请求进行安全验证、日志记录、流量控制等操作。

工作原理

  1. 请求路由:当外部请求到达 Zuul 网关时,Zuul 根据配置的路由规则将请求转发到相应的微服务。
  2. 请求过滤:在请求转发之前或之后,Zuul 可以通过过滤器对请求进行各种处理,例如添加请求头、验证用户身份、记录日志等。

使用步骤

添加依赖

在项目中添加 Zuul 的依赖:

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

创建 Zuul 网关

创建一个 Spring Boot 项目作为 Zuul 网关,在启动类上添加 @EnableZuulProxy 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
public class ZuulGatewayApplication {

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

配置 Zuul

在配置文件中配置 Zuul 的路由规则和其他属性:

server:
  port: 8080

spring:
  application:
    name: zuul-gateway
  cloud:
    zuul:
      routes:
        service1:
          path: /service1/**
          serviceId: service-provider1
        service2:
          path: /service2/**
          serviceId: service-provider2

在这个配置中,定义了两个路由规则,将以 /service1/ 开头的请求转发到名为 service-provider1 的服务,将以 /service2/ 开头的请求转发到名为 service-provider2 的服务。

使用过滤器

可以创建自定义的过滤器来对请求进行处理。例如,创建一个前置过滤器来添加请求头:

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class PreRequestFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info("Request: {} {}", request.getMethod(), request.getRequestURL());
        ctx.addZuulRequestHeader("X-Custom-Header", "Custom Value");
        return null;
    }
}

在启动类中注册过滤器:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableZuulProxy
public class ZuulGatewayApplication {

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

    @Bean
    public PreRequestFilter preRequestFilter() {
        return new PreRequestFilter();
    }
}

注意事项:

  • 确保 Zuul 网关正确配置了服务的路由规则,避免请求无法正确转发。
  • 合理使用过滤器来实现安全、日志等功能,但要注意过滤器的性能影响。
  • 在生产环境中,可以对 Zuul 进行高可用部署,以提高系统的可靠性。

六、Spring Cloud Config 配置中心

Spring Cloud Config 简介

Spring Cloud Config 是一个集中式的配置管理工具,用于在微服务架构中管理各个微服务的配置文件。它可以将配置信息存储在不同的后端存储中,如 Git、SVN、本地文件系统等,并提供了客户端和服务器端的实现,使得微服务可以从配置中心获取自己的配置信息,实现配置的集中管理和动态更新。

工作原理

  1. 配置存储:配置信息可以存储在 Git 仓库、SVN 仓库、本地文件系统等后端存储中。
  2. 配置服务器:Spring Cloud Config Server 作为配置中心的服务器端,负责从后端存储中读取配置信息,并提供给客户端。
  3. 客户端获取配置:微服务作为客户端,通过向配置服务器发送请求来获取自己的配置信息。客户端可以在启动时或运行时动态获取配置更新。

使用步骤

添加依赖

在配置中心服务器项目中添加以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

在需要从配置中心获取配置的微服务项目中添加以下依赖:

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

创建配置中心服务器

创建一个 Spring Boot 项目作为配置中心服务器,在启动类上添加 @EnableConfigServer 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

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

在配置文件中配置后端存储的位置:

server:
  port: 8888

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-username/your-config-repo
          search-paths: config-repo

这里假设使用 Git 作为后端存储,配置了 Git 仓库的地址和搜索路径。

微服务从配置中心获取配置

在微服务的配置文件中配置配置中心的地址和应用名称:

spring:
  application:
    name: service-name
  cloud:
    config:
      uri: http://localhost:8888
      name: service-name
      profile: dev

这里指定了配置中心的地址为 http://localhost:8888,应用名称为 service-name,环境为 dev

微服务可以通过 @Value 注解或 Environment 对象来获取配置信息:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class ServiceApplication {

    @Value("${custom.property}")
    private String customProperty;

    @GetMapping("/getProperty")
    public String getProperty() {
        return customProperty;
    }

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

注意事项:

  • 确保配置中心服务器能够正常连接到后端存储,并读取配置信息。
  • 微服务在启动时会从配置中心获取配置,如果配置中心不可用,可能会导致微服务启动失败。可以考虑使用本地缓存或备用配置方案。
  • 在生产环境中,可以对配置中心进行高可用部署,以提高系统的可靠性。

七、Spring Cloud Bus消息总线

Spring Cloud Bus 简介

Spring Cloud Bus 是 Spring Cloud 中的一个消息总线,用于在分布式系统中传播状态变化,实现配置的动态更新和服务的自动发现等功能。它基于消息代理(如 RabbitMQ、Kafka 等)实现,可以将配置中心的配置变化通知到各个微服务,使微服务能够及时获取最新的配置信息。

工作原理

  1. 消息总线:Spring Cloud Bus 使用消息代理作为消息总线,各个微服务通过连接到消息总线来接收和发送消息。
  2. 配置更新通知:当配置中心的配置发生变化时,配置中心会向消息总线发送一个更新事件。各个微服务订阅了这个事件,当接收到事件后,会从配置中心重新获取配置信息,并更新自己的配置。
  3. 服务自动发现:Spring Cloud Bus 也可以用于服务的自动发现。当一个新的服务实例上线或下线时,服务注册中心会向消息总线发送一个事件,其他服务可以通过订阅这个事件来及时发现服务的变化。

使用步骤

添加依赖

在需要使用 Spring Cloud Bus 的项目中添加以下依赖:

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

这里假设使用 RabbitMQ 作为消息代理,如果使用其他消息代理,可以相应地调整依赖。

配置消息代理

在配置文件中配置消息代理的连接信息:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
  cloud:
    bus:
      enabled: true

触发配置更新

可以通过向 /actuator/bus-refresh 端点发送 POST 请求来触发配置更新。例如,可以使用以下命令通过 curl 触发配置更新:

curl -X POST http://localhost:8080/actuator/bus-refresh

这里假设微服务运行在端口 8080 上。

注意事项:

  • 确保消息代理(如 RabbitMQ)正常运行,并正确配置连接信息。
  • 在生产环境中,要注意消息总线的安全性和稳定性,避免消息丢失或重复发送。
  • 可以使用 Spring Cloud Bus 与 Spring Cloud Config 结合,实现配置的自动更新,但要注意配置更新的频率和对系统性能的影响。

Spring Cloud Alibaba

Spring Cloud Alibaba 是一套开源的微服务解决方案,它基于 Spring Cloud 规范,并整合了阿里巴巴的开源组件。主要的组件有:

一、服务注册与发现

Nacos:

  • 作用:既可以作为服务注册中心,也可以作为配置中心。服务提供者和消费者可以将自己的信息注册到 Nacos,实现服务的自动发现和调用。同时,Nacos 还可以集中管理微服务的配置信息,实现配置的动态更新。
  • 特点:支持多种服务发现和配置管理模式,如临时实例、持久化实例等。具有高可用、可扩展的特性,可以轻松应对大规模微服务架构的需求。

二、负载均衡

Ribbon(与 Spring Cloud 共用)或 LoadBalancer:

  • 作用:在客户端实现负载均衡,当一个服务有多个实例时,根据一定的负载均衡策略从多个实例中选择一个进行调用。
  • 特点:LoadBalancer 是 Spring Cloud 原生的负载均衡组件,与 Nacos 结合使用时,可以根据 Nacos 中的服务实例信息进行负载均衡。支持多种负载均衡策略,如轮询、随机、加权轮询等。

三、服务调用

Feign(与 Spring Cloud 共用)或 OpenFeign:

  • 作用:基于 Ribbon 和 Hystrix(如果启用)实现声明式的服务调用。通过定义接口并添加注解的方式,即可轻松调用其他微服务,无需手动编写 HTTP 请求代码。
  • 特点:简化了服务调用的代码编写,提高了开发效率。可以与 Nacos 结合使用,实现服务的自动发现和调用。

Feign 和 OpenFeign 有以下一些区别:

背景和关系

  • Feign:最初是由 Netflix 开发的声明式 HTTP 客户端,用于简化服务之间的调用。在 Spring Cloud 早期版本中集成了 Feign 来实现服务调用。
  • OpenFeign:OpenFeign 是对 Feign 的进一步改进和扩展,现在是 Spring Cloud 官方推荐的声明式服务调用客户端。它在 Feign 的基础上进行了优化和增强,并且与 Spring 生态系统更好地集成。

功能特性

依赖管理

  • Feign:通常需要一些额外的配置和依赖管理,尤其是在与其他组件集成时可能需要手动处理一些兼容性问题。
  • OpenFeign:作为 Spring Cloud 体系的一部分,与 Spring Boot 和其他 Spring Cloud 组件的集成更加无缝。它通常可以通过简单的依赖引入和配置就能快速使用。

代码生成和灵活性

  • Feign:通过定义接口并添加注解来描述服务调用,但在一些复杂场景下可能需要额外的代码来处理特殊情况。
  • OpenFeign:提供了更强大的代码生成和自定义功能。可以通过配置和扩展来满足更复杂的业务需求,例如自定义编码器、解码器、日志级别等。

性能和优化

  • OpenFeign:在性能方面进行了一些优化,例如连接池管理、请求压缩等。它还支持对 HTTP 连接的更细粒度控制,可以更好地适应不同的网络环境和性能要求。

社区支持和更新

  • OpenFeign:由于是 Spring Cloud 官方推荐的组件,通常会得到更及时的更新和更好的社区支持。它会随着 Spring Cloud 的发展不断演进,以满足不断变化的微服务架构需求。

总的来说,OpenFeign 在功能、性能和与 Spring Cloud 生态系统的集成方面都比传统的 Feign 更具优势,是构建微服务架构中服务调用的更优选择。

四、断路器

Sentinel:

  • 作用:实现流量控制、熔断降级、系统负载保护等功能。当某个服务出现故障时,Sentinel 能够快速熔断该服务的调用,避免故障扩散,同时提供降级机制,返回备用的响应结果。
  • 特点:具有丰富的流量控制策略,如 QPS 限流、线程数限流等。可以实时监控服务的运行状态,根据预设的规则进行流量控制和熔断降级。支持多种数据源,如 Nacos、ZooKeeper 等,可以方便地进行规则的动态配置。

五、网关

Spring Cloud Gateway:

  • 作用:作为微服务架构的统一入口,负责请求的路由和过滤。可以将外部请求转发到内部的各个微服务,同时可以对请求进行安全验证、日志记录、流量控制等操作。
  • 特点:基于 Spring 5 和 Project Reactor 实现,具有高并发、低延迟的特性。支持多种路由规则和过滤器,可以根据实际需求进行灵活配置。可以与 Nacos 结合使用,实现动态路由和服务发现。

六、分布式事务

Seata:

  • 作用:解决分布式系统中的事务问题,保证数据的一致性。在分布式环境下,一个业务操作可能涉及多个数据库或服务的操作,Seata 可以确保这些操作要么全部成功,要么全部回滚。
  • 特点:采用了 AT(Automatic Transaction)模式、TCC(Try-Confirm-Cancel)模式等多种事务模式,可以根据不同的业务场景进行选择。支持多种数据库,如 MySQL、Oracle、PostgreSQL 等。具有高可用、高性能的特性,可以轻松应对大规模分布式系统的事务需求。

以下是 Spring Cloud Alibaba 中一些主要组件的示例代码和注意事项:

一、Nacos 服务注册与发现

Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

主要功能

服务注册与发现

  • 微服务可以将自己的信息注册到 Nacos 服务器,其他服务可以通过 Nacos 发现这些服务的实例信息,实现服务的自动发现和调用。
  • 支持动态更新服务实例,当服务实例上线、下线或发生变化时,Nacos 能够及时通知客户端。

配置管理

  • 集中管理微服务的配置信息,可以将配置存储在 Nacos 服务器中,微服务从 Nacos 读取配置,实现配置的集中管理和动态更新。
  • 支持配置的版本管理、灰度发布等功能,可以方便地进行配置的变更和管理。

服务管理

  • 可以对服务进行健康检查,确保服务的可用性。
  • 支持动态调整服务的权重、流量控制等,实现服务的精细化管理。

使用步骤

服务提供者示例:

创建一个 Maven 项目,在pom.xml文件中添加以下依赖:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.7.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

创建一个简单的服务提供者接口和实现类:

package com.example.provider.service;

public interface HelloService {
    String sayHello();
}
package com.example.provider.service.impl;

import com.example.provider.service.HelloService;
import org.springframework.stereotype.Service;

@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello() {
        return "Hello from provider!";
    }
}

创建一个控制器类:

package com.example.provider.controller;

import com.example.provider.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Autowired
    private HelloService helloService;

    @GetMapping("/hello")
    public String hello() {
        return helloService.sayHello();
    }
}

application.properties文件中添加 Nacos 配置:

server.port=8081
spring.application.name=provider-service
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

服务消费者示例:

创建另一个 Maven 项目,在pom.xml文件中添加与服务提供者相同的依赖。

创建一个服务消费者的接口和实现类:

package com.example.consumer.service;

public interface ConsumerService {
    String callProvider();
}
package com.example.consumer.service.impl;

import com.example.consumer.service.ConsumerService;
import com.example.provider.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ConsumerServiceImpl implements ConsumerService {

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public String callProvider() {
        return restTemplate.getForObject("http://provider-service/hello", String.class);
    }

    @Configuration
    public class RestTemplateConfig {

        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
            factory.setConnectTimeout(5000);
            factory.setReadTimeout(5000);
            return new RestTemplate(factory);
        }
    }
}

创建一个控制器类:

package com.example.consumer.controller;

import com.example.consumer.service.ConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConsumerController {

    @Autowired
    private ConsumerService consumerService;

    @GetMapping("/callProvider")
    public String callProvider() {
        return consumerService.callProvider();
    }
}

application.properties文件中添加 Nacos 配置:

server.port=8082
spring.application.name=consumer-service
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

配置管理示例:

在 Nacos 控制台中创建一个配置文件,命名为consumer-service.properties,内容如下:

custom.message=Hello from Nacos config!

在服务消费者项目中添加配置管理依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

application.properties文件中添加以下配置:

server.port=8082
spring.application.name=consumer-service
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.file-extension=properties
spring.cloud.nacos.config.prefix=consumer-service

创建一个配置类来读取配置:

package com.example.consumer.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Value("${custom.message}")
    private String customMessage;

    public String getCustomMessage() {
        return customMessage;
    }
}

在服务消费者的控制器中注入配置类并使用配置值:

package com.example.consumer.controller;

import com.example.consumer.config.AppConfig;
import com.example.consumer.service.ConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConsumerController {

    @Autowired
    private ConsumerService consumerService;

    @Autowired
    private AppConfig appConfig;

    @GetMapping("/callProvider")
    public String callProvider() {
        return consumerService.callProvider() + " " + appConfig.getCustomMessage();
    }
}

通过以上代码示例,你可以看到如何使用 Spring Cloud Alibaba Nacos 实现服务注册与发现以及配置管理。首先,服务提供者将自己注册到 Nacos 服务注册中心,并提供一个简单的接口。服务消费者通过 Nacos 发现服务提供者,并调用其接口。同时,通过 Nacos 配置中心,服务消费者可以动态获取配置信息。

请注意,在实际使用中,你需要将 Nacos 的地址替换为你自己的实际地址,并根据需求调整配置和代码。

二、Sentinel 流量控制和熔断降级

Spring Cloud Alibaba Sentinel 介绍

Spring Cloud Alibaba Sentinel 是一款面向分布式服务架构的流量控制组件,主要用于解决微服务架构中的流量控制、熔断降级、系统负载保护等问题。

流量控制

  • 可以对资源(如接口、方法等)的访问进行流量控制,防止因流量过大而导致系统崩溃。
  • 支持多种流量控制策略,如直接拒绝、匀速排队、预热等。

熔断降级

  • 当服务出现故障或响应时间过长时,自动进行熔断,快速返回错误响应,避免故障扩散。
  • 可以根据不同的情况设置熔断策略,如慢调用比例、异常比例、异常数等。

系统负载保护

  • 当系统负载过高时,自动进行限流,保护系统不被压垮。
  • 可以根据 CPU 使用率、内存使用率等指标进行系统负载保护。

功能示例

流量控制示例

  • 添加依赖:在项目的pom.xml文件中添加 Spring Cloud Alibaba Sentinel 的依赖。
<dependency>
       <groupId>com.alibaba.cloud</groupId>
       <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
   </dependency>
  • 配置 Sentinel:在application.propertiesapplication.yml文件中添加 Sentinel 的配置信息,如控制台地址等。
   spring.cloud.sentinel.transport.dashboard=127.0.0.1:8080
  • 定义资源:在服务的接口方法上使用@SentinelResource注解来定义资源。
import com.alibaba.csp.sentinel.annotation.SentinelResource;
   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.RestController;

   @RestController
   public class TestController {

       @SentinelResource(value = "testResource", blockHandler = "handleBlock")
       @GetMapping("/test")
       public String test() {
           return "Hello, Sentinel!";
       }

       public String handleBlock(BlockException ex) {
           return "Too many requests, please try later.";
       }
   }

在这个例子中,/test接口被定义为一个资源,当流量超过限制时,会调用handleBlock方法返回错误响应。

熔断降级示例

  • 添加依赖和配置:与流量控制示例相同,添加依赖并配置 Sentinel 控制台地址。
  • 定义资源和降级方法:在接口方法上使用@SentinelResource注解,并指定降级方法。
import com.alibaba.csp.sentinel.annotation.SentinelResource;
   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.RestController;

   @RestController
   public class TestController {

       @SentinelResource(value = "testResource", fallback = "handleFallback")
       @GetMapping("/test")
       public String test() {
           // 模拟可能出现故障的代码
           if (Math.random() < 0.5) {
               throw new RuntimeException("Service is unavailable.");
           }
           return "Hello, Sentinel!";
       }

       public String handleFallback() {
           return "Service is unavailable, please try later.";
       }
   }

在这个例子中,当/test接口出现异常时,会调用handleFallback方法返回降级后的响应。

通过使用 Spring Cloud Alibaba Sentinel,可以有效地保护微服务系统的稳定性和可靠性,提高系统的容错能力和可扩展性。

三、Seata 分布式事务

Seata 简介

Seata 致力于在微服务架构下提供高性能和简单易用的分布式事务服务。它通过对业务无侵入的方式,解决了分布式系统中的数据一致性问题。

Seata 主要有三个核心模块:

Transaction Coordinator (TC):事务协调器,负责管理全局事务的状态,协调各个事务参与者的提交或回滚操作。

Transaction Manager ™:事务管理器,由业务系统实现,负责开启、提交或回滚一个全局事务。

Resource Manager (RM):资源管理器,由业务系统实现,负责管理分支事务对数据库资源的操作。

使用步骤

添加依赖

在项目的 pom.xml 文件中添加 Seata 依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

配置 Seata 服务器

下载并启动 Seata 服务器,可以从 Seata 的官方仓库获取最新版本。配置文件(如 registry.conffile.conf)需要根据实际情况进行调整,主要配置包括注册中心地址、存储模式等。

业务代码集成

假设我们有两个服务 ServiceA 和 ServiceB,在 ServiceA 中调用 ServiceB 的业务方法,并且需要保证事务一致性。

ServiceA:

import com.alibaba.fastjson.JSONObject;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class ServiceAController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private ServiceBClient serviceBClient;

    @GlobalTransactional
    @PostMapping("/operationA")
    public JSONObject operationA() {
        jdbcTemplate.update("INSERT INTO table_a (column1) VALUES ('value1')");
        serviceBClient.operationB();
        return new JSONObject();
    }
}

ServiceB:

import com.alibaba.fastjson.JSONObject;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class ServiceBController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @PostMapping("/operationB")
    public JSONObject operationB() {
        jdbcTemplate.update("INSERT INTO table_b (column1) VALUES ('value2')");
        return new JSONObject();
    }
}

在 ServiceA 的 operationA 方法上添加 @GlobalTransactional 注解,开启全局事务。在这个方法中调用 ServiceB 的 operationB 方法,如果在执行过程中出现任何异常,Seata 会自动回滚全局事务,确保数据的一致性。

注意事项:

  • 确保 Seata 服务器正确配置和启动。
  • 在使用 @GlobalTransactional 注解的方法中,尽量避免复杂的业务逻辑和长时间的操作,以免影响事务的性能和可靠性。
  • 对于数据库连接和事务的管理,需要根据实际情况进行优化,避免出现连接泄漏和事务超时等问题。

四、Spring Cloud Gateway 网关

Spring Cloud Gateway 是基于 Spring WebFlux 实现的 API 网关,用于为微服务架构提供统一的入口,并实现路由、过滤等功能。

引入依赖

在项目的 pom.xml 文件中添加以下依赖:

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

配置文件示例

以下是一个 application.yml 配置文件的示例:

server:
  port: 8080

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: service1-route
          uri: lb://service1
          predicates:
            - Path=/service1/**
          filters:
            - StripPrefix=1
        - id: service2-route
          uri: lb://service2
          predicates:
            - Path=/service2/**

在这个配置中,定义了两个路由:

  • service1-route:将以 /service1/ 开头的请求转发到名为 service1 的服务(通过 lb://service1 使用服务发现来定位服务),并使用 StripPrefix 过滤器去除请求路径中的第一层前缀。
  • service2-route:类似地,将以 /service2/ 开头的请求转发到 service2 服务。

示例代码

假设已经有两个服务 service1service2,通过 Spring Cloud Gateway 进行路由转发。

创建一个 Spring Boot 应用作为网关服务:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayApplication {

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

服务发现与负载均衡(如果使用服务注册中心):

假设使用 Eureka 或 Nacos 作为服务注册中心,网关可以通过服务发现和负载均衡机制将请求转发到具体的服务实例。

注意事项:

  • 确保正确配置服务注册中心(如 Eureka、Nacos 等),并将需要路由的服务注册到服务注册中心。
  • 根据实际需求配置过滤器和断言,以满足不同的路由和请求处理要求。
  • 可以使用自定义过滤器来实现更复杂的业务逻辑,如安全验证、日志记录等。

以下是一些 Spring Cloud Gateway 的其他配置示例:

添加全局过滤器

全局过滤器作用于所有的路由,可以实现一些通用的功能,比如统一的日志记录、安全验证等。

创建一个全局过滤器:

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class LoggingGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = request.getHeaders();

        log.info("Request: {} {}", request.getMethod(), request.getURI());
        log.info("Headers: {}", headers);

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            log.info("Response status: {}", response.getStatusCode());
        }));
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

这个过滤器会记录请求的方法、URI 和请求头信息,以及响应的状态码。

在配置类中注册过滤器:

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

@Configuration
public class GatewayConfig {

    @Bean
    public LoggingGlobalFilter loggingGlobalFilter() {
        return new LoggingGlobalFilter();
    }
}

路由权重配置

可以为同一个服务配置多个实例,并通过权重来分配请求流量。

假设服务 service1 有两个实例,一个权重为 2,另一个权重为 1。

配置文件:

spring:
  cloud:
    gateway:
      routes:
        - id: service1-route-1
          uri: lb://service1/instance1
          predicates:
            - Path=/service1/**
          filters:
            - StripPrefix=1
          metadata:
            weight: 2
        - id: service1-route-2
          uri: lb://service1/instance2
          predicates:
            - Path=/service1/**
          filters:
            - StripPrefix=1
          metadata:
            weight: 1

这样,当有请求到达 /service1 路径时,会按照 2:1 的比例将请求分发到两个实例上。

请求超时配置

可以设置请求的超时时间,避免长时间等待响应。

配置文件:

spring:
  cloud:
    gateway:
      routes:
        - id: service1-route
          uri: lb://service1
          predicates:
            - Path=/service1/**
          filters:
            - StripPrefix=1
          timeouts:
            connect: 5s
            read: 10s

在这个配置中,设置了连接超时时间为 5 秒,读取超时时间为 10 秒。如果请求在规定时间内没有建立连接或没有收到响应,网关会中断请求并返回超时错误。

五、OpenFeign 服务调用

项目结构

假设我们有一个微服务架构,包含服务提供者和服务消费者。

依赖管理

在两个项目的 pom.xml 文件中添加以下依赖:

服务提供者和服务消费者共同依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

服务消费者额外依赖:

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

服务提供者(Service Provider)代码

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class ServiceProviderApplication {

    @GetMapping("/service")
    public String provideService() {
        return "Hello from Service Provider!";
    }

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

服务消费者(Service Consumer)代码

创建服务接口:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("service-provider")
public interface ServiceProviderClient {

    @GetMapping("/service")
    String getService();
}

编写服务消费者代码:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class ServiceConsumerApplication {

    @Autowired
    private ServiceProviderClient serviceProviderClient;

    @GetMapping("/callService")
    public String callService() {
        return serviceProviderClient.getService();
    }

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

服务消费者启动类:

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

@SpringBootApplication
@EnableFeignClients
public class ServiceConsumerApplication {

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

配置文件(假设使用了服务注册中心 Nacos,服务消费者配置):

server:
  port: 8081

spring:
  application:
    name: service-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

注意事项:

  • 确保服务注册中心(如 Nacos)已经启动并正确配置。
  • 如果需要,可以配置 OpenFeign 的日志级别来查看请求和响应信息,例如在配置文件中添加:
logging:
  level:
    org.springframework.cloud.openfeign: DEBUG
  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值