RPC-准备阶段
2020-02-16 本文已影响0人
白璞1024
他是一种通过网络从远程计算机程序上请求服务,不需要了解底层网络的技术
完整的RPC网络调用流程
- 服务消费方:以本地调用方式调用客户端存根;
- 什么叫客户端存根?就是远程方法在本地的模拟对象,一样的也有方法名,也有方法参数,client stub 接收到调用后负责将方法名方法的参数等包装,并将包装后的信息通过网络发送到服务端。
- 服务端收到消息后,交给代理存根在服务器的部分后尽心解码为实际的方法名和参数
- server stub 根据解码结果调用服务器上本地的实际服务。
- 本地服务执行,将结果返回给server stub
- server stub将返回的结果打包成消息并发送给消费方
- client stub接受到消息进行解码
- 消费方得到最后的结果。
写一个类似框架,需要解决几个不常用的问题
- 代理模式
- 序列化问题 利用java的相关机制,也就是Serializable
- 通信问题 BIO
- 登记的服务实力化问题 使用反射机制
- 在运行时候,判断任意一个对象所属的类
- 运行时候构造人意一个类的对象
- 运行时候,判断任意一个类所就有的方法和成员变量
- 运行时候,调用任意一个对象的方法
- 生成动态代理
下边的代码简单的解释一下上述的问题
1、 代理模式
//静态代理方法的实现
/**
* 接口类
*/
public interface IGetServer {
void choice(String desc);
}
/**
* 接口的实现类
*/
public class Receptionist implements IGetServer {
public void choice(String desc) {
System.out.println(desc);
}
}
/**
*代理类
*/
public class ProxyServer implements InvocationHandler {
private Object receptionist;//实现类的实例
public ProxyServer(Object receptionist) {
this.receptionist = receptionist;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行对应的方法之前执行的方法");
//实际的方法
Object result = method.invoke(receptionist,args);
System.out.println("执行之后执行的方法");
return result;
}
}
//-----------------------------------
/**
*调用类
*/
public class Proxyclient {
//调用代理方法
public static void main(String[] args) {
IGetServer ig = (IGetServer) Proxy.newProxyInstance(IGetServer.class.getClassLoader(),new Class[]{IGetServer.class},new ProxyServer(new Receptionist()));
ig.choice("这里是我要传入的参数");
}
}
2、 序列化
bean
同时实现了Se rierizable就好了
public class SerialBean implements Serializable {
private final String name;
private final String age;
public SerialBean(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
主要用到的是如何调用序列化和反序列化
public class TestSerial {
public static void main(String[] args) {
setSer();//序列化
getSer();
}
//序列化
private static void setSer() {
SerialBean bean = new SerialBean("Mark","123");
List<String> list= new ArrayList<String>();
list.add("my name");
list.add( "is " );
list.add("mark");
ObjectOutputStream os = null;
try {
os = new ObjectOutputStream(new FileOutputStream("/Users/weblogic/study/Serial.txt"));
os.writeObject(bean);
os.writeObject(list);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void getSer(){
try {
ObjectInputStream is = new ObjectInputStream(
new FileInputStream("/Users/weblogic/study/Serial.txt"));
SerialBean bean = (SerialBean) is.readObject();
System.out.println(bean.getAge());
System.out.println(bean.getName());
List tempList = (List) is.readObject();
for(Iterator iterable = tempList.iterator();iterable.hasNext();){
System.out.println(iterable.next());
}
is.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
3、 反射
public class RefleDemo {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//实例化对象的标准用法
Servant servant = new Servant();
servant.service("hello|");
// 全限定名拿到勒的class对象
Class servantClazz = Class.forName("cn.baip.netty.rpc.refle.Servant");
//通过class对象拿到类的实例
Servant servant1 = (Servant) servantClass.newInstance();
//拿到所有的方法名
Method[] methods = servantClazz.getMethods();
for (Method method :methods){
System.out.println(method.getName());//方法的名称
if(method.getName().equals("toString")){
try {
System.out.println(method.invoke(servant1,null));
System.out.println("执行,"+method.invoke(servantClazz.newInstance(),null));
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}