负载均衡概述
负载均衡是微服务架构中的核心组件,用于将请求合理分配到多个服务实例上,提高系统的可用性和性能。
负载均衡的分类
负载均衡大致可以分为两类
1. 服务端负载均衡
- 实现位置:独立部署的负载均衡服务器(位于客户端和服务端之间)
- 工作原理:客户端请求先到达负载均衡器,由负载均衡器选择具体的服务实例
- 代表产品:Nginx、HAProxy、F5、阿里云SLB
- 优点:集中管理、配置简单
- 缺点:增加网络延迟、单点故障风险
客户端 负载均衡器
Nginx/HAProxy/F5 服务实例1
192.168.1.10:8080 服务实例2
192.168.1.11:8080 服务实例3
192.168.1.12:8080
2. 客户端负载均衡
- 实现位置:集成在客户端应用程序内部
- 工作原理:客户端维护服务提供者列表,根据算法选择服务实例
- 代表产品:Ribbon、Spring Cloud LoadBalancer
- 优点:无单点故障、减少网络跳转
- 缺点:客户端复杂度增加
获取服务列表 服务注册 服务注册 服务注册 客户端应用
内置负载均衡组件
Ribbon/LoadBalancer 注册中心
Eureka/Nacos 服务实例1
payment-service:8001 服务实例2
payment-service:8002 服务实例3
payment-service:8003
Spring Cloud中的负载均衡实现
1. Feign + Ribbon(Spring Cloud 2020之前)
java
// 依赖配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
// 主启动类
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
// Feign客户端定义
@FeignClient(name = "payment-service")
public interface PaymentService {
@GetMapping("/payment/get/{id}")
String getPaymentById(@PathVariable("id") Long id);
}
工作原理:
- Feign接收到对服务名("payment-service")的调用请求
- Ribbon的LoadBalancerFeignClient通过拦截器机制自动拦截HTTP请求,识别服务名
- Ribbon从服务注册中心获取该服务("payment-service")的可用实例列表
- 使用默认的轮询算法或配置的其他算法选择目标实例
- 将HTTP请求路由到选中的服务实例并返回结果
2. Feign + Spring Cloud LoadBalancer(Spring Cloud 2020之后)
java
// 依赖配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
// 主启动类
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
// Feign客户端定义
@FeignClient(name = "payment-service")
public interface PaymentService {
@GetMapping("/payment/get/{id}")
String getPaymentById(@PathVariable("id") Long id);
}
工作原理:
- Feign接收到对服务名("payment-service")的调用请求
- Spring Cloud LoadBalancer的LoadBalancerInterceptor通过拦截器机制自动拦截HTTP请求,提取服务名
- Spring Cloud LoadBalancer从服务注册中心获取该服务("payment-service")的可用实例列表
- 使用轮询算法或配置的其他算法选择目标实例
- 将HTTP请求路由到选中的服务实例并返回结果
3. Feign + 自定义负载均衡策略
java
// 依赖配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
// 主启动类
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
// 自定义负载均衡配置
@Configuration
public class CustomLoadBalancerConfig {
@Bean
public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
Environment environment,
LoadBalancerClientFactory clientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
clientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
// Feign客户端定义
@FeignClient(name = "payment-service", configuration = CustomLoadBalancerConfig.class)
public interface PaymentService {
@GetMapping("/payment/get/{id}")
String getPaymentById(@PathVariable("id") Long id);
}
工作原理:
- Feign接收到对服务名("payment-service")的调用请求
- Spring Cloud LoadBalancer的LoadBalancerInterceptor通过拦截器机制自动拦截HTTP请求,并提取服务名
- 自定义LoadBalancer从服务注册中心获取该服务("payment-service")的可用实例列表
- 使用自定义负载均衡策略选择目标实例
- 将HTTP请求路由到选中的服务实例并返回结果