分布式架构网络通信
在分布式系统设计中,网络通信是最基础也是最重要的组成部分。在Java生态系统中,有多种技术可以实现远程服务通信:
- RMI (Remote Method Invocation):Java原生的远程调用框架
- Hessian:基于HTTP的轻量级RPC框架
- SOAP:基于XML的Web服务协议
- ESB (Enterprise Service Bus):企业服务总线
- JMS (Java Message Service):面向消息的中间件API
基本原理
网络通信基础
从计算机系统底层来看,网络通信的本质是将数据从一台计算机传输到另一台计算机。这个过程主要涉及两个关键组件:
-
传输协议:
- TCP:面向连接的可靠传输协议,提供数据顺序保证和重传机制
- UDP:无连接的不可靠传输协议,提供较低的延迟
-
网络IO模型:
- BIO (Blocking IO):同步阻塞模型
- NIO (Non-blocking IO):同步非阻塞模型
- AIO (Asynchronous IO):异步非阻塞模型
开发流程
服务端开发步骤
- 定义远程接口:创建一个继承自
java.rmi.Remote的子接口 - 实现远程接口:创建一个实现类,继承
java.rmi.server.UnicastRemoteObject - 启动RMI服务器:创建注册表并绑定远程对象
客户端开发步骤
- 查找远程对象:使用
Naming.lookup()方法获取远程对象的Stub - 调用远程方法:调用方法与本地方法调用语法相同
代码实现
创建远程接口
package icu.wzk.service;
import icu.wzk.model.WzkUser;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface WzkService extends Remote {
String sayHello(WzkUser wzkUser) throws RemoteException;
}
创建引用对象
package icu.wzk.model;
public class WzkUser implements Serializable {
private String name;
private int age;
// 省略 get 和 set 方法
}
实现远程服务对象
package icu.wzk.service.impl;
import icu.wzk.model.WzkUser;
import icu.wzk.service.WzkService;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class WzkServiceImpl extends UnicastRemoteObject implements WzkService {
private static final long serialVersionUID = 1L;
public WzkServiceImpl() throws RemoteException {
super();
}
@Override
public String sayHello(WzkUser wzkUser) throws RemoteException {
System.out.println("WzkService: " + wzkUser.getName() + ", " + wzkUser.getAge());
return "success";
}
}
服务端程序
package icu.wzk;
import icu.wzk.service.WzkService;
import icu.wzk.service.impl.WzkServiceImpl;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class WzkServer {
public static void main(String[] args) throws Exception {
WzkService wzkService = new WzkServiceImpl();
LocateRegistry.createRegistry(8888);
Naming.bind("//127.0.0.1:8888/wzk", wzkService);
}
}
客户端程序
package icu.wzk;
import icu.wzk.model.WzkUser;
import icu.wzk.service.WzkService;
import java.rmi.Naming;
public class WzkClient {
public static void main(String[] args) throws Exception {
WzkService wzkService = (WzkService) Naming.lookup("//127.0.0.1:8888/wzk");
WzkUser wzkUser = new WzkUser();
wzkUser.setAge(18);
wzkUser.setName("wzkicu");
System.out.println(wzkService.sayHello(wzkUser));
}
}
测试效果
运行 WzkServer 和 WzkClient 程序后:
- 客户端返回结果:
success - 服务端输出:
WzkService: wzkicu, 18