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

Java: Allow multiplexing multiple services over a single TCP connection

    Details

    • Patch Info:
      Patch Available

      Description

      The current TServer implementations expose a single service on a port. If an application has many services many ports have to be opened. This is cumbersome because:

      • you have to document which service is available on which port, and remembering the port numbers is difficult
      • to prevent the overhead of connection setup on each call, a client has to maintain to many connections: at least one to each port
      • it requires opening many ports on a firewall if one is between the client and the server.

      By multiplexing multiple services on a single port the problems above are resolved:

      • instead of a port number a symbolic name can be assigned to a service
      • a client can maintain a small pool of connections to a single port
      • only one port has to be opened on the firewall

      The attached Java implementation simply wraps a normal CALL message with a (new) SERVICE_SELECTION message. It is not necessary to modify or wrap the response. No changes are needed to the generated classes. Only a new type of server is introduced, and an invocation handler for a dynamic proxy around the Client classes of services is provided for the client side. The implementation does not handle communication errors (invalid data, timeouts, etc.) yet.

      1. CalculatorImpl.java
        2 kB
        Johan Stuyts
      2. MultiplexTestClientMain.java
        3 kB
        Johan Stuyts
      3. MultiplexTestServerMain.java
        1 kB
        Johan Stuyts
      4. SharedImpl.java
        0.5 kB
        Johan Stuyts
      5. ThriftMultiplexInvocationHandler.java
        2 kB
        Johan Stuyts
      6. TMultiplexServer.java
        3 kB
        Johan Stuyts
      7. TSimpleMultiplexServer.java
        5 kB
        Johan Stuyts
      8. TMultiplexServer.py
        14 kB
        ruslan.usifov
      9. Thrift Endpoints and Channels.vsd
        141 kB
        James E. King, III
      10. ThriftCSharpEndpointsChannels.zip
        264 kB
        James E. King, III
      11. ReleaseWaitingReplyThreadsOnDisconnect.patch
        2 kB
        James E. King, III

        Issue Links

          Activity

          Hide
          Roger Meier added a comment -

          outdated and fixed by other subtasks of THRIFT-1915

          Show
          Roger Meier added a comment - outdated and fixed by other subtasks of THRIFT-1915
          Hide
          Carl Yeksigian added a comment -

          Any reason this sub task should stay open? Seems like the parent task has all of the necessary components.

          Show
          Carl Yeksigian added a comment - Any reason this sub task should stay open? Seems like the parent task has all of the necessary components.
          Hide
          Nevo Hed added a comment -

          You can use rpc ... We try to be somewhat Async for scalability
          On Sunday, January 15, 2012, Pedro Algarvio (Commented) (JIRA) <
          https://issues.apache.org/jira/browse/THRIFT-66?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13186525#comment-13186525]
          Erlang - Library, Java - Library, Perl - Library, Python - Library, Ruby -
          Library
          MultiplexTestServerMain.java, ReleaseWaitingReplyThreadsOnDisconnect.patch,
          SharedImpl.java, TMultiplexServer.java, TMultiplexServer.py,
          TSimpleMultiplexServer.java, Thrift Endpoints and Channels.vsd,
          ThriftCSharpEndpointsChannels.zip, ThriftMultiplexInvocationHandler.java
          port. If an application has many services many ports have to be opened.
          This is cumbersome because:
          remembering the port numbers is difficult
          to maintain to many connections: at least one to each port
          client and the server.
          are resolved:
          with a (new) SERVICE_SELECTION message. It is not necessary to modify
          or wrap the response. No changes are needed to the generated classes. Only
          a new type of server is introduced, and an invocation handler for a dynamic
          proxy around the Client classes of services is provided for the client
          side. The implementation does not handle communication errors (invalid
          data, timeouts, etc.) yet.
          administrators:
          https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa

          Show
          Nevo Hed added a comment - You can use rpc ... We try to be somewhat Async for scalability On Sunday, January 15, 2012, Pedro Algarvio (Commented) (JIRA) < https://issues.apache.org/jira/browse/THRIFT-66?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13186525#comment-13186525 ] Erlang - Library, Java - Library, Perl - Library, Python - Library, Ruby - Library MultiplexTestServerMain.java, ReleaseWaitingReplyThreadsOnDisconnect.patch, SharedImpl.java, TMultiplexServer.java, TMultiplexServer.py, TSimpleMultiplexServer.java, Thrift Endpoints and Channels.vsd, ThriftCSharpEndpointsChannels.zip, ThriftMultiplexInvocationHandler.java port. If an application has many services many ports have to be opened. This is cumbersome because: remembering the port numbers is difficult to maintain to many connections: at least one to each port client and the server. are resolved: with a (new) SERVICE_SELECTION message. It is not necessary to modify or wrap the response. No changes are needed to the generated classes. Only a new type of server is introduced, and an invocation handler for a dynamic proxy around the Client classes of services is provided for the client side. The implementation does not handle communication errors (invalid data, timeouts, etc.) yet. administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
          Hide
          Pedro Algarvio added a comment -

          Thanks Nevo!

          Did I understand wrong or is this only possible with one way messages?

          Ie, it's not possible to do regular RPC calls between the two servers?

          Show
          Pedro Algarvio added a comment - Thanks Nevo! Did I understand wrong or is this only possible with one way messages? Ie, it's not possible to do regular RPC calls between the two servers?
          Hide
          Nevo Hed added a comment -

          Hi Pedro,

          We are doing this by creating a server on each side. Client established a
          ''connection'' with a normal RPC call rest of the communication is with
          oneway messages ...

          The Connect parameters include a address+port for the client to be reached
          at. Typically we do have a set of request+response oneway messages, but
          no order or timing is required, so a "Push" works, as long as the client
          ensures that the connection is alive from time to time (you can have your
          own heartbeat timer).

          One key major key to make this work is to do the following when
          establishing the connection from the client:
          1) create socket+transport
          2) call transport::open()
          3) call getsockname on the socket's FD
          4) use the local addr returned (sin_addr.s_addr) to construct parameters
          the connect-request message.

          The server then takes that parameter (addr, port), converts the addr to
          string. This ensures that we keep DNS out of it, and that we talk on the
          correct interface for the return traffic (as would happen if thrift would
          have supported this natively)

          Client Server
          ===========Connect()========>

          <-------------AnyOneWayMessage() —
          <-------------AnyOneWayMessage() —
          --------------AnyOneWayMessage() --->
          --------------AnyOneWayMessage() --->
          --------------AnyOneWayMessage() --->
          <-------------AnyOneWayMessage() —
          --------------AnyOneWayMessage() --->
          <-------------AnyOneWayMessage() —
          --------------AnyOneWayMessage() --->
          <-------------AnyOneWayMessage() —

          On Sun, Jan 15, 2012 at 7:44 AM, Pedro Algarvio (Commented) (JIRA) <

          Show
          Nevo Hed added a comment - Hi Pedro, We are doing this by creating a server on each side. Client established a ''connection'' with a normal RPC call rest of the communication is with oneway messages ... The Connect parameters include a address+port for the client to be reached at. Typically we do have a set of request+response oneway messages, but no order or timing is required, so a "Push" works, as long as the client ensures that the connection is alive from time to time (you can have your own heartbeat timer). One key major key to make this work is to do the following when establishing the connection from the client: 1) create socket+transport 2) call transport::open() 3) call getsockname on the socket's FD 4) use the local addr returned (sin_addr.s_addr) to construct parameters the connect-request message. The server then takes that parameter (addr, port), converts the addr to string. This ensures that we keep DNS out of it, and that we talk on the correct interface for the return traffic (as would happen if thrift would have supported this natively) Client Server ===========Connect()========> <-------------AnyOneWayMessage() — <-------------AnyOneWayMessage() — --------------AnyOneWayMessage() ---> --------------AnyOneWayMessage() ---> --------------AnyOneWayMessage() ---> <-------------AnyOneWayMessage() — --------------AnyOneWayMessage() ---> <-------------AnyOneWayMessage() — --------------AnyOneWayMessage() ---> <-------------AnyOneWayMessage() — On Sun, Jan 15, 2012 at 7:44 AM, Pedro Algarvio (Commented) (JIRA) <
          Hide
          Pedro Algarvio added a comment -

          Not even two way communication? I'd like to be able to push "events" to the clients, is that possible? Has anyone done it?

          Show
          Pedro Algarvio added a comment - Not even two way communication? I'd like to be able to push "events" to the clients, is that possible? Has anyone done it?
          Hide
          Bryan Duxbury added a comment -

          I don't think it was ever 100% accepted that we wanted to add this additional complexity to Thrift. Don't get me wrong, I can see how it would be useful, but it comes at a cost, and none of the interested parties succeeded in championing through a change this significant.

          Show
          Bryan Duxbury added a comment - I don't think it was ever 100% accepted that we wanted to add this additional complexity to Thrift. Don't get me wrong, I can see how it would be useful, but it comes at a cost, and none of the interested parties succeeded in championing through a change this significant.
          Hide
          Pedro Algarvio added a comment -

          This is about 4 years old. Any reason why this hasn't been adopted/implemented yet?

          Show
          Pedro Algarvio added a comment - This is about 4 years old. Any reason why this hasn't been adopted/implemented yet?
          Hide
          James E. King, III added a comment -

          Looks like the test .thrift files in the Channels subdirectory have a syntax error. The IDL does not have channel specifications - those are made in code. For anybody applying the patch, just remove the channel designation in the ThriftTest/Channels/echo.thrift and rand.thrift and everything will compile. It was taken out a while ago, but I forgot to update the .thrift files. I guess the Single File Code Generator for Visual Studio doesn't get invoked on a Rebuild All, which is odd.

          Show
          James E. King, III added a comment - Looks like the test .thrift files in the Channels subdirectory have a syntax error. The IDL does not have channel specifications - those are made in code. For anybody applying the patch, just remove the channel designation in the ThriftTest/Channels/echo.thrift and rand.thrift and everything will compile. It was taken out a while ago, but I forgot to update the .thrift files. I guess the Single File Code Generator for Visual Studio doesn't get invoked on a Rebuild All, which is odd.
          Hide
          James E. King, III added a comment -

          Bugfix: when a remote end crashes, the local endpoint might have had user request threads blocking on a reply coming in which never would, and those threads would be blocked forever. The patch ReleaseWaitingReplyThreadsOnDisconnect.patch fixes this bug in the larger patch I submitted.

          Show
          James E. King, III added a comment - Bugfix: when a remote end crashes, the local endpoint might have had user request threads blocking on a reply coming in which never would, and those threads would be blocked forever. The patch ReleaseWaitingReplyThreadsOnDisconnect.patch fixes this bug in the larger patch I submitted.
          Hide
          James E. King, III added a comment -

          This patch zip contains a diff to apply to the trunk as of Sunday August 8 2010.
          It contains enhancements for the C# thrift compiler and runtime library.
          Normally patches address single issues, however given the content of the change which
          encompasses the entire C# runtime, it has to be presented as a single patch.

          Bugfixes and Enhancements:

          (not in Jira): The library is now compiled for .NET 2.0 by default; moving to v3.5
          does not cause any significant gains and excludes a large class of
          potential implementers still at .NET 2.0.

          (not in Jira): The C# runtime was not properly assigning a sequence ID to requests.

          (not in Jira): The C# runtime forced exceptions to be created using multiple statements.
          They can now be created on a single code line (for simple types).

          (not in Jira): The legacy C# runtime Server code has been refactored and simplified.

          (not in Jira): Thrift protocol is unidirectional. This has changed with the introduction
          of Endpoints. Using the new Endpoints in C# you can host a service that
          allows each end to register request handlers on different channels (see
          THRIFT-66). There is also a new TListeningEndpoint to replace the
          [now] legacy C# Server implementation. Tests are included.

          THRIFT-66: Allow multiplexing multiple services over a single TCP connection
          This is now possible through Thrift Channels. Up to 256 Thrift Services
          can run over a single connection if both sides are channel-aware. Only the
          C# runtime has this feature in this patch. Compatibility with legacy
          clients is easily maintained by providing for a channel zero implementation
          of a thrift service. There is no discovery protocol for this
          mechanism. Channel IDs are also not expressly put into the Thrift IDL
          to bind a service to just one channel. This will allow for flexibility
          in API versioning and various debugging scenarios.
          Tests are also included.

          THRIFT-181: C# SSL Support
          Full SSL support with two-way certificate validation has been added.
          Tests are also included.

          THRIFT-509: C# Library Does Not Provide Strong Name
          The runtime and MSVC Single File Code Generators are now strongly named.

          THRIFT-740: Visual Studio 2008 .thrift file complete integration
          This patch includes the Microsoft Visual Studio 2008 Single File Code Generator
          patch previously submitted to the project. The test project depends on it.
          Tests (examples), and a tutorial are included.

          To apply this patch, apply the .patch file and then copy the files from lib and test
          into the appropriate locations; the patch generator for subverion does not handle binaries.

          Jim King
          James_E_K@dell.com

          Show
          James E. King, III added a comment - This patch zip contains a diff to apply to the trunk as of Sunday August 8 2010. It contains enhancements for the C# thrift compiler and runtime library. Normally patches address single issues, however given the content of the change which encompasses the entire C# runtime, it has to be presented as a single patch. Bugfixes and Enhancements: (not in Jira): The library is now compiled for .NET 2.0 by default; moving to v3.5 does not cause any significant gains and excludes a large class of potential implementers still at .NET 2.0. (not in Jira): The C# runtime was not properly assigning a sequence ID to requests. (not in Jira): The C# runtime forced exceptions to be created using multiple statements. They can now be created on a single code line (for simple types). (not in Jira): The legacy C# runtime Server code has been refactored and simplified. (not in Jira): Thrift protocol is unidirectional. This has changed with the introduction of Endpoints. Using the new Endpoints in C# you can host a service that allows each end to register request handlers on different channels (see THRIFT-66 ). There is also a new TListeningEndpoint to replace the [now] legacy C# Server implementation. Tests are included. THRIFT-66 : Allow multiplexing multiple services over a single TCP connection This is now possible through Thrift Channels. Up to 256 Thrift Services can run over a single connection if both sides are channel-aware. Only the C# runtime has this feature in this patch. Compatibility with legacy clients is easily maintained by providing for a channel zero implementation of a thrift service. There is no discovery protocol for this mechanism. Channel IDs are also not expressly put into the Thrift IDL to bind a service to just one channel. This will allow for flexibility in API versioning and various debugging scenarios. Tests are also included. THRIFT-181 : C# SSL Support Full SSL support with two-way certificate validation has been added. Tests are also included. THRIFT-509 : C# Library Does Not Provide Strong Name The runtime and MSVC Single File Code Generators are now strongly named. THRIFT-740 : Visual Studio 2008 .thrift file complete integration This patch includes the Microsoft Visual Studio 2008 Single File Code Generator patch previously submitted to the project. The test project depends on it. Tests (examples), and a tutorial are included. To apply this patch, apply the .patch file and then copy the files from lib and test into the appropriate locations; the patch generator for subverion does not handle binaries. Jim King James_E_K@dell.com
          Hide
          James E. King, III added a comment -

          Visio diagram showing how endpoints and channels work - a concept to replace the existing one-way communication mechanism. I have not marked this as meant for inclusion yet, as there may be some changes before it is finalized. You may need Visio 2010 to view it?

          Show
          James E. King, III added a comment - Visio diagram showing how endpoints and channels work - a concept to replace the existing one-way communication mechanism. I have not marked this as meant for inclusion yet, as there may be some changes before it is finalized. You may need Visio 2010 to view it?
          Hide
          James E. King, III added a comment -

          I also wanted to explitly avoid having service discovery as part of the protocol, although there is nothing preventing someone from adding their own extension that does this. Originally I had made it so that the channel was part of the service declaration, i.e.:

          service Rand channel 5

          { ... }

          However that was met with some opposition. So now the channel identifier is declared in code when starting up an endpoint. As long as both sides have some innate knowledge of what runs on a given channel, it should be okay. This just leaves the channel namespace up to the host application. I will attach my Visio diageam of endpoints and channels.

          Show
          James E. King, III added a comment - I also wanted to explitly avoid having service discovery as part of the protocol, although there is nothing preventing someone from adding their own extension that does this. Originally I had made it so that the channel was part of the service declaration, i.e.: service Rand channel 5 { ... } However that was met with some opposition. So now the channel identifier is declared in code when starting up an endpoint. As long as both sides have some innate knowledge of what runs on a given channel, it should be okay. This just leaves the channel namespace up to the host application. I will attach my Visio diageam of endpoints and channels.
          Hide
          Bryan Duxbury added a comment -

          I would be strongly against adding discovery features like this to the Thrift protocol.

          Show
          Bryan Duxbury added a comment - I would be strongly against adding discovery features like this to the Thrift protocol.
          Hide
          Jan Dolecek added a comment -

          And how do you assign channel numbers for services? Do you have to set them manually and then remember them?
          What about making channel eg. 255 reserved for internal service. Here could be method "int lookupChannel(1: string channelName)". Then, you can give your channel names or aliases and use them in clients. Each server also could have it's channels assigned in different order.

          Show
          Jan Dolecek added a comment - And how do you assign channel numbers for services? Do you have to set them manually and then remember them? What about making channel eg. 255 reserved for internal service. Here could be method "int lookupChannel(1: string channelName)". Then, you can give your channel names or aliases and use them in clients. Each server also could have it's channels assigned in different order.
          Hide
          James E. King, III added a comment -

          I took a completely different approach to solving this... there is an unused byte in the VERSION_1 Thrift message header which I designated for a "Channel". I rewrote the C# runtime and added two-way communication, SSL Support, and multiple services on a single connection which is binary compatible with older clients (they can only communication on channel zero, in one direction, just like a legacy client would..)

          When an endpoint initializes it can install protocol handlers on whatever channel it wants. Each side of the connection is able to implement a protocol handler, and each side is able to make a client to query the other side. Each side is also able to process multiple requests in parallel on a single connection. It is still going through testing, and I would like to refactor the shutdown logic so that it does not rely on socket exceptions before I post it though, unless folks would like to get the ball rolling on two-way communication across all Thrift languages and use this as a template to work from..

          Show
          James E. King, III added a comment - I took a completely different approach to solving this... there is an unused byte in the VERSION_1 Thrift message header which I designated for a "Channel". I rewrote the C# runtime and added two-way communication, SSL Support, and multiple services on a single connection which is binary compatible with older clients (they can only communication on channel zero, in one direction, just like a legacy client would..) When an endpoint initializes it can install protocol handlers on whatever channel it wants. Each side of the connection is able to implement a protocol handler, and each side is able to make a client to query the other side. Each side is also able to process multiple requests in parallel on a single connection. It is still going through testing, and I would like to refactor the shutdown logic so that it does not rely on socket exceptions before I post it though, unless folks would like to get the ball rolling on two-way communication across all Thrift languages and use this as a template to work from..
          Hide
          James E. King, III added a comment -

          I have implemented a similar multiplexed runtime in C# and tested it with 200 concurrent clients who are pushing and receiving. It uses no sleep loops and does proper blocking when waiting to send or receive data. I think it would be a good idea to define a standard specification for multiplexed communications so all the language runtimes can synchronize.

          Definition: Once the client connects to the server, multiple virtual communication channels are opened in both directions for reliable RPC that can be initiated by either end. As there are multiple communication channels each side chooses to be the client or server. Each virtual transport handles a single thrift service declaration. An added benefit, other than two-way communications, is that you can split your RPCs into functional areas and service them on different virtual channels. This may help to clean up larger .thrift files.

          Implementation: The wire format is simple, and as follows:

          01: byte, range 01-FF, indicates the virtual transport ID
          02-05: int32, network byte order, indicates the payload length
          06-end: payload

          This requires no changes to the compiler / compiled code. Note that fully integrating this into the mainline will likely tuck it under the version exchange. Here is the preferred runtime implementation:

          • As there is a single communication channel, a single thread should be used to read from the socket, and a single thread should be used to write.
          • For the read thread, it should block on read of the actual transport. When it gets some data it should route it to an appropriate virtual transport kept in a map. The virtual transport should store incoming binary data in order and distribute it out the overridden Read function. When there is no more data to read this should block. This means that when data is enqueued to the virtual transport it ideally needs some form of event to wait on.
          • For the write side, when a virtual transport receives a Write call, it should store the outgoing binary data in-order and use an event to signal the write thread to do some work. Ideally the write thread can wait on multiple events including a shutdown event, and get notification of which virtual transport needs a write, and then push the data out. This makes the write thread block when there is nothing to do, and wake up when it is time to stop.
          • sleeping loops should be avoided where possible

          Acknowledgement: charlie (d o t) mas (a t) gmail (d o t) com released an initial implementation which I overhauled

          Comment: Still waiting for Dell approval to release open-source code back to the community. Once that happens I will push up a patch for review.

          Show
          James E. King, III added a comment - I have implemented a similar multiplexed runtime in C# and tested it with 200 concurrent clients who are pushing and receiving. It uses no sleep loops and does proper blocking when waiting to send or receive data. I think it would be a good idea to define a standard specification for multiplexed communications so all the language runtimes can synchronize. Definition: Once the client connects to the server, multiple virtual communication channels are opened in both directions for reliable RPC that can be initiated by either end. As there are multiple communication channels each side chooses to be the client or server. Each virtual transport handles a single thrift service declaration. An added benefit, other than two-way communications, is that you can split your RPCs into functional areas and service them on different virtual channels. This may help to clean up larger .thrift files. Implementation: The wire format is simple, and as follows: 01: byte, range 01-FF, indicates the virtual transport ID 02-05: int32, network byte order, indicates the payload length 06-end: payload This requires no changes to the compiler / compiled code. Note that fully integrating this into the mainline will likely tuck it under the version exchange. Here is the preferred runtime implementation: As there is a single communication channel, a single thread should be used to read from the socket, and a single thread should be used to write. For the read thread, it should block on read of the actual transport. When it gets some data it should route it to an appropriate virtual transport kept in a map. The virtual transport should store incoming binary data in order and distribute it out the overridden Read function. When there is no more data to read this should block. This means that when data is enqueued to the virtual transport it ideally needs some form of event to wait on. For the write side, when a virtual transport receives a Write call, it should store the outgoing binary data in-order and use an event to signal the write thread to do some work. Ideally the write thread can wait on multiple events including a shutdown event, and get notification of which virtual transport needs a write, and then push the data out. This makes the write thread block when there is nothing to do, and wake up when it is time to stop. sleeping loops should be avoided where possible Acknowledgement: charlie (d o t) mas (a t) gmail (d o t) com released an initial implementation which I overhauled Comment: Still waiting for Dell approval to release open-source code back to the community. Once that happens I will push up a patch for review.
          Hide
          ruslan.usifov added a comment -

          This is my port of multiplexing for python

          Show
          ruslan.usifov added a comment - This is my port of multiplexing for python
          Hide
          ruslan.usifov added a comment -

          I think this is interesting too!!!!

          Show
          ruslan.usifov added a comment - I think this is interesting too!!!!
          Hide
          Jérémie BORDIER added a comment -

          I do think this would be a very interesting feature, but i think that it should be specced and implemented in every languages to have a consistent framework.

          Show
          Jérémie BORDIER added a comment - I do think this would be a very interesting feature, but i think that it should be specced and implemented in every languages to have a consistent framework.
          Hide
          Bryan Duxbury added a comment -

          Is there still interest in this issue? If so, the files attached should be converted to a patch, and we should discuss how it works and would integrate with other languages.

          Show
          Bryan Duxbury added a comment - Is there still interest in this issue? If so, the files attached should be converted to a patch, and we should discuss how it works and would integrate with other languages.
          Hide
          Bryan Duxbury added a comment -

          Changing to Trivial, since it's a new feature.

          Show
          Bryan Duxbury added a comment - Changing to Trivial, since it's a new feature.
          Hide
          T Jake Luciani added a comment -

          Not sure why this is filed as a perl fix?

          Show
          T Jake Luciani added a comment - Not sure why this is filed as a perl fix?
          Hide
          Johan Stuyts added a comment -

          I attached the following classes:

          • TMultiplexServer: a base class for services that expose multiple services on a single port
          • TSimpleMultiplexServer: an implementation of TMultiplexServer that uses a thread per connection
          • ThriftMultiplexInvocationHandler: the invocation handler around dynamic proxies for Client instances of services. The handler wraps the CALL message with a service selection message
          • MultiplexTestServerMain: a test class that starts a multiplexing server on port 9090 with a number of services
          • MultiplexTestClientMain: a test class that opens a single connection to the server and invokes multiple functions of multiple services
          • CalculatorImpl: implementation of the Calculator service for the test
          • SharedImpl: implementation of the SharedService service for the test

          To test the implementation you need to add the following line to TMessageType:

            public static final byte SERVICE_SELECTION  = 4;
          
          Show
          Johan Stuyts added a comment - I attached the following classes: TMultiplexServer : a base class for services that expose multiple services on a single port TSimpleMultiplexServer : an implementation of TMultiplexServer that uses a thread per connection ThriftMultiplexInvocationHandler : the invocation handler around dynamic proxies for Client instances of services. The handler wraps the CALL message with a service selection message MultiplexTestServerMain : a test class that starts a multiplexing server on port 9090 with a number of services MultiplexTestClientMain : a test class that opens a single connection to the server and invokes multiple functions of multiple services CalculatorImpl : implementation of the Calculator service for the test SharedImpl : implementation of the SharedService service for the test To test the implementation you need to add the following line to TMessageType : public static final byte SERVICE_SELECTION = 4;

            People

            • Assignee:
              Roger Meier
              Reporter:
              Johan Stuyts
            • Votes:
              13 Vote for this issue
              Watchers:
              14 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development