That really is awesomely cool. As Ted Dunning says, scary as anything, but really, really clever!

Best regards and a tip of the hat,
Rush

On Apr 2, 2009, at 4:17 PM, Joel Meyer wrote:

On Tue, Mar 24, 2009 at 5:01 PM, Doug Daniels <[email protected] >wrote:


<snip>

I think I've done something similar to what you're trying to do, and as long as you can commit to using only async messages it's possible to pull it off
without having to start a server on the client to accept RPCs from the
server.

When your RPC is marked as async the server doesn't send a response and the client doesn't try to read one. So, if all your RPC calls from the client to the server are async you have effectively freed up the inbound half of the
socket connection. That means that you can use it for receiving async
messages from the server - the only catch is that you have to start a new
thread to read and dispatch the incoming async RPC calls.

In a typical Thrift RPC system you'd create a MyService.Processor on your server and a MyService.Client on your client. To do bidirectional async
message sending you'll need to go a step further and create a
MyService.Client on your server for each client that connects (this can be
accomplished by providing your own TProcessorFactory) and then on each
client you create a MyService.Processor. (This assumes that you've gone with a generic MyService definition like you described above that has a bunch of
optional messages, another option would be to define separate service
definitions for the client and server.) With two clients connected the
objects in existence would look something like this:

Server:
 MyService.Processor mainProcessor - handles incoming async RPCs
MyService.Client clientA - used to send outgoing async RPCs to ClientA MyService.Client clientB - used to send outgoing async RPCs to ClientB

ClientA:
 MyService.Client - used to send messages to Server
 MyService.Processor clientProcessor - used (by a separate thread) to
process incoming async RPCs

ClientB:
 MyService.Client - used to send messages to Server
 MyService.Processor clientProcessor - used (by a separate thread) to
process incoming async RPCs

Hopefully that explains the concept. If you need example code I can try and pull something together (it will be in Java). The nice thing about this method is that you don't have to establish two connections, so you can get
around the firewall issues others have mentioned. I've been using this
method on a service in production and haven't had any problems. When you have a separate thread in your client running a Processor you're basically blocking on a read, waiting for a message from the server. The benefit of this is that you're notified immediately when the server shuts down instead of having to wait until you send a message and then finding out that the TCP
connection was reset.
<snip>

Reply via email to