Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I'd like to use multiple services on one transport ( Thrift )

I'd like to create several services, and I want to use them with different identifiers. So I mean :

I've got a Users and Projects service . I want to use these at the same time.

I mean I can add more 'services' to the "handlermap" on xmlrpc.

http://ws.apache.org/xmlrpc/server.html

phm.addHandler("Users",
             Users.class); 
phm.addHandler("Projects",
               Projects.class);

I would like to do the same in the thrift.

Here is a simple example : test.thrift

typedef i64 UserId

struct Bonk
{
  1: string message,
  2: i32 type
}

struct Insanity
{
  1: map<Bonk, UserId> userMap,
  2: list<Bonk> xtructs
}



service ThriftTest
{
  void         testVoid(),
  string       testString(1: string test),
  byte         testByte(1: byte test),
  i32          testI32(1: i32 test),
  i64          testI64(1: i64 test),
  double       testDouble(1: double test),
  list<map<i32,i32>> testMap(1: map<i32,i32> test),
  map<string,string> testStringMap(1: map<string,string> test),
  set<i32>     testSet(1: set<i32> test),
  map<i32,map<i32,i32>> testMapMap(1: i32 test),
  map<UserId, map<i32,Insanity>> testInsanity(1: Insanity argument)
}

Then I create an implementatino, then add it to the instance of TServer .

Users.Processor users_proccesor = new Users.Processor(New UsersImpl());
Projects.Processor project_processor = new Projects.Processors(new ProjectsImp());
// I would like to add Users and Projects  
ThriftTest.Processor prc = new ThriftTest.Processor(new ThiftTestImp());
            TServerTransport serverTransport = new TServerSocket(9090);
            TServer server = new TSimpleServer(new Args(serverTransport).processor( prc ));

And here's my big problem, I can't add multiple instances of the server.

Thank you for your help in advance.

like image 329
kmmrtkq Avatar asked Aug 01 '11 23:08

kmmrtkq


People also ask

What are thrift services?

Thrift was originally developed by Facebook and now it is open sourced as an Apache project. Apache Thrift is a set of code-generation tools that allows developers to build RPC clients and servers by just defining the data types and service interfaces in a simple definition file.

Why should I use thrift?

It can take months and even years for these materials to fully break down in landfills! By choosing to buy secondhand clothing instead of brand new, you reduce waste and help the planet. In this way, thrift shopping is the ultimate way to live out the “reduce, reuse, recycle” motto!

What is a thrift object?

Thrift structs define a common object – they are essentially equivalent to classes in OOP languages, but without inheritance. A struct has a set of strongly typed fields, each with a unique name identifier. Fields may have various annotations (numeric field IDs, optional default values, etc.)


2 Answers

Multiplexed Services (in essence that's what you want to do here) are being integrated right now. There are already patches for a number of languages available, either already accepted or in the process of being reviewed.

https://issues.apache.org/jira/browse/THRIFT-563 is a good place to start.

PS: Reviewers and contributions are welcome ;-)

like image 60
JensG Avatar answered Nov 05 '22 15:11

JensG


RPC invocation is transmitted over the wire in TMessage structure that doesn't have 'targetService' field. So there's no straightforward way to bind several services to a single port without adding this field to TMessage and recompiling thrift.

It's possible to do a hack by implementing custom TServer similar to TSimpleSever (or any other TServer).

Server should read target service in the loop and get corresponding processor:

      ...
      inputProtocol = inputProtocolFactory_.getProtocol(inputTransport);
      outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
      do {
        String target = inputProtocol.readString();
        processor = processorFactoryMap.get(target).getProcessor(client);
      while (processor.process(inputProtocol, outputProtocol));
      ...

Client should prefix each message with target service string. This can be done by wrapping TBinaryProtocol in a custom protocol:

public void writeMessageBegin(TMessage message) throws TException {
    wrapped.writeString(target);
    wrapped.writeMessageBegin(message);
}

The main disadvantage of this approach is losing interoperability with other clients. So, probably it's better either to start two different TServers on different ports, or define all methods in a single thrift service, and then delegate invocations to appropriate handlers.

like image 34
Wildfire Avatar answered Nov 05 '22 13:11

Wildfire