本文目录导读:

- 场景一:客户端负载均衡(微服务架构-Ribbon / Spring Cloud LoadBalancer)
- 场景二:服务器端负载均衡(Nginx + Java 应用)
- 场景三:使用 Java 内置工具类实现几种常见算法
在Java中实现负载均衡请求,通常有两种主要的应用场景:客户端负载均衡(如微服务调用)和 服务器端负载均衡(如反向代理)。
下面针对这两种场景,分别给出常见的实现案例和代码示例。
客户端负载均衡(微服务架构-Ribbon / Spring Cloud LoadBalancer)
在微服务架构中(例如Spring Cloud),调用方(消费者)会从注册中心获取服务列表,然后在本地通过负载均衡算法选择一个实例进行调用。
原生 Java + 简单轮询算法(手写)
这是一个最基础的方式,展示了负载均衡的核心逻辑。
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
// 模拟一个服务实例
class ServerInstance {
private String ip;
private int port;
public ServerInstance(String ip, int port) {
this.ip = ip;
this.port = port;
}
public String getUrl() {
return "http://" + ip + ":" + port + "/api/data";
}
}
// 简易轮询负载均衡器
public class RoundRobinLoadBalancer {
private final List<ServerInstance> serverList;
private final AtomicInteger counter = new AtomicInteger(0);
public RoundRobinLoadBalancer(List<ServerInstance> serverList) {
this.serverList = serverList;
}
// 获取下一个服务实例(轮询)
public ServerInstance getNextServer() {
int index = counter.getAndIncrement() % serverList.size();
return serverList.get(index);
}
// 测试
public static void main(String[] args) {
List<ServerInstance> servers = List.of(
new ServerInstance("192.168.1.1", 8080),
new ServerInstance("192.168.1.2", 8080),
new ServerInstance("192.168.1.3", 8080)
);
RoundRobinLoadBalancer lb = new RoundRobinLoadBalancer(servers);
// 模拟10次请求
for (int i = 0; i < 10; i++) {
ServerInstance server = lb.getNextServer();
System.out.println("请求 " + (i + 1) + " 分发到: " + server.getUrl());
}
}
}
输出示例:
请求 1 分发到: http://192.168.1.1:8080/api/data
请求 2 分发到: http://192.168.1.2:8080/api/data
请求 3 分发到: http://192.168.1.3:8080/api/data
请求 4 分发到: http://192.168.1.1:8080/api/data
...
Spring Cloud + LoadBalancer(推荐,企业级)
如果项目使用Spring Cloud,推荐使用 Spring Cloud LoadBalancer(取代了已进入维护状态的 Netflix Ribbon)。
依赖(pom.xml):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
RestTemplate 配置:
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
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();
}
}
服务调用代码:
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;
private static final String PRODUCT_SERVICE_URL = "http://product-service"; // 服务名
@GetMapping("/order/create")
public String createOrder() {
// 直接调用服务名,LoadBalancer会自动从注册中心获取列表并轮询
String response = restTemplate.getForObject(
PRODUCT_SERVICE_URL + "/products",
String.class
);
return "Order created, product info: " + response;
}
}
原理: Spring Cloud LoadBalancer 默认使用轮询算法,也可以切换为随机或权重等策略。
服务器端负载均衡(Nginx + Java 应用)
这是最经典的架构:Nginx 作为反向代理,把请求分发到多个 Tomcat / Spring Boot 实例。
Nginx 配置示例(nginx.conf):
upstream backend_servers {
# 默认使用轮询(round-robin)
server 192.168.1.10:8080 weight=2; # 权重2
server 192.168.1.11:8080 weight=1; # 权重1
server 192.168.1.12:8080 weight=1;
# 其他可选的算法:
# least_conn; # 最少连接
# ip_hash; # IP哈希(会话保持)
}
server {
listen 80;
server_name example.com;
location /api/ {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Java 端不需要任何负载均衡代码,只需要部署多个实例即可:
# 启动3个实例(端口不同) java -jar myapp.jar --server.port=8080 java -jar myapp.jar --server.port=8081 java -jar myapp.jar --server.port=8082
Nginx 会自动将请求分发到这三个实例。
使用 Java 内置工具类实现几种常见算法
有时你需要在一个 Java 进程中做简单的负载均衡(RPC 客户端、网关、SDK)。
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class LoadBalancerAlgorithms {
// 1. 随机算法
public static <T> T random(List<T> servers) {
Random random = new Random();
return servers.get(random.nextInt(servers.size()));
}
// 2. 加权随机算法
public static <T> T weightedRandom(Map<T, Integer> serverWeights) {
List<T> weightedList = new ArrayList<>();
serverWeights.forEach((server, weight) -> {
for (int i = 0; i < weight; i++) {
weightedList.add(server);
}
});
Random random = new Random();
return weightedList.get(random.nextInt(weightedList.size()));
}
// 3. 平滑加权轮询(解决普通加权轮询的突发流量问题)
static class SmoothWeightedRoundRobin<T> {
private final List<ServerWeight<T>> servers;
static class ServerWeight<T> {
T server;
int weight;
int currentWeight;
ServerWeight(T server, int weight) {
this.server = server;
this.weight = weight;
this.currentWeight = 0;
}
}
public SmoothWeightedRoundRobin(Map<T, Integer> serverWeights) {
this.servers = new ArrayList<>();
serverWeights.forEach((server, weight) ->
servers.add(new ServerWeight<>(server, weight))
);
}
public T getNext() {
int totalWeight = 0;
ServerWeight<T> selected = null;
for (ServerWeight<T> sw : servers) {
sw.currentWeight += sw.weight;
totalWeight += sw.weight;
if (selected == null || sw.currentWeight > selected.currentWeight) {
selected = sw;
}
}
if (selected != null) {
selected.currentWeight -= totalWeight;
return selected.server;
}
return null;
}
}
// 测试
public static void main(String[] args) {
List<String> servers = List.of("A", "B", "C");
System.out.println("随机算法: " + random(servers));
Map<String, Integer> weightedServers = new HashMap<>();
weightedServers.put("A", 5);
weightedServers.put("B", 3);
weightedServers.put("C", 2);
System.out.println("加权随机: " + weightedRandom(weightedServers));
SmoothWeightedRoundRobin<String> swrr = new SmoothWeightedRoundRobin<>(weightedServers);
for (int i = 0; i < 10; i++) {
System.out.println("平滑轮询 " + (i + 1) + ": " + swrr.getNext());
}
}
}
| 场景 | 推荐方案 | 适用场景 |
|---|---|---|
| 微服务调用 | Spring Cloud LoadBalancer / Ribbon | 服务间 RPC 调用 |
| 反向代理 | Nginx / HAProxy + Java 后端 | 对外统一入口 |
| 网关 | Spring Cloud Gateway / Zuul | API 网关层 |
| 客户端直连 | 手写轮询/随机/一致性Hash | 自定义 RPC 客户端、SDK |
| 消息队列 | 消息队列自带的生产者/消费者负载均衡 | 异步解耦 |
最佳实践建议:
- 不要重复造轮子 —— 微服务优先用 Spring Cloud LoadBalancer。
- Nginx 是最成熟的服务器端方案,性能好、配置简单。
- 如果需要会话保持,注意使用
ip_hash(Nginx)或Sticky Session。 - 如果是长连接(如 gRPC),要考虑连接池和健康检查。
如果你有更具体的场景需求(比如需要一致性哈希、动态权重调整等),可以继续追问,我可以给出针对性的实现。