1、基本原理
RPC底层原理:
服务端:暴露一个服务接口,整个接口中方法逻辑实现
暴露服务接口:
Map
key:暴露服务接口的名称
value:这个接口对应的实现类的实例
通过客户端传入的接口名称获取暴露服务列表中的接口实例,通过反射调用对应方法
客户端:调用暴露一个服务接口,不用管整个接口的具体实现逻辑,只管调用获取相应结果就ok
接口能直接调用:不能
1、接口找到接口的实现类---no(接口的实现类不在这个机器上面,而在远程实现的)
2、使用代理来为接口生成对应代理类--- ok
3、通过网络连接找到服务端调用服务端对应接口的具体实现类中的方法
2.1、网络连接
2.2、需要把调用这个方法需要的数据准备并打包发送给服务端
2.3、准备参数【参数类型,值列表】
方法名称、接口名称
2、服务端代码
public class RpcServer {
private Map
//创建线程池管理线程提高线程复用及限制线程数
private ThreadPoolExecutor executor = new ThreadPoolExecutor(8, 20, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10));
public void publishService(Class> interfaceClass, Object instance){
this.serviceMap.put(interfaceClass.getName(), instance);
}
/**
* 启动服务的方法
* @param port
*/
public void start(int port){
try{
//监听客户端发送数据
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(port));
System.out.println("server is start.....");
while(true){
executor.execute(new Task(serverSocket.accept()));
}
}catch(Exception e){
e.printStackTrace();
}
}
private class Task implements Runnable{
private Socket client;
public Task(Socket client) {
this.client = client;
}
@Override
public void run() {
try{
//先用流放前面
ObjectInputStream deSerializer = new ObjectInputStream(client.getInputStream());
ObjectOutputStream serializer = new ObjectOutputStream(client.getOutputStream());
//通过网络连接诶获取客户端发送的数据读写
RequestData requestData = (RequestData) deSerializer.readObject();
//通过暴露服务列表获取接口对应实例
Object instance = serviceMap.get(requestData.getInterfaceName());
//反射操作
Method method = instance.getClass().getDeclaredMethod(requestData.getMethodName(), requestData.getParameterTypes());
Object result = method.invoke(instance, requestData.getParameters());
//返回给客户端
System.out.println("返回给客户端的数据:" + result);
serializer.writeObject(result);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public interface HelloApi {
public String sysHello(String name);
}
public class HelloApiImpl implements HelloApi{
public String sysHello(String name) {
return "server:" + name;
}
}
public class ServerApp {
public static void main(String[] args) {
RpcServer rpcServer = new RpcServer();
rpcServer.publishService(HelloApi.class, new HelloApiImpl());
rpcServer.start(8888);
}
}
3、客户端代码
1、依赖jar
2、代码
@Configuration
public class RpcConfig {
@Bean
public HelloApi api(){
return RpcClient.getRemoteProxy(HelloApi.class, new InetSocketAddress("localhost", 8888));
}
}
public class RpcClient {
@SuppressWarnings("unchecked")
public static
//使用jdk动态代理
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class>[]{interfaceClass}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {
//使用BIO
Socket client = new Socket();
//连接服务器
client.connect(address);
ObjectOutputStream serializer = new ObjectOutputStream(client.getOutputStream());
ObjectInputStream deSerializer = new ObjectInputStream(client.getInputStream());
//封装请求数据包
RequestData requestData = new RequestData();
requestData.setInterfaceName(interfaceClass.getName());
requestData.setMethodName(method.getName());
requestData.setParameterTypes(method.getParameterTypes());
requestData.setParameters(args);
//序列化到网络传输
serializer.writeObject(requestData);
//获取调用返回结果
return deSerializer.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
});
}
}
public class App {
public static void main(String[] args) {
//HelloApi proxy = RpcClient.getRemoteProxy(HelloApi.class, new InetSocketAddress("localhost", 8888));
ApplicationContext context = new AnnotationConfigApplicationContext(RpcConfig.class);
HelloApi proxy = context.getBean(HelloApi.class);
System.out.println(proxy.sysHello("zhangsan"));
}
}