For certain kinds of data it would be useful to continuously stream data from server to client (or vice-versa). This can be represented as an Avro array response or request where each array element triggers a callback at the receiving end. This likely requires an extension to the avro spec, but is much more capable than a polling solution. It is related to Comet in the sense that the RPC request is long lived, but is effectively a sequence of smaller inverse RPCs. Poling in general has built-in race conditions for many types of information exchange and should be avoided whenever such race conditions exist.
For streaming large volumes of data, this would be much more efficient than an individual RPC per item. For example, if the RPC is "I need to know every state change in X" polling is not an option, but streaming is. If the requirement is "I need to know when the next state change occurs, but do not need to know all changes" polling is OK, and streaming may send too much data. On 1/20/12 11:25 AM, "Armin Garcia" <armin.gar...@arrayent.com> wrote: > Hi James, > > I see your point. On a different NIO framework, I implemented exactly the same > message handling procedure (ie message routing) you just described. I guess I > was pushing the NettyTransceiver a bit beyond its intended scope. > > I'll take a look at the comet pattern and see what I can do with it. > > Again, thanks Shaun & James. > > -Armin > > > On Fri, Jan 20, 2012 at 10:15 AM, James Baldassari <jbaldass...@gmail.com> > wrote: >> Hi Armin, >> >> First I'd like to explain why the server-initiated messages are problematic. >> Allowing the server to send unsolicited messages back to the client may work >> for some Transceiver implementations (possibly PHP), but this change would >> not be compatible with NettyTransceiver. When the NettyTransceiver receives >> a message from the server, it needs to know which callback to invoke in order >> to pass the message back correctly to the client. There could be several >> RPCs "in flight" concurrently, so one of NettyTransceiver's jobs is to match >> up the response with the request that initiated it. If the client didn't >> initiate the RPC then NettyTransceiver won't know where to deliver the >> message, unless there were some catch-all callback that would be invoked >> whenever one of these "unsolicited" messages were received. So although >> you're probably only interested in the PHP client, allowing the server to >> send these unsolicited messages would potentially break NettyTransceiver (and >> possibly other implementations as well). >> >> Shaun's idea of having the client poll the server periodically would >> definitely work. What we want to do is have the client receive notifications >> from the server as they become available on the server side, but we also >> don't want the client to be polling with such a high frequency that a lot of >> CPU and bandwidth resources are wasted. I think we can get the best of both >> worlds by copying the Comet pattern, i.e. the "long poll" but using the Avro >> RPC layer instead of (or on top of) HTTP. First we'll start with Shaun's >> update listener interface: >> >> protocol WeatherUpdateListener { >> WeatherUpdate listenForUpdate(); >> } >> >> The PHP client would invoke this RPC against the server in a tight loop. On >> the server side, the RPC will block until there is an update that is ready to >> be sent to the client. When the client does receive an event from the server >> (or some timeout occurs), the client will immediately send another poll to >> the server and block until the next update is received. In this way the >> client will not be flooding the server with RPCs, but the client will also >> get updates in a timely manner. >> >> See the following for more info about Comet: >> http://www.javaworld.com/javaworld/jw-03-2008/jw-03-asynchhttp.html?page=6 >> >> -James >> >> >> >> On Fri, Jan 20, 2012 at 12:44 PM, Armin Garcia <armin.gar...@arrayent.com> >> wrote: >>> Hi Shaun, >>> >>> This is definitely another way. I share your same concern. I have to keep >>> an eye out for high availablilty and high throughput. I'll be depending on >>> this connection to support a massive amount of data. >>> >>> -Armin >>> >>> >>> On Fri, Jan 20, 2012 at 9:25 AM, Shaun Williams <shaun_willi...@apple.com> >>> wrote: >>>> Another solution is to use the response leg of a transaction to push >>>> messages to the client, e.g. provide a server protocol like this: >>>> >>>> WeatherUpdate listenForUpdate(); >>>> >>>> This would essentially block until an update is available. The only >>>> problem is that if the client is expecting a series of updates, it would >>>> need to call this method again after receiving each update. >>>> >>>> This is not an ideal solution, but it might solve your problem. >>>> >>>> -Shaun >>>> >>>> >>>> >>>> On Jan 20, 2012, at 8:24 AM, Armin Garcia wrote: >>>> >>>>> >>>>> Hi James, >>>>> >>>>> >>>>> First, thank you for your response. >>>>> >>>>> >>>>> Yes, you are right. I am trying to setup a bi-directional communication >>>>> link. Your suggestion would definitely accomplish this requirement. I >>>>> was hoping the same channel could be reused without having to establish >>>>> another uni-directional link. Netty or rather NIO is inherently >>>>> bi-directional. I am suspecting RPC by definition is only uni-directional >>>>> or rather a pull technology? >>>>> >>>>> >>>>> One of my goals is to support as many different language bindings using >>>>> Avro. PHP is one of those languages. Unfortunately, the PHP library can >>>>> only function as a client. >>>>> >>>>> >>>>> -Armin >>>>> >>>>> On Fri, Jan 20, 2012 at 7:47 AM, James Baldassari <jbaldass...@gmail.com> >>>>> wrote: >>>>>> Hi Armin, >>>>>> >>>>>> Could you explain a little more about what you're trying to do? It >>>>>> sounds like you want a protocol in which either client or the server >>>>>> initiates a remote procedure call. The easiest way to do this is to have >>>>>> the client also be a server and the server also be a client. For >>>>>> example, consider the following protocols: >>>>>> >>>>>> protocol WeatherClient { >>>>>> double getTemperature(string postalCode); >>>>>> void registerForTemperatureUpdates(string postalCode, string >>>>>> clientHost, int clientPort); >>>>>> } >>>>>> >>>>>> protocol WeatherUpdateListener { >>>>>> void onTemperatureUpdate(String postalCode, double newTemperature); >>>>>> } >>>>>> >>>>>> The client side would use WeatherClient (and >>>>>> SpecificRequestor/NettyTransceiver) to request the temperature for some >>>>>> postal code from the server. The client could also register with the >>>>>> server for temperature updates by passing the postal code it's interested >>>>>> in as well as the hostname/IP and port of a netty server running on the >>>>>> client. The client would run its own netty server using a >>>>>> WeatherUpdateListener and SpecificResponder. When the server has a >>>>>> temperature update to send back to the client, it would send a message to >>>>>> the client using the WeatherUpdateListener interface. Is this close to >>>>>> what you're looking for? >>>>>> >>>>>> -James >>>>>> >>>>>> >>>>>> >>>>>> On Fri, Jan 20, 2012 at 6:34 AM, Armin Garcia <armin.gar...@arrayent.com> >>>>>> wrote: >>>>>>> I am trying to figure out how a message can be sent through a Netty >>>>>>> Server to a connected client. I see the channel is stored in a group >>>>>>> for each client that connects to a Netty Server: >>>>>>> >>>>>>> public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) >>>>>>> throws Exception >>>>>>> { >>>>>>> e.getChannel().write(null); >>>>>>> allChannels.add(e.getChannel()); >>>>>>> super.channelOpen(ctx, e); >>>>>>> } >>>>>>> >>>>>>> The challenge is how to leverage this channel in order to send an >>>>>>> unsolicited message to the client. Is there an example that writes to >>>>>>> the channel but not as a response to a message received? >>>>>>> >>>>>>> I fully expect to take the existing Netty Server and modify it. I >>>>>>> suspect the solution lies somewhere in creating a NettyDataPack then >>>>>>> writing it to the channel. I'm definitely an Avro greenhorn, so I'm a >>>>>>> bit unsure of how to wrangle my message into a NettyDataPack. >>>>>>> >>>>>>> -Armin >>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> >