本文目录导读:

- 基于Nginx的反向代理负载均衡
- Spring Cloud LoadBalancer实现
- 基于Ribbon的负载均衡(Spring Cloud Netflix)
- Dubbo的负载均衡
- 简单的Java实现
- 生产环境最佳实践
我来介绍几种常见的Java负载均衡实现案例,从简单到复杂逐步说明。
基于Nginx的反向代理负载均衡
配置示例
# nginx.conf
upstream backend_servers {
# 负载均衡策略:轮询(默认)
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083 weight=3; # 权重配置
# 其他策略示例
# ip_hash; # IP哈希
# least_conn; # 最少连接
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Spring Cloud LoadBalancer实现
添加依赖
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
RestTemplate配置
@Configuration
public class LoadBalancerConfig {
@Bean
@LoadBalanced // 添加负载均衡能力
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
服务调用
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
public String getProductInfo(String productId) {
// 直接使用服务名调用,自动负载均衡
String url = "http://product-service/api/products/" + productId;
return restTemplate.getForObject(url, String.class);
}
}
自定义负载均衡策略
@Component
public class CustomLoadBalancerConfiguration {
@Bean
public ReactorLoadBalancer<ServiceInstance> customLoadBalancer(
Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
name
);
}
}
基于Ribbon的负载均衡(Spring Cloud Netflix)
配置方式
# application.yml
product-service:
ribbon:
listOfServers: localhost:8081,localhost:8082,localhost:8083
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 随机策略
ConnectTimeout: 3000
ReadTimeout: 60000
自定义策略
public class CustomRule extends AbstractLoadBalancerRule {
private int currentIndex = 0;
private int currentWeight = 0;
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// 初始化配置
}
@Override
public Server choose(Object key) {
ILoadBalancer lb = getLoadBalancer();
if (lb == null) {
return null;
}
List<Server> servers = lb.getAllServers();
if (servers.isEmpty()) {
return null;
}
// 自定义选择逻辑(轮询加权)
return getNextServer(servers);
}
private synchronized Server getNextServer(List<Server> servers) {
// 简单的加权轮询
Server server = servers.get(currentIndex % servers.size());
currentIndex++;
return server;
}
}
Dubbo的负载均衡
配置方式
<!-- dubbo-consumer.xml -->
<dubbo:reference id="orderService"
interface="com.example.OrderService"
loadbalance="roundrobin" /> <!-- 轮询策略 -->
自定义负载均衡算法
public class CustomLoadBalance extends AbstractLoadBalance {
@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers,
URL url,
Invocation invocation) {
int length = invokers.size();
int totalWeight = 0;
boolean sameWeight = true;
int firstWeight = getWeight(invokers.get(0), invocation);
// 计算总权重
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
totalWeight += weight;
if (sameWeight && weight != firstWeight) {
sameWeight = false;
}
}
// 加权随机选择
if (totalWeight > 0 && !sameWeight) {
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
for (int i = 0; i < length; i++) {
offset -= getWeight(invokers.get(i), invocation);
if (offset < 0) {
return invokers.get(i);
}
}
}
return invokers.get(ThreadLocalRandom.current().nextInt(length));
}
}
简单的Java实现
轮询算法
public class RoundRobinLoadBalancer {
private List<String> servers;
private AtomicInteger index = new AtomicInteger(0);
public RoundRobinLoadBalancer(List<String> servers) {
this.servers = servers;
}
public String getServer() {
if (servers.isEmpty()) {
return null;
}
int currentIndex = index.getAndIncrement() % servers.size();
return servers.get(currentIndex);
}
}
加权随机算法
public class WeightedRandomLoadBalancer {
private List<ServerNode> servers;
private int totalWeight;
public WeightedRandomLoadBalancer(List<ServerNode> servers) {
this.servers = servers;
this.totalWeight = servers.stream()
.mapToInt(ServerNode::getWeight)
.sum();
}
public String getServer() {
Random random = new Random();
int randomNumber = random.nextInt(totalWeight);
int currentWeight = 0;
for (ServerNode server : servers) {
currentWeight += server.getWeight();
if (randomNumber < currentWeight) {
return server.getAddress();
}
}
return servers.get(0).getAddress();
}
@Data
@AllArgsConstructor
public static class ServerNode {
private String address;
private int weight;
}
}
生产环境最佳实践
完整配置示例
# 生产环境配置
spring:
cloud:
loadbalancer:
retry:
enabled: true # 启用重试
max-retries-on-same-service-instance: 1
max-retries-on-next-service-instance: 3
health-check:
interval: 30s # 健康检查间隔
path: /actuator/health
# Nacos作为注册中心
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.100:8848
namespace: prod
weight: 100 # 实例权重
服务端配置
# 服务端 application.yml
server:
port: ${PORT:8081}
spring:
application:
name: user-service
eureka:
instance:
lease-renewal-interval-in-seconds: 10 # 心跳间隔
lease-expiration-duration-in-seconds: 30 # 过期时间
metadata-map:
version: v1
zone: zone1
选择合适的负载均衡方案需要考虑:
- 应用场景:微服务间调用、网关分发、数据库读写分离
- 性能要求:吞吐量、响应时间
- 可用性要求:故障转移、健康检查
- 扩展性需求:动态扩容、灰度发布
对于微服务架构,推荐使用Spring Cloud LoadBalancer + Nacos/Eureka,配合Hystrix或Sentinel实现熔断降级,构建高可用的系统。