目录
一、微服务概述
1.1 微服务架构特点
微服务架构是一种将单体应用程序拆分为多个小型服务的架构风格,每个服务都运行在自己的进程中,服务之间通过轻量级的通信机制(如 HTTP/REST、消息队列等)进行交互。它具有以下显著特点:
- 服务拆分:遵循单一职责原则,每个微服务专注于完成一项特定的任务或功能,比如在电商系统中,将用户管理、商品管理、订单管理等功能拆分成独立的微服务,每个微服务负责自己的业务逻辑和数据存储,这样使得服务的功能单一,易于开发、维护和理解。
- 独立部署:各个微服务可以独立进行部署、升级和扩展,互不影响。例如,当订单微服务的业务量增加时,可以单独对订单微服务进行扩展,而无需对整个系统进行调整,从而加快了业务迭代的速度,提高了系统的灵活性和可扩展性。
- 去中心化:在微服务架构中,不存在一个统一的管理中心来控制所有服务,而是各个服务自治,每个服务可以根据自身的需求选择合适的技术栈、数据库等,这种去中心化的管理和治理方式,支持团队的敏捷性和创新。
1.2 微服务与单体架构对比
- 优势:
- 可扩展性:微服务架构下每个服务可以根据负载进行单独扩展,比如在电商大促期间,可以针对订单服务和商品服务进行重点扩展,以应对高并发,而单体架构扩展时往往需要整体扩展,成本较高且效率较低。
- 灵活性和敏捷性:各服务可采用不同技术栈,独立开发和部署,能快速响应业务变化,如用户服务可以用 Java 开发,搜索服务可以用 Python 结合 Elasticsearch 开发,而单体架构技术栈相对单一,修改和部署都较为复杂。
- 故障隔离:某个微服务出现故障,理论上只会影响自身功能,不会导致整个系统瘫痪,比如支付微服务故障,不会影响用户浏览商品,而单体架构中一处错误可能引发整个系统崩溃。
- 技术多样性:允许为不同服务选择最适合的框架、语言和工具,优化开发效率和性能 ,而单体架构技术选型较为统一,难以针对不同功能模块进行优化。
- 挑战:
- 管理复杂性增加:服务数量增多,管理和协调变得更加复杂,需要处理服务间通信、服务发现、分布式事务等问题。
- 分布式系统挑战:需要处理分布式系统的复杂性,如网络延迟、分布式事务等,确保数据一致性的难度较大。
- 运维成本增加:每个服务都需要独立部署和监控,增加了运维成本,对运维人员的技术要求也更高。
- 适用场景:
- 微服务架构:适用于大型、复杂、业务变化频繁、需要高可扩展性和灵活性的系统,如大型电商平台、社交网络平台等。
- 单体架构:适用于小型项目、业务逻辑简单、开发周期短、资源有限的场景,比如一些小型的企业内部管理系统。
1.3 Spring Cloud 核心组件
Spring Cloud 是一系列框架的集合,它为微服务架构提供了丰富的组件,用于实现服务治理、配置管理、负载均衡等功能,以下是一些核心组件:
- Eureka:服务注册与发现组件,主要负责服务实例的注册和发现。微服务启动时会将自己注册到 Eureka Server 上,其他微服务通过 Eureka Server 获取服务实例列表,从而实现服务间的通信。Eureka Server 采用 CS 架构,并且具有自我保护机制,在网络分区等异常情况下,能保证服务的可用性。
- Ribbon:客户端负载均衡器,它与服务发现组件(如 Eureka)无缝集成,当一个微服务需要调用另一个微服务时,Ribbon 会从服务实例列表中选择一个合适的实例进行调用,提供了多种负载均衡策略,如轮询、随机、加权等,以提高系统的性能和可用性。
- Feign:声明式服务调用组件,基于接口的注解配置,让远程服务调用像调用本地方法一样简单。它集成了 Ribbon 的负载均衡功能,并且支持熔断器集成,在调用服务出现异常时可以进行容错处理。
- Gateway:API 网关,是微服务架构的统一入口,负责对外部请求进行路由转发、请求过滤、权限验证等操作 。它基于 Spring 5、Spring Boot 2 和 Project Reactor 等技术开发,采用异步非阻塞模型,性能优越,并且支持多种谓词和过滤器,能灵活地对请求进行处理。
二、服务注册与发现(Eureka/Nacos)
2.1 Eureka Server 搭建
Eureka Server 是服务注册与发现的核心组件,下面是搭建 Eureka Server 的详细步骤:
- 创建 Spring Boot 项目:使用 Spring Initializr 创建一个新的 Spring Boot 项目,在依赖选择中添加Spring Cloud Netflix Eureka Server依赖。如果是使用 Maven 项目,在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.0</version> <!-- 根据实际情况调整版本 -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 配置启动类:在启动类上添加@EnableEurekaServer注解,开启 Eureka Server 功能。例如:
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.yml文件中配置 Eureka Server 的相关属性,比如端口号、服务名称、是否注册自己、是否获取注册表等。示例配置如下:
server:
port: 8761 # Eureka Server端口
spring:
application:
name: eureka-server # 服务名称
eureka:
instance:
hostname: localhost # 主机名
client:
register-with-eureka: false # 不注册自己到Eureka Server
fetch-registry: false # 不从Eureka Server获取服务列表
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # Eureka Server地址
完成上述配置后,启动 Eureka Server 应用,访问http://localhost:8761,如果看到 Eureka Server 的管理界面,说明搭建成功。
2.2 服务提供者开发
服务提供者是提供具体业务功能的微服务,需要将自身注册到 Eureka Server 并暴露接口,步骤如下:
- 创建 Spring Boot 项目:同样使用 Spring Initializr 创建项目,并添加Spring Cloud Netflix Eureka Client和Spring Boot Starter Web依赖。Maven 依赖配置如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 配置启动类:在启动类上添加@EnableEurekaClient注解(Spring Cloud 2020+ 版本默认启用服务发现功能,此注解可以省略),表示该服务是 Eureka 客户端,会向 Eureka Server 注册。例如:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
- 配置服务注册信息:在application.yml中配置服务名称、Eureka Server 地址等信息,确保服务能够正确注册到 Eureka Server。示例配置:
server:
port: 8081 # 服务提供者端口
spring:
application:
name: user-service # 服务名称
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # Eureka Server地址
instance:
prefer-ip-address: true # 使用IP地址注册
- 暴露接口:编写 Controller 类,定义对外提供服务的接口。例如,创建一个简单的用户服务接口:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users")
public String getUsers() {
return "User Service is running!";
}
}
启动服务提供者应用,在 Eureka Server 的管理界面中可以看到user-service已经注册成功,这表明服务提供者已经成功将自身注册到 Eureka Server,并可以对外提供服务。
2.3 服务消费者开发
服务消费者通过 Eureka Server 获取服务提供者的实例列表,并使用RestTemplate+Ribbon进行服务调用,实现步骤如下:
- 创建 Spring Boot 项目:创建项目时添加Spring Cloud Netflix Eureka Client、Spring Boot Starter Web依赖,如果没有默认引入 Ribbon,还需要添加Spring Cloud Netflix Ribbon依赖(一般 Eureka Client 中已经包含 Ribbon 依赖)。Maven 依赖配置如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 配置启动类:启动类添加@EnableEurekaClient注解(同服务提供者,新版本可省略),开启 Eureka 客户端功能。示例代码:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
- 配置服务注册信息:在application.yml中配置服务名称和 Eureka Server 地址,与服务提供者类似。例如:
server:
port: 8082 # 服务消费者端口
spring:
application:
name: order-service # 服务名称
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # Eureka Server地址
- 配置并使用 RestTemplate:在配置类中创建RestTemplate实例,并添加@LoadBalanced注解,使其具备负载均衡能力,能够与 Ribbon 结合使用。示例代码:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
- 调用服务:在 Controller 中注入RestTemplate,通过服务名调用服务提供者的接口。例如,订单服务调用用户服务获取用户信息:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/getUser")
public String getUser() {
String url = "http://user-service/users";
return restTemplate.getForObject(url, String.class);
}
}
通过以上步骤,服务消费者就可以通过 Eureka Server 发现服务提供者,并使用RestTemplate+Ribbon进行服务调用。
2.4 Nacos 整合
Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,它可以将服务注册与配置中心的功能合二为一,以下是整合 Nacos 的步骤:
- 引入依赖:在 Spring Boot 项目的pom.xml文件中引入spring-cloud-starter-alibaba-nacos-discovery和spring-cloud-starter-alibaba-nacos-config依赖,用于服务注册和配置管理。示例依赖配置:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
同时,确保项目中引入了 Spring Cloud Alibaba 和 Spring Cloud 相关的依赖管理:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2023.0.1</version> <!-- 根据实际情况调整版本 -->
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.0</version> <!-- 根据实际情况调整版本 -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 配置 Nacos Server 地址:在bootstrap.yml(优先于application.yml加载,用于获取 Nacos 配置)或application.yml文件中配置 Nacos Server 的地址、服务名等信息。如果使用bootstrap.yml,配置如下:
spring:
application:
name: product-service # 服务名称
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos Server地址
config:
server-addr: 127.0.0.1:8848 # Nacos Server地址
file-extension: yaml # 配置文件格式
prefix: ${spring.application.name} # 配置文件前缀,一般为服务名
- 启用服务注册与发现:在启动类上添加@EnableDiscoveryClient注解,启用服务注册与发现功能。例如:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
- 使用 Nacos 配置中心(可选):如果需要使用 Nacos 作为配置中心,可以在 Nacos 控制台创建配置文件,配置文件的Data ID格式一般为 s p r i n g . a p p l i c a t i o n . n a m e − {spring.application.name}- spring.application.name−{spring.profiles.active}.${file-extension},例如product-service-dev.yaml。在应用中,可以通过@Value注解或@ConfigurationProperties注解获取配置中心的配置。例如,在 Controller 中获取配置:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@Value("${product.name}")
private String productName;
@GetMapping("/product/info")
public String getProductInfo() {
return "Product Name: " + productName;
}
}
通过以上步骤,就完成了 Nacos 的整合,实现了服务注册与配置中心二合一的功能,在实际开发中可以大大提高开发效率和系统的可维护性。
三、服务调用与负载均衡
3.1 Feign 声明式服务调用
Feign 是一种声明式的 Web 服务客户端,它让服务调用变得更加简单和直观,开发者只需定义一个接口并使用注解来配置 HTTP 请求,Feign 会自动生成实现类来处理 HTTP 请求的发送和接收。
- 依赖导入:在服务消费者的pom.xml文件中添加spring-cloud-starter-openfeign依赖。例如:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 接口定义:创建一个 Feign 客户端接口,使用@FeignClient注解指定要调用的服务名称,接口中的方法使用 Spring MVC 风格的注解来定义请求的路径、方法和参数等信息。比如,订单服务调用用户服务获取用户信息,定义如下接口:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "user-service")
public interface UserFeignClient {
@GetMapping("/users/{id}")
String getUserById(@PathVariable("id") Long id);
}
- 参数传递:在 Feign 接口方法中,可以使用@PathVariable、@RequestParam、@RequestBody等注解来传递参数。其中,@PathVariable用于路径参数,@RequestParam用于查询参数,@RequestBody用于请求体参数 。例如:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "product-service")
public interface ProductFeignClient {
@GetMapping("/products")
String getProducts(@RequestParam("category") String category);
@PostMapping("/products")
String addProduct(@RequestBody Product product);
}
在上述代码中,getProducts方法通过@RequestParam传递category参数,addProduct方法通过@RequestBody传递Product对象作为请求体。使用时,在需要调用服务的地方注入 Feign 客户端接口,即可像调用本地方法一样调用远程服务。例如:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private UserFeignClient userFeignClient;
@GetMapping("/order/{userId}")
public String getOrderByUserId(@PathVariable Long userId) {
String userInfo = userFeignClient.getUserById(userId);
// 处理订单逻辑,结合用户信息等
return "Order related to user: " + userInfo;
}
}
3.2 Ribbon 负载均衡策略
Ribbon 是一个客户端负载均衡器,它与 Eureka 等服务发现组件紧密集成,为服务调用提供了负载均衡的功能,通过在客户端维护服务实例列表,并根据一定的策略选择合适的实例进行调用,从而提高系统的可用性和性能。
- 默认策略:Ribbon 的默认负载均衡策略是ZoneAvoidanceRule(区域感知策略),在单区域环境下,它类似于轮询策略(RoundRobinRule) 。ZoneAvoidanceRule会综合考虑区域的可用性和实例的可用性,优先选择处于可用区域且负载较低的实例。例如,在一个包含多个数据中心(区域)的分布式系统中,它会避免选择那些整体性能较差或者网络不稳定的区域中的实例,而是从性能较好的区域中选择实例进行调用。
- 自定义策略:如果默认策略不能满足业务需求,可以通过配置或代码方式自定义负载均衡策略。
- 配置方式:在application.yml文件中,针对特定的服务进行策略配置。比如,要将user-service的负载均衡策略改为随机策略(RandomRule),配置如下:
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
- 代码方式:创建一个配置类,定义IRule的 Bean 来指定负载均衡策略。例如,创建一个配置类来使用最少并发数策略(BestAvailableRule):
import com.netflix.loadbalancer.BestAvailableRule;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RibbonConfig {
@Bean
public IRule ribbonRule() {
return new BestAvailableRule();
}
}
在上述代码中,BestAvailableRule会选择当前并发请求数最小的服务实例进行调用,适用于希望将请求分配到负载较轻实例的场景,通过这种方式可以根据实际业务场景灵活选择合适的负载均衡策略,优化服务调用的性能和可用性。
3.3 服务熔断与降级
在分布式系统中,服务之间存在依赖关系,当某个服务出现故障或响应超时,可能会导致级联故障,最终使整个系统崩溃,这就是所谓的 “服务雪崩”。为了防止这种情况发生,可以使用 Hystrix 来实现服务熔断与降级。
- Hystrix 整合:在项目中引入spring-cloud-starter-netflix-hystrix依赖。例如:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 启用 Hystrix:在启动类上添加@EnableHystrix注解,开启 Hystrix 功能。例如:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableHystrix
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 服务熔断:Hystrix 通过断路器(Circuit Breaker)来实现服务熔断。当对某个服务的调用失败率达到一定阈值(默认是 50%),且在一定时间窗口(默认 10 秒)内请求数达到一定数量(默认 20 个)时,断路器会打开,后续对该服务的请求将不再实际调用,而是直接返回一个预设的 fallback 结果,快速失败,避免资源的无效消耗。例如,对一个调用用户服务的方法进行熔断配置:
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@HystrixCommand(commandProperties = {
// 熔断触发的最小请求数,20个
@com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
// 熔断触发的错误百分比阈值,50%
@com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
// 熔断开启后的休眠时间窗,5秒
@com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
})
public String getUserInfo(Long userId) {
// 实际调用用户服务的逻辑
// 例如通过Feign调用其他服务获取用户信息
}
}
- 服务降级:当服务熔断或者服务调用出现异常(如超时、运行时异常等)时,会触发服务降级。通过定义 fallback 方法,在服务不可用时返回一个兜底的结果,保证系统的基本可用性 。例如,继续上面的例子,为getUserInfo方法添加 fallback 方法:
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@HystrixCommand(commandProperties = {
@com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
@com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
@com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
}, fallbackMethod = "getUserInfoFallback")
public String getUserInfo(Long userId) {
// 实际调用用户服务的逻辑
}
public String getUserInfoFallback(Long userId) {
// 降级逻辑,返回默认信息或错误提示
return "User service is currently unavailable, please try again later.";
}
}
通过服务熔断与降级机制,可以有效地防止服务雪崩,提高系统的稳定性和容错性。
3.4 实战案例
下面通过一个基于 Spring Cloud 的用户 - 订单微服务调用案例,来巩固前面所学的知识,展示完整的微服务开发流程。
- 项目结构:
- eureka-server:服务注册中心,负责服务的注册与发现。
- user-service:用户服务,提供用户相关的接口,如查询用户信息。
- order-service:订单服务,处理订单相关业务,需要调用用户服务获取用户信息。
- 实现步骤:
- 搭建 Eureka Server:按照前面 “2.1 Eureka Server 搭建” 的步骤,创建 Eureka Server 项目,配置并启动,使其监听在8761端口。
- 开发用户服务:依据 “2.2 服务提供者开发” 的内容,创建user-service项目,注册到 Eureka Server,暴露查询用户信息的接口。例如,创建UserController:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users/{id}")
public String getUserById(@PathVariable Long id) {
// 模拟从数据库或其他数据源获取用户信息
return "User with id " + id + " information";
}
}
- 开发订单服务:参照 “2.3 服务消费者开发” 和 “3.1 Feign 声明式服务调用” 的步骤,创建order-service项目,注册到 Eureka Server,并使用 Feign 调用user-service。首先添加 Feign 依赖,然后创建 Feign 客户端接口UserFeignClient:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "user-service")
public interface UserFeignClient {
@GetMapping("/users/{id}")
String getUserById(@PathVariable("id") Long id);
}
接着在OrderController中注入UserFeignClient并调用:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private UserFeignClient userFeignClient;
@GetMapping("/orders/{userId}")
public String getOrderByUserId(@PathVariable Long userId) {
String userInfo = userFeignClient.getUserById(userId);
// 处理订单逻辑,结合用户信息创建订单等
return "Order created for user: " + userInfo;
}
}
- 负载均衡与服务熔断降级:根据 “3.2 Ribbon 负载均衡策略” 和 “3.3 服务熔断与降级”,在order-service中配置 Ribbon 的负载均衡策略(如使用随机策略),并对调用user-service的方法添加 Hystrix 的熔断与降级配置。在application.yml中配置 Ribbon 策略:
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
在UserFeignClient接口对应的调用方法上添加 Hystrix 注解:
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "user-service")
public interface UserFeignClient {
@GetMapping("/users/{id}")
@HystrixCommand(fallbackMethod = "getUserByIdFallback")
String getUserById(@PathVariable("id") Long id);
default String getUserByIdFallback(Long id) {
return "User service is unavailable, please try again later.";
}
}
通过这个实战案例,完整地展示了 Spring Cloud 微服务中服务注册与发现、服务调用、负载均衡以及服务熔断降级的实现过程,有助于深入理解和掌握 Spring Cloud 微服务开发的核心技术。