挑战 |
描述 |
解决方案 |
网络延迟 |
节点间物理距离导致延迟 |
缓存、就近访问 |
节点故障 |
部分节点不可用 |
冗余设计、故障检测 |
消息丢失 |
网络问题导致消息丢失 |
可靠传输协议、重试机制 |
一致性保证 |
数据在多节点间保持一致 |
共识算法、最终一致性 |
特性 |
RPC |
消息队列 |
通信模式 |
请求 - 响应同步模式 |
异步发布 - 订阅模式 |
耦合度 |
高(客户端依赖服务接口) |
低(生产者与消费者解耦) |
可靠性 |
依赖网络和服务可用性 |
消息持久化,可靠性高 |
适用场景 |
服务间强依赖的实时调用 |
异步任务处理、流量削峰 |
// 服务接口定义
public interface HelloService {
String sayHello(String name);
}
// 服务实现
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
// RPC请求对象
public class RpcRequest implements Serializable {
private static final long serialVersionUID = 1L;
private String className;
private String methodName;
private Object[] parameters;
// getters and setters
}
// RPC响应对象
public class RpcResponse implements Serializable {
private static final long serialVersionUID = 1L;
private Object result;
private Throwable exception;
// getters and setters
}
// 服务端
public class RpcServer {
private final int port;
private final Map serviceMap = new HashMap<>();
public RpcServer(int port) {
this.port = port;
}
public void registerService(String serviceName, Object service) {
serviceMap.put(serviceName, service);
}
public void start() throws IOException {
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("RPC服务器启动,监听端口: " + port);
while (true) {
try (Socket socket = serverSocket.accept();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream())) {
// 读取请求
RpcRequest request = (RpcRequest) input.readObject();
// 查找并调用服务
Object service = serviceMap.get(request.getClassName());
RpcResponse response = new RpcResponse();
try {
Method method = service.getClass().getMethod(
request.getMethodName(),
getParameterTypes(request.getParameters()));
Object result = method.invoke(service, request.getParameters());
response.setResult(result);
} catch (Exception e) {
response.setException(e);
}
// 返回响应
output.writeObject(response);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
private Class>[] getParameterTypes(Object[] parameters) {
if (parameters == null || parameters.length == 0) {
return new Class[0];
}
Class>[] parameterTypes = new Class[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parameterTypes[i] = parameters[i].getClass();
}
return parameterTypes;
}
}
// 客户端
public class RpcClient {
private final String host;
private final int port;
public RpcClient(String host, int port) {
this.host = host;
this.port = port;
}
@SuppressWarnings("unchecked")
public T createProxy(Class serviceClass) {
return (T) Proxy.newProxyInstance(
serviceClass.getClassLoader(),
new Class>[]{serviceClass},
(proxy, method, args) -> {
try (Socket socket = new Socket(host, port);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream())) {
// 创建并发送请求
RpcRequest request = new RpcRequest();
request.setClassName(serviceClass.getName());
request.setMethodName(method.getName());
request.setParameters(args);
output.writeObject(request);
// 接收响应
RpcResponse response = (RpcResponse) input.readObject();
if (response.getException() != null) {
throw response.getException();
}
return response.getResult();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
});
}
}
// 使用示例
public class RpcExample {
public static void main(String[] args) {
// 启动服务器
new Thread(() -> {
try {
RpcServer server = new RpcServer(9000);
server.registerService(HelloService.class.getName(), new HelloServiceImpl());
server.start();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
// 客户端调用
RpcClient client = new RpcClient("localhost", 9000);
HelloService service = client.createProxy(HelloService.class);
String result = service.sayHello("RPC");
System.out.println("远程调用结果: " + result);
}
}
模式 |
描述 |
优点 |
缺点 |
本地缓存 |
缓存数据存储在应用进程内 |
访问速度极快 |
无法共享,内存浪费 |
集中式缓存 |
所有应用访问同一缓存服务器 |
数据共享,减少冗余 |
单点故障风险 |
分布式缓存 |
缓存数据分布在多个节点 |
高可用,可扩展性强 |
实现复杂度高 |
// 缓存节点接口
public interface CacheNode {
void put(String key, Object value);
Object get(String key);
void remove(String key);
Set getKeys();
}
// 本地缓存实现
public class LocalCache implements CacheNode {
private final ConcurrentHashMap cache = new ConcurrentHashMap<>();
@Override
public void put(String key, Object value) {
cache.put(key, value);
}
@Override
public Object get(String key) {
return cache.get(key);
}
@Override
public void remove(String key) {
cache.remove(key);
}
@Override
public Set getKeys() {
return cache.keySet();
}
}
// 分布式缓存节点
public class DistributedCacheNode implements CacheNode {
private final String nodeId;
private final int port;
private final LocalCache localCache = new LocalCache();
private final Map remoteNodes = new ConcurrentHashMap<>();
private final ExecutorService threadPool = Executors.newFixedThreadPool(10);
public DistributedCacheNode(String nodeId, int port) {
this.nodeId = nodeId;
this.port = port;
}
// 启动节点服务器
public void start() {
threadPool.submit(() -> {
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("缓存节点 " + nodeId + " 启动,监听端口: " + port);
while (true) {
try (Socket socket = serverSocket.accept();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream())) {
CacheRequest request = (CacheRequest) input.readObject();
CacheResponse response = new CacheResponse();
try {
switch (request.getOperation()) {
case PUT:
localCache.put(request.getKey(), request.getValue());
break;
case GET:
response.setValue(localCache.get(request.getKey()));
break;
case REMOVE:
localCache.remove(request.getKey());
break;
case GET_KEYS:
response.setKeys(localCache.getKeys());
break;
}
} catch (Exception e) {
response.setException(e);
}
output.writeObject(response);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
// 连接到其他节点
public void connectToNode(String nodeId, String host, int port) {
remoteNodes.put(nodeId, new RemoteCacheNode(host, port));
}
// 分布式哈希算法确定节点
private String getResponsibleNode(String key) {
// 简化实现,实际应使用一致性哈希算法
List nodeIds = new ArrayList<>(remoteNodes.keySet());
nodeIds.add(this.nodeId);
Collections.sort(nodeIds);
return nodeIds.get(Math.abs(key.hashCode()) % nodeIds.size());
}
@Override
public void put(String key, Object value) {
String responsibleNode = getResponsibleNode(key);
if (responsibleNode.equals(this.nodeId)) {
localCache.put(key, value);
} else {
remoteNodes.get(responsibleNode).put(key, value);
}
}
@Override
public Object get(String key) {
String responsibleNode = getResponsibleNode(key);
if (responsibleNode.equals(this.nodeId)) {
return localCache.get(key);
} else {
return remoteNodes.get(responsibleNode).get(key);
}
}
@Override
public void remove(String key) {
String responsibleNode = getResponsibleNode(key);
if (responsibleNode.equals(this.nodeId)) {
localCache.remove(key);
} else {
remoteNodes.get(responsibleNode).remove(key);
}
}
@Override
public Set getKeys() {
// 简化实现,实际应合并所有节点的keys
return localCache.getKeys();
}
}
// 远程缓存节点代理
public class RemoteCacheNode implements CacheNode {
private final String host;
private final int port;
public RemoteCacheNode(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public void put(String key, Object value) {
sendRequest(new CacheRequest(CacheOperation.PUT, key, value));
}
@Override
public Object get(String key) {
CacheResponse response = sendRequest(new CacheRequest(CacheOperation.GET, key));
return response.getValue();
}
@Override
public void remove(String key) {
sendRequest(new CacheRequest(CacheOperation.REMOVE, key));
}
@Override
public Set getKeys() {
CacheResponse response = sendRequest(new CacheRequest(CacheOperation.GET_KEYS));
return response.getKeys();
}
private CacheResponse sendRequest(CacheRequest request) {
try (Socket socket = new Socket(host, port);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream())) {
output.writeObject(request);
return (CacheResponse) input.readObject();
} catch (Exception e) {
throw new RuntimeException("远程缓存调用失败", e);
}
}
}
// 消息接口
public interface Message {
String getId();
String getTopic();
Object getPayload();
long getTimestamp();
}
// 消息实现
public class DefaultMessage implements Message {
private final String id;
private final String topic;
private final Object payload;
private final long timestamp;
public DefaultMessage(String id, String topic, Object payload) {
this.id = id;
this.topic = topic;
this.payload = payload;
this.timestamp = System.currentTimeMillis();
}
@Override
public String getId() {
return id;
}
@Override
public String getTopic() {
return topic;
}
@Override
public Object getPayload() {
return payload;
}
@Override
public long getTimestamp() {
return timestamp;
}
}
// 消息队列接口
public interface MessageQueue {
void publish(Message message);
Message consume(String topic);
void subscribe(String topic, MessageListener listener);
void unsubscribe(String topic, MessageListener listener);
}
// 消息队列实现
public class SimpleMessageQueue implements MessageQueue {
private final Map> topicQueues = new ConcurrentHashMap<>();
private final Map> topicListeners = new ConcurrentHashMap<>();
private final ExecutorService threadPool = Executors.newFixedThreadPool(10);
@Override
public synchronized void publish(Message message) {
String topic = message.getTopic();
topicQueues.computeIfAbsent(topic, k -> new LinkedBlockingQueue<>()).add(message);
// 异步通知所有订阅者
List listeners = topicListeners.getOrDefault(topic, Collections.emptyList());
for (MessageListener listener : listeners) {
threadPool.submit(() -> listener.onMessage(message));
}
}
@Override
public Message consume(String topic) {
BlockingQueue queue = topicQueues.get(topic);
return queue != null ? queue.poll() : null;
}
@Override
public synchronized void subscribe(String topic, MessageListener listener) {
topicListeners.computeIfAbsent(topic, k -> new CopyOnWriteArrayList<>()).add(listener);
}
@Override
public synchronized void unsubscribe(String topic, MessageListener listener) {
List listeners = topicListeners.get(topic);
if (listeners != null) {
listeners.remove(listener);
}
}
}
// 分布式消息队列节点
public class DistributedMessageQueueNode implements MessageQueue {
private final String nodeId;
private final int port;
private final SimpleMessageQueue localQueue = new SimpleMessageQueue();
private final Map remoteNodes = new ConcurrentHashMap<>();
private final ConsistentHashRouter router;
public DistributedMessageQueueNode(String nodeId, int port, List nodeIds) {
this.nodeId = nodeId;
this.port = port;
this.router = new ConsistentHashRouter(nodeIds);
}
// 启动节点服务器
public void start() {
// 启动网络服务接收消息
new Thread(() -> {
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("消息队列节点 " + nodeId + " 启动,监听端口: " + port);
while (true) {
try (Socket socket = serverSocket.accept();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream())) {
// 处理消息请求
MessageRequest request = (MessageRequest) input.readObject();
switch (request.getType()) {
case PUBLISH:
localQueue.publish(request.getMessage());
break;
case CONSUME:
Message message = localQueue.consume(request.getTopic());
output.writeObject(message);
break;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
// 连接到其他节点
public void connectToNode(String nodeId, String host, int port) {
remoteNodes.put(nodeId, new RemoteMessageQueueNode(host, port));
}
@Override
public void publish(Message message) {
String responsibleNode = router.getNode(message.getTopic());
if (responsibleNode.equals(nodeId)) {
localQueue.publish(message);
} else {
remoteNodes.get(responsibleNode).publish(message);
}
}
@Override
public Message consume(String topic) {
String responsibleNode = router.getNode(topic);
if (responsibleNode.equals(nodeId)) {
return localQueue.consume(topic);
} else {
return remoteNodes.get(responsibleNode).consume(topic);
}
}
@Override
public void subscribe(String topic, MessageListener listener) {
localQueue.subscribe(topic, listener);
}
@Override
public void unsubscribe(String topic, MessageListener listener) {
localQueue.unsubscribe(topic, listener);
}
}
以上示例,介绍了分布式系统中网络编程的核心概念和实现方法。在实际开发中,建议使用成熟的开源框架(如gRPC、Redis、Kafka)来简化分布式系统的开发,避免重复造轮子。