thrift

  • 自己实现简单rpc:
实现原理:客户端和服务端建立socket链接,客户端使用jdk代理,将要调用的方法的类名,方法名,方法参数类型,
方法参数通过socket输出流发送到server端,server端获取使用输入流读取这些内容,调用相关的实现类的方法,再将结果写入socket,客户端就获得了远程调用方法结果。
  • client
/**
* Created by wanshenghua on 2018/3/30.
*/
public class ClientStub {

    private static Socket socket ;

    public static < T> T buildProxy(Class< T> clazz ,String ip ,Integer port) throws Throwable{
        socket = new Socket(ip ,port) ;
        T t = ( T) Proxy. newProxyInstance(clazz.getClassLoader() , new Class[]{clazz} , proxyPerson()) ;
        //System.out.println(t);
        return t ;
    }

    public static InvocationHandler proxyPerson(){
        return new InvocationHandler(){
            @Override
            public Object invoke(Object proxy , Method method , Object[] args) throws Throwable {
                OutputStream outputStream = socket.getOutputStream() ;

                ObjectOutputStream oos = new ObjectOutputStream(outputStream) ;
                oos.writeObject(method.getDeclaringClass().getSimpleName()) ;
                oos.writeObject(method.getName()) ;
                oos.writeObject(method.getParameterTypes()) ;
                oos.writeObject(args) ;
                oos.flush() ;

                InputStream inputStream = socket.getInputStream() ;
                ObjectInputStream ois = new ObjectInputStream(inputStream) ;

                return ois.readObject() ;

            }
        } ;
    }
}

  • server
/**
* Created by wanshenghua on 2018/3/30.
*/
public class ServerStub {

    private static int port = 8888 ;

    private static ServerSocket serverSocket ;

    private static Map<String ,Object> servicePool = new HashMap<String , Object>() ;

    static {
        servicePool.put( "PersonService" ,new PersonServiceImpl()) ;
    }

    public static void main(String[] args) throws Exception{
        serverSocket = new ServerSocket( port) ;

        while( true){
            publish() ;
        }
    }

    public static void publish() throws Exception{
        Socket accept = serverSocket.accept() ;
        InputStream inputStream = accept.getInputStream() ;
        ObjectInputStream ois = new ObjectInputStream(inputStream) ;
        String className = (String) ois.readObject() ;
        String methodName = (String) ois.readObject() ;
        Class[] argsClass = (Class[]) ois.readObject() ;
        Object[] args = (Object[]) ois.readObject() ;

        Object tarObject = servicePool.get(className) ;
        Method method = tarObject.getClass().getMethod(methodName , argsClass) ;
        Object result = method.invoke(tarObject , args) ;

        OutputStream outputStream = accept.getOutputStream() ;
        ObjectOutputStream oos = new ObjectOutputStream(outputStream) ;
        oos.writeObject(result) ;
        oos.flush() ;

    }

    static class PersonServiceImpl implements  PersonService{
        @Override
        public Person findById( int personId) {
            if(personId == 1){
                return new Person(personId , "wsh" , "man") ;
            } else{
                return new Person(personId , "sumang" , "woman") ;
            }

        }
    }
}



  • Thrift
thrift启动服务端
public   class   Service {
     public   static   void   main(String[] args)  throws   TTransportException {
         TServerTransport serverTransport =  new   TServerSocket( 7777 );
          
         // TProcessor实现类为由编译器生成的UserService.Processor,并将服务接口的实现类实例设置到对应的域上
         TProcessor processor =  new   UserService.Processor<UserService.Iface>( new   UserServiceImpl());
 
         TServer.Args tArgs =  new   TServer.Args(serverTransport);
         tArgs.processor(processor);
         TServer server =  new   TSimpleServer(tArgs);
 
         server.serve();
     }
}

简单分析:
1.tserverTransport是服务传输对象,主要包装了socket编程中的serverTransport对象,用于获取来自客户端的socket连接,它有以下几个实现类:

其中TServerSocket支持同步io,TNonblockingServerSocket支持异步io.
2. TProcessor为实现类的顶级接口,具体的实现,比如这里是UserServiceImpl需要我们自己去实现Iface接口中的方法。
3.args主要为thrift端的一些参数,它的继承关系如下:

其中AbstractServerArgs为Tserver的内部类,主要有以下几个属性:
当执行 TServer.Args tArgs =  new   TServer.Args(serverTransport);代码时,会调用该类的一个构造方法,将serverTransport再传递
给该类的serverTransport属性。现在我们看到这七个属性中六个属性都有值了,只有processorFactory,因此执行第四部代码
4.tArgs.processor(processor);会args对象中的processFactory赋值。
5.TServer server = new TSimpleServer(tArgs);将args中的参数全部赋给服务器对象。
6.server.serve();执行服务器对象的服务方法。
下面看看server.serce具体做了哪些事(这里以我们代码中的TSimpleServer为例):
try {
    //设置一下内部的serverSocket属性的超时时间,serverSocket属性可以直接传入,也可以通过ip和port让TServerSocket自己内部构建
    this.serverTransport_.listen() ;
} catch (TTransportException var8) {
    LOGGER.error( "Error occurred during listening." , var8) ;
    return;
}

this.setServing( true) ;

while(! this.stopped_) {
    TTransport client = null;
    TProcessor processor = null;
    TTransport inputTransport = null;
    TTransport outputTransport = null;
    TProtocol inputProtocol = null;
    TProtocol outputProtocol = null;

    try {
        //通过上面说到的serverSocket属性获取来自客户端的socket连接,将socket的输入输出流包装成缓存输入输出流,将这些都作为TSocket的属性再返回
        //TSocket是 TTtansprot一个子类,
        client = this.serverTransport_.accept() ;
        if (client != null) {
            processor = this.processorFactory_.getProcessor(client) ;
            //负责socket流的数据读取
            inputTransport = this.inputTransportFactory_.getTransport(client) ;
            //负责socket流的数据写出
            outputTransport = this.outputTransportFactory_.getTransport(client) ;
            //通过工厂得到协议层对象,上面我们看到该工厂对象默认为Factory对象,该对象返回一个使用二进制协议的对象,具体的传输则交给参数TTtansprot
            inputProtocol = this.inputProtocolFactory_.getProtocol(inputTransport) ;
            outputProtocol = this.outputProtocolFactory_.getProtocol(outputTransport) ;

            while( true) {
                //根据inputProtocol,outputProtocol我们可以得到客户端调用的类名,方法名,参数类型,参数等信息,在处理器中进行查找调用,在写出
                if (processor.process(inputProtocol , outputProtocol)) {
                    continue;
                }
            }
        }
    }

在这里我们构建服务对象时的的很多参数都是默认的,比如
TTransportFactory inputTransportFactory = new TTransportFactory() ;
TTransportFactory outputTransportFactory = new TTransportFactory() ;
TProtocolFactory inputProtocolFactory = new Factory() ;
TProtocolFactory outputProtocolFactory = new Factory() ;
其实这些属性都可以由我们根据需求自由选择搭配,具体区别,可以参考(https://www.cnblogs.com/maociyuan/p/5718341.html)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值