1、服务接口定义
public interface Service {
String sayHello(String name);
}
2、服务接口实现
public class ServiceImpl implements Service {
@Override
public String sayHello(String name) {
return "Hello, " + name;
}
}
3、服务端
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author ronshi
* @date 2024/6/20 14:17
*/
public class RpcServer {
private int port;
private boolean isRunning;
private ConcurrentHashMap<String, Object> serviceRegistry = new ConcurrentHashMap<>();
public RpcServer(int port) {
this.port = port;
}
public void registerService(String serviceName, Object service) {
serviceRegistry.put(serviceName, service);
}
public void start() {
isRunning = true;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("RPC Server started on port " + port);
while (isRunning) {
Socket clientSocket = serverSocket.accept();
new Thread(new ClientHandler(clientSocket, serviceRegistry)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop() {
isRunning = false;
}
private static class ClientHandler implements Runnable {
private Socket clientSocket;
private ConcurrentHashMap<String, Object> serviceRegistry;
public ClientHandler(Socket clientSocket, ConcurrentHashMap<String, Object> serviceRegistry) {
this.clientSocket = clientSocket;
this.serviceRegistry = serviceRegistry;
}
@Override
public void run() {
try (
ObjectInputStream input = new ObjectInputStream(clientSocket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(clientSocket.getOutputStream())) {
String serviceName = input.readUTF();
String methodName = input.readUTF();
Class<?>[] paramTypes = (Class<?>[]) input.readObject();
Object[] args = (Object[]) input.readObject();
Object service = serviceRegistry.get(serviceName);
if (service == null) {
output.writeObject(new RuntimeException("Service not found: " + serviceName));
return;
}
Method method = service.getClass().getMethod(methodName, paramTypes);
Object result = method.invoke(service, args);
output.writeObject(result);
} catch (Exception e) {
try (ObjectOutputStream output = new ObjectOutputStream(clientSocket.getOutputStream())) {
output.writeObject(e);
} catch (IOException ioException) {
ioException.printStackTrace();
}
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
RpcServer server = new RpcServer(8080);
server.registerService("Service", new ServiceImpl());
server.start();
}
}
4、客户端
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
/**
* @author ronshi
* @date 2024/6/20 14:29
*/
public class RpcClient {
private String host;
private int port;
public RpcClient(String host, int port) {
this.host = host;
this.port = port;
}
public Object invoke(String serviceName, String methodName, Class<?>[] paramTypes, Object[] args)
throws IOException, ClassNotFoundException {
try (
Socket socket = new Socket(host, port);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream())) {
output.writeUTF(serviceName);
output.writeUTF(methodName);
output.writeObject(paramTypes);
output.writeObject(args);
Object result = input.readObject();
if (result instanceof Throwable) {
throw new RuntimeException((Throwable) result);
}
return result;
}
}
public static void main(String[] args) {
RpcClient client = new RpcClient("localhost", 8080);
try {
Object result = client.invoke("Service", "sayHello", new Class[] {String.class}, new Object[] {"World"});
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意事项:
- 安全性:这个示例使用了Java的序列化机制,它在生产环境中是不安全的,并且性能也较差。建议使用更高效的序列化库,如Protocol Buffers、Hessian、Kryo等。
- 异常处理:在真实的应用中,需要处理各种可能的异常,如网络异常、序列化异常等。
- 服务注册与发现:这个示例只实现了简单的服务注册与发现机制,需要完善这个机制来支持服务的动态发现和负载均衡。
- 性能优化:这个示例使用了阻塞的Socket和Java序列化,这可能会成为性能瓶颈。在实际应用中,可以考虑使用NIO(如Netty)和更高效的序列化库来提高性能。
- 功能扩展:可以添加更多的功能,如超时控制、重试机制、服务路由、负载均衡等。