Thrift
  1. Thrift
  2. THRIFT-1915 Multiplexing Services
  3. THRIFT-563

Support for Multiplexing Services on any Transport, Protocol and Server

    Details

    • Type: Sub-task Sub-task
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 0.9.1
    • Component/s: Java - Library
    • Labels:
      None
    • Patch Info:
      Patch Available

      Description

      Motivation and Benefits

      We plan to use Thrift with a large number of functions communicating among (at least) three languages. To keep maintainability high, we hope to avoid a single service defined with a large number of functions. This would require monolithic, unwieldy service implementations as the number of functions grows.

      Breaking up our API into multiple IDLs gives us multiple abstract base classes, which provides more flexibility in the object-oriented design of our server platform.

      Before our changes, the alternative was to open up additional ports with smaller service implementations on each. We'd rather not open additional ports.

      Our Approach

      We pursued an approach with the following in mind:

      • No modifications to existing Thrift code.
      • No modification to the Thrift protocol as described in the whitepaper.
      • No modification to any TServer, TProtocol or TTransport.
      • No need for any new TServer implementation. Works with any TServer implementation.
      • Work with any combination of TServer, TProtocol or TTransport.
      • Avoid language-specific features, to ease implementation in other languages.

      Additions to Thrift

      Convenience class:

      • TProtocolDecorator (extends TProtocol). This is a no-op decorator around the TProtocol abstract class.

      For use by clients:

      • TMultiplexedProtocol (extends TProtocolDecorator). This decorates any TProtocol by modifying the behaviour of writeMessageBegin(TMessage) to change TMessage.name from function_name to service_name + separator + function_name.

      For use by the server:

      • TMultiplexedProcessor (implements TProcessor). It should be used to communicate with a client that was written using TMultiplexedProtocol. It removes service_name + separator from TMessage.name, turning it back into the standard message format. It then brokers the service request to the TProcessor which is registered to handle requests for that service.

      Sample Usage - Client

      In this example, we've chosen to use TBinaryProtocol with two services: Calculator and WeatherReport.

      TSocket transport = new TSocket("localhost", 9090);
      transport.open();
      
      TBinaryProtocol protocol = new TBinaryProtocol(transport);
      
      TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
      Calculator.Client service = new Calculator.Client(mp);
      
      TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
      WeatherReport.Client service2 = new WeatherReport.Client(mp2);
      
      System.out.println(service.add(2,2));
      System.out.println(service2.getTemperature());
      

      Sample Usage - Server

      TMultiplexedProcessor processor = new TMultiplexedProcessor();
      
      processor.registerProcessor(
          "Calculator",
          new Calculator.Processor(new CalculatorHandler()));
      
      processor.registerProcessor(
          "WeatherReport",
          new WeatherReport.Processor(new WeatherReportHandler()));
      
      TServerTransport t = new TServerSocket(9090);
      TSimpleServer server = new TSimpleServer(processor, t);
      
      server.serve();
      
      1. THRIFT-563_fixed-signatures.patch
        18 kB
        Rob Slifka
      2. multiplex_c++.tar
        30 kB
        Patrik Lindblom
      3. multiplex.py
        2 kB
        Walter Huf
      4. THRIFT-563.patch
        15 kB
        Rob Slifka

        Issue Links

          Activity

          Hide
          Doug MacEachern added a comment -

          Created a new ticket (THRIFT-1914) for the Python version based on Walter Huf's multiplex.py

          Show
          Doug MacEachern added a comment - Created a new ticket ( THRIFT-1914 ) for the Python version based on Walter Huf's multiplex.py
          Hide
          Patrik Lindblom added a comment -

          Jens,

          I have create a new ticket (THRIFT-1902) for the C++ version of the Multiplexed protocol.
          I have also submitted a patch (including ASF copyright headers) to that ticket for further processing.

          Show
          Patrik Lindblom added a comment - Jens, I have create a new ticket ( THRIFT-1902 ) for the C++ version of the Multiplexed protocol. I have also submitted a patch (including ASF copyright headers) to that ticket for further processing.
          Hide
          Hudson added a comment -

          Integrated in Thrift #633 (See https://builds.apache.org/job/Thrift/633/)
          THRIFT-563 Support for Multiplexing Services on any Transport, Protocol and Server (Revision 3661867febfa3a303ae8f5df2ed1a29e882821c3)
          THRIFT-563 Support for Multiplexing Services on any Transport, Protocol and Server (Revision cac2c5761e2ebe8b14a3c03dd2ee756c1e14441b)

          Result = ABORTED
          jensg : https://git-wip-us.apache.org/repos/asf?p=thrift.git&a=commit&h=3661867febfa3a303ae8f5df2ed1a29e882821c3
          Files :

          • lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java
          • lib/java/src/org/apache/thrift/protocol/TMultiplexedProtocol.java
          • lib/java/src/org/apache/thrift/TMultiplexedProcessor.java

          jensg : https://git-wip-us.apache.org/repos/asf?p=thrift.git&a=commit&h=cac2c5761e2ebe8b14a3c03dd2ee756c1e14441b
          Files :

          • lib/java/src/org/apache/thrift/protocol/TMultiplexedProtocol.java
          • lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java
          • lib/java/src/org/apache/thrift/TMultiplexedProcessor.java
          Show
          Hudson added a comment - Integrated in Thrift #633 (See https://builds.apache.org/job/Thrift/633/ ) THRIFT-563 Support for Multiplexing Services on any Transport, Protocol and Server (Revision 3661867febfa3a303ae8f5df2ed1a29e882821c3) THRIFT-563 Support for Multiplexing Services on any Transport, Protocol and Server (Revision cac2c5761e2ebe8b14a3c03dd2ee756c1e14441b) Result = ABORTED jensg : https://git-wip-us.apache.org/repos/asf?p=thrift.git&a=commit&h=3661867febfa3a303ae8f5df2ed1a29e882821c3 Files : lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java lib/java/src/org/apache/thrift/protocol/TMultiplexedProtocol.java lib/java/src/org/apache/thrift/TMultiplexedProcessor.java jensg : https://git-wip-us.apache.org/repos/asf?p=thrift.git&a=commit&h=cac2c5761e2ebe8b14a3c03dd2ee756c1e14441b Files : lib/java/src/org/apache/thrift/protocol/TMultiplexedProtocol.java lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java lib/java/src/org/apache/thrift/TMultiplexedProcessor.java
          Hide
          Jens Geyer added a comment - - edited

          Both changes look good to me, committed.
          Thanks Rob!

          Regarding the C++ and Python files: I have not forgotten them, but I'd suggest to open separate tickets (plus providing them as a patch file) for them, so the C++/Python people can take care of them indenpendently.

          Show
          Jens Geyer added a comment - - edited Both changes look good to me, committed. Thanks Rob! Regarding the C++ and Python files: I have not forgotten them, but I'd suggest to open separate tickets (plus providing them as a patch file) for them, so the C++/Python people can take care of them indenpendently.
          Hide
          Rob Slifka added a comment -

          Fixed errors pointed out by @Roger.

          Show
          Rob Slifka added a comment - Fixed errors pointed out by @Roger.
          Hide
          Rob Slifka added a comment -

          Just pulled down master. Looks like the signatures for TProtocol::readBinary() and TProtocol::writeBinary() had since been modified. Attaching a new patch for TProtocolDecorator.

          Show
          Rob Slifka added a comment - Just pulled down master. Looks like the signatures for TProtocol::readBinary() and TProtocol::writeBinary() had since been modified. Attaching a new patch for TProtocolDecorator .
          Hide
          Rob Slifka added a comment - - edited

          @Roger - I wouldn't be surprised. This patch was created against a version of HEAD from 8/2009 Booting it up now and having a look.

          Show
          Rob Slifka added a comment - - edited @Roger - I wouldn't be surprised. This patch was created against a version of HEAD from 8/2009 Booting it up now and having a look.
          Hide
          Rob Slifka added a comment -

          Added ASF copyright as specified here http://www.apache.org/legal/src-headers.html.

          Show
          Rob Slifka added a comment - Added ASF copyright as specified here http://www.apache.org/legal/src-headers.html .
          Hide
          Roger Meier added a comment -

          I have these issues:

              [javac] lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java:189: error: readBinary() in TProtocolDecorator cannot override readBinary() in TProtocol
              [javac] lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java:110: error: method writeBinary in class TProtocol cannot be applied to given types;
              [javac] lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java:190: error: incompatible types
              [javac] lib/java/src/org/apache/thrift/TMultiplexedProcessor.java:112: error: TMultiplexedProcessor.StoredMessageProtocol is not abstract and does not override abstract method readBinary() in TProtocol
              [javac] lib/java/src/org/apache/thrift/protocol/TMultiplexedProtocol.java:33: error: TMultiplexedProtocol is not abstract and does not override abstract method readBinary() in TProtocol
              [javac] 5 errors
          
          Show
          Roger Meier added a comment - I have these issues: [javac] lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java:189: error: readBinary() in TProtocolDecorator cannot override readBinary() in TProtocol [javac] lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java:110: error: method writeBinary in class TProtocol cannot be applied to given types; [javac] lib/java/src/org/apache/thrift/protocol/TProtocolDecorator.java:190: error: incompatible types [javac] lib/java/src/org/apache/thrift/TMultiplexedProcessor.java:112: error: TMultiplexedProcessor.StoredMessageProtocol is not abstract and does not override abstract method readBinary() in TProtocol [javac] lib/java/src/org/apache/thrift/protocol/TMultiplexedProtocol.java:33: error: TMultiplexedProtocol is not abstract and does not override abstract method readBinary() in TProtocol [javac] 5 errors
          Hide
          Jens Geyer added a comment -

          Rob,

          I just noticed that the ASF headers were missing in these added files. Could you please add them?

          Show
          Jens Geyer added a comment - Rob, I just noticed that the ASF headers were missing in these added files. Could you please add them?
          Hide
          Jens Geyer added a comment -

          Committed.

          Nice idea and great work!
          I think, I will provide some patches too.

          Show
          Jens Geyer added a comment - Committed. Nice idea and great work! I think, I will provide some patches too.
          Hide
          Randy Abernethy added a comment -

          Hi Jens, I agree with the patch. I think the model is good and I will use/test it if committed.

          Show
          Randy Abernethy added a comment - Hi Jens, I agree with the patch. I think the model is good and I will use/test it if committed.
          Hide
          Jens Geyer added a comment -

          Randy,

          does that read "I agree with the patch"?

          Patrick,

          could you please make a patch out of it?

          Show
          Jens Geyer added a comment - Randy, does that read "I agree with the patch"? Patrick, could you please make a patch out of it?
          Hide
          Randy Abernethy added a comment -

          We rolled our own server multiplexer but would switch to this solution in a heartbeat if committed.

          Show
          Randy Abernethy added a comment - We rolled our own server multiplexer but would switch to this solution in a heartbeat if committed.
          Hide
          Patrik Lindblom added a comment -

          Added C++ implementation of the classes.

          Show
          Patrik Lindblom added a comment - Added C++ implementation of the classes.
          Hide
          Walter Huf added a comment -

          I have ported the given patch into Python, and tested it with a simple server and client.
          On the server side, you make your normal processors, and then construct a TMultiplexedProcessor and run .registerProcessor to add your normal processors.
          On the client side, you create your normal protocol, and then create several TMultiplexedProtocols, passing in your main protocol and a service name. Then you create the service's client, passing the corresponding TMultiplexedProtocol.

          Show
          Walter Huf added a comment - I have ported the given patch into Python, and tested it with a simple server and client. On the server side, you make your normal processors, and then construct a TMultiplexedProcessor and run .registerProcessor to add your normal processors. On the client side, you create your normal protocol, and then create several TMultiplexedProtocols, passing in your main protocol and a service name. Then you create the service's client, passing the corresponding TMultiplexedProtocol.
          Hide
          John Chen added a comment -

          Hey Rob, Can we get the implementation for C++ and python language as well, can you please provide the patch for the same problem?

          Show
          John Chen added a comment - Hey Rob, Can we get the implementation for C++ and python language as well, can you please provide the patch for the same problem?
          Hide
          alok gupta added a comment -

          Hey Rob, Can we get the implementation for C++ language as well, can you please provide the patch for the same.

          Show
          alok gupta added a comment - Hey Rob, Can we get the implementation for C++ language as well, can you please provide the patch for the same.
          Hide
          Sergey Vasilyev added a comment -

          Are there any news on Python implementation of this multiplexed protocol+process? Is this solution still useful with new versions of Thrift, or should it be updated? Thanks.

          Show
          Sergey Vasilyev added a comment - Are there any news on Python implementation of this multiplexed protocol+process? Is this solution still useful with new versions of Thrift, or should it be updated? Thanks.
          Hide
          Rob Slifka added a comment -

          Yep, you nailed exactly why we chose the TProcessor-as-broker approach. We didn't want to limit multiplexing support to any specific TTransport (e.g. THttpClient).

          Regarding your specific concern: THttpClient already allows setting custom headers via THttpClient::setCustomHeaders(...) and as our approach is TTransport-agnostic, setting those headers would work just fine.

          Show
          Rob Slifka added a comment - Yep, you nailed exactly why we chose the TProcessor -as-broker approach. We didn't want to limit multiplexing support to any specific TTransport (e.g. THttpClient ). Regarding your specific concern: THttpClient already allows setting custom headers via THttpClient::setCustomHeaders(...) and as our approach is TTransport -agnostic, setting those headers would work just fine.
          Hide
          Jarski added a comment -

          This looks great - something my company will certainly try out if it is checked in.

          Our team has in the past discussed approaches to dealing with exactly the issue you're trying to address, although we have been looking at it as something to build over the thrift http protocol – specifically, each service would be served on its own http handler, e.g. server:port/Calculator, server:port/WeatherReport, etc. Your approach would be a good alternative, more widely applicable, and probably simpler (although one reason that our team still likes the http idea is that it supports out-of-band data, e.g. request ids or credentials passed with every method without having to add them explicitly to every method as args,).

          Show
          Jarski added a comment - This looks great - something my company will certainly try out if it is checked in. Our team has in the past discussed approaches to dealing with exactly the issue you're trying to address, although we have been looking at it as something to build over the thrift http protocol – specifically, each service would be served on its own http handler, e.g. server:port/Calculator, server:port/WeatherReport, etc. Your approach would be a good alternative, more widely applicable, and probably simpler (although one reason that our team still likes the http idea is that it supports out-of-band data, e.g. request ids or credentials passed with every method without having to add them explicitly to every method as args,).
          Hide
          Rob Slifka added a comment - - edited

          At least a C++ server and a Python client. If there's enough interest, we'll contribute that as well. If you're interested, be sure to click the Vote and Watch links on the top left of this page!

          Show
          Rob Slifka added a comment - - edited At least a C++ server and a Python client. If there's enough interest, we'll contribute that as well. If you're interested, be sure to click the Vote and Watch links on the top left of this page!
          Hide
          Ryan added a comment -

          Are you planning on implementing other languages? I think this looks fantastic. I would love to use it.

          Show
          Ryan added a comment - Are you planning on implementing other languages? I think this looks fantastic. I would love to use it.
          Hide
          Rob Slifka added a comment -

          Patch file, for the three classes mentioned above taken from /trunk.

          Show
          Rob Slifka added a comment - Patch file, for the three classes mentioned above taken from /trunk.

            People

            • Assignee:
              Unassigned
              Reporter:
              Rob Slifka
            • Votes:
              24 Vote for this issue
              Watchers:
              30 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development