суббота, 19 июня 2010 г.

Apache Thrift или ...

...как подружить свой серверный код на Java с клиентским кодом на C++/PHP/Perl/Python или наоборот? :)
Thrift позволяет достаточно просто организовать RPC-сервис для этого.

Для этого нужно:
  1. Скачать и собрать thrift (http://incubator.apache.org/thrift/download/)
  2. Написать .thrift файл с описанием интерфейса


    namespace java name.stasikos.thrift.generated
    namespace cpp thrift.demo
    namespace perl thriftdemo
    namespace py thriftdemo
    
    typedef binary Text
    
    struct TimeStamp {
      1: i32 sequence
      2: Text date
    }
    
    service thriftDemo {
      void reset()
      void setIncrement(1:i32 increment)
      TimeStamp get();
    }
    

  3. Сгенерировать собранным thrift файлы для нужных языков программирования.

    $ thrift --gen cpp Demo.thrift

    $ thrift --gen java Demo.thrift
  4. Поправить скелет сгенерированного Thrift-сервера чтобы реализовать потребности :)



    package name.stasikos.thrift;
    
    import java.util.Date;
    import name.stasikos.thrift.generated.TimeStamp;
    import name.stasikos.thrift.generated.thriftDemo;
    import org.apache.thrift.TException;
    import org.apache.thrift.protocol.TBinaryProtocol;
    import org.apache.thrift.protocol.TProtocolFactory;
    import org.apache.thrift.server.TServer;
    import org.apache.thrift.server.TThreadPoolServer;
    import org.apache.thrift.transport.TServerSocket;
    import org.apache.thrift.transport.TServerTransport;
    
    /**
    *
    * @author stasikos
    */
    public class ThriftServer {
    
      public static class Thrift implements thriftDemo.Iface {
    
        static int sequenceNumber;
        static int seqIncrement = 1;
    
        public void reset() throws TException {
          sequenceNumber = 0;
        }
    
        public void setIncrement(int increment) throws TException {
          seqIncrement = increment;
        }
    
        public TimeStamp get() throws TException {
          TimeStamp ts = new TimeStamp(sequenceNumber, (new Date()).toString().getBytes());
          sequenceNumber++;
          return ts;
        }
    
      }
    
      protected static void doMain(final String[] args) throws Exception {
        Thrift thrift = new Thrift();
        thriftDemo.Processor processor = new thriftDemo.Processor(thrift);
        TServerTransport serverTransport = new TServerSocket(18999);
        TProtocolFactory protFactory = new TBinaryProtocol.Factory(true, true);
        TServer server = new TThreadPoolServer(processor, serverTransport,
        protFactory);
        server.serve();
      }
    
      public static void main(String[] args) throws Exception {
        doMain(args);
      }
    }
    



  5. Написать клиента :)

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/time.h>
    #include <poll.h>
    #include <iostream>
    
    #include <protocol/TBinaryProtocol.h>
    #include <transport/TSocket.h>
    #include <transport/TTransportUtils.h>
    
    #include "gen-cpp/Demo_constants.h"
    #include "gen-cpp/Demo_types.h"
    #include "gen-cpp/thriftDemo.h"
    
    using namespace apache::thrift;
    using namespace apache::thrift::transport;
    using namespace apache::thrift::protocol;
    using namespace thrift::demo;
    
    int main(int argc, char** argv) {
      boost::shared_ptr<TTransport> socket(new TSocket("localhost", 18999));
      boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
      boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
      thriftDemoClient client(protocol);
    
    
      try {
        transport->open();
        client.reset();
        TimeStamp t;
        client.get(t);
        std::cout << "seq:" << t.sequence << " date:" << t.date <<   std::endl;
        client.get(t);
        std::cout << "seq:" << t.sequence << " date:" << t.date <<   std::endl;
        client.setIncrement(3);
        client.get(t);
        std::cout << "seq:" << t.sequence << " date:" << t.date << std::endl;
      } catch (TException &te) {
        std::cout << "exception: " << te.what();
      }
    
    }
    


  6. Скомпилировать...

    $ g++ -o demo -I/usr/local/include/thrift -lthrift demo.cpp gen-cpp/thriftDemo.cpp gen-cpp/Demo_types.cpp

  7. Запустить...

    $ ./demo

    seq:0 date:Sat Jun 19 00:42:22 EEST 2010

    seq:1 date:Sat Jun 19 00:42:22 EEST 2010

    seq:2 date:Sat Jun 19 00:42:22 EEST 2010


Это был простой пример, как экспортировать API на Java куда-то в C++

Комментариев нет:

Отправить комментарий