0 Replies Latest reply on Feb 4, 2004 1:05 AM by Tom Elrod

    Remoting Plan

    Tom Elrod Master

      Paste from e-mail thread:

      For those not familiar with remoting and its current capabilities (and how they work), I would suggest reading remoting documentation at http://www.jboss.org/developers/projects/jboss/remoting.

      Is important to remember that there are two layers involved in remoting, a sub-system layer that sits on top of remoting (both on the client and server side) and the remoting layer underneath (whose primary responsibility is transport). The sub-system layer is domain specific (JMX, JMS, EJB, AOP, whatever). This sub-system layer does the mapping into and out of the generic remoting layer.


      Responses inlined...

      Bill Burke wrote:

      >
      >
      > Adrian Brock wrote:
      >
      >> On Wed, 2004-01-14 at 04:49, Tom Elrod wrote:
      >>
      >>> One of the first things I think that needs to be done is breaking up the remoting pieces a little so they can be used in different places within the server. Right now, all the features are pretty closely coupled. This will help in integrating some of the remoting pieces into the invoker layer (mainly just the transport part). This will also help in solving some of the other issues (such as security), which are commented inline below.
      >>>
      >>> Adrian Brock wrote:
      >>>
      >>>> Hi Tom,
      >>>>
      >>>> I would like to add the requirement that the client callbacks
      >>>> and possibly remote objects be handled transparently inside the
      >>>> remoting as far as possible.
      >>>>
      >>>
      >>> Not sure how to do this much batter than is now? Calling client will have to provide some sort of interface to callback on when receive callback, right? Currently the interface is InvokerCallbackHandler which only contains:
      >>>
      >>> public void handleCallback(InvocationRequest invocation)
      >>> throws HandleCallbackException;
      >>>
      >>> Don't see how can do callbacks without interface to callback on since expect the callback to be async. Don't want to block calling thread, or no point in doing callback.
      >>>
      >>
      >>
      >> Are you saying the callback is only for the response?
      >> What I'm after is being able to deliver a handler to the server
      >> that can later be invoked by the server.
      >> e.g. NotificationListener in jmx
      >> Remoting would turn it into a remote proxy.
      >> Of course this will be on a different thread.
      >>
      >
      > Tom, remember we talked about having callbacks for classloading too for the two stage demarshalling?
      >

      For async (push) callbacks (and am referring to a sub-system client who wishes to receive callbacks from a sub-system server, as in the case of JMX Notifications), the client subsystem would provide a callback handler interface to the remoting layer (client-side). This is the interface that will be called on within the client's implementation when a callback is received from the server.

      The remoting client will keep a reference to the client's callback handler interface locally and make the invocation on the remoting server. This invocation will tell the remoting server to create a remoting proxy back to the client to represent the client's callback handler on the server side. The remoting server will then make the invocation on the server-side subsystem and will be passing the server-side proxy for the client's callback handler. Thus the server-side sub-system is not aware that it does not have a direct reference to the client's callback handler. When the server-side sub-system calls on this callback handler, it will really be calling on the proxy that will then dispatch the callback to the remoting client, which will then make the callback on the real client's callback handler.

      Note, doing it this way prevents the callback handler implementation from having to be serializable.

      Pull callbacks are different (but can read remoting doc for that

      One very nice feature of remoting (that applies in all cases, not just callbacks) is that if the server is actually local, the transport layer is cut out and the invocation is made directly on the local server (so do not incur overhead of serialization). One real life use case of this was at Vocalocity where we would need an MBean service to convert text to speech. If a synthesis service was local, would use that one, and make the call directly on the MBean, without having to add any extra logic above the remoting layer, which obviously improved performance a great deal.


      >>
      >>>> There is a mechanism to provide a callback handler on the client's
      >>>> session. But this looks like it always has to open a new endpoint
      >>>> If you compare this with the mechanism used in jmx-remoting, where
      >>>> it can do polling over the same transport.
      >>>>
      >>>> It would be preferable for the transport to handle the callback.
      >>>> It knows better the mechanism is bidirectional, needs to open
      >>>> a new endpoint on the client or has to use polling/piggyback.
      >>>> I'd keep the option open to use an alternate transport
      >>>> for callbacks.
      >>>>
      >>>
      >>> I don't think this is a good idea for a few reasons. First, I don't think the transport really knows if should be bi-directional. This will usually be determined by the network configuration. For example, might have a setup where allows socket connections out, but firewall blocks incoming sockets. Don't know of a way for us to discover this from within remoting automatically.
      >>>
      >>
      >>
      >> It is only the transport that knows whether it can support
      >> bidirectionality.
      >> SOAP does not, sockets can.
      >> I'm saying it should be configurable, but it should not be upto each
      >> user of remoting to handle the different mechanisms.
      >> You wouldn't write a NotificationListener in jmx that has to support
      >> polling or async callbacks. It is the responsibility of jmx to deliver the notification
      >> to the registered handler.
      >> The same should be true of any remote aspect.
      >>
      >
      > Agreed.
      >

      We have gotten burned on this in the past and think that is should really be determined at the sub-system level (if want to do it programatically) or by configuration (if just want to default entire transport protocol). However, if you can tell me how to avoid the following scenario, I'll concede.

      Client wants to add itself as a notification listener to a remote mbeanserver. The remoting layer makes the invocation over a network to the remote mbeanserver using a socket connector (thus being bidirectional). The remote mbeanserver adds the notification listener (will be a proxy, but not important for this example). The remote mbean server then generates a notification to be dispatched to the notification listener. The remoting layer then attempts to make socket connection back to the client's remoting server, but the firewall between the client's remoting server and the server's remoting server blocks this, so can not establish connection back in. Therefore, the client never receives any notifications and just thinks none have been generated by the remote mbeanserver since no way for server to tell client that there was a problem.

      There are many ways we can set up remoting so that it can be told if each transport should be bidirectional or not, but don't think setting it to a hard-code value that can not be changed is good (I know that is the way it is in the code now, but like I was saying, it has burned me in the past during a demo and needs to be changed).


      >>
      >>> Second, would like to allow the user the ability to have callbacks on a different transport. An example would be using socket transport for making outbound invocations, but soap for inbound (for callbacks in this case). This puts the burden on the user of remoting, but think that's where it should lie.
      >>>
      >>
      >>
      >> Configuration yes, implementation no.
      >>
      >
      > This should be a low priority item anyways as we currently have no need for it.
      >

      This is already built in (by design).

      >>
      >>> I agree with not having to open a new endpoint for pooling callbacks (which already exists within remoting, just not at transport level). Could change to piggyback callbacks on return from invocations when doing pooling, so they will be there locally when client makes getCallbacks() call.
      >>>
      >>> The only problem is when callbacks exist on server, but client has not made an invocation since the callbacks were generated on the server, so no callbacks exist locally when client makes getCallbacks() call. Would have to incur the extra call across the wire to make sure client gets all callbacks that exist, so not sure if this buys us much.
      >>>
      >>
      >>
      >> This describes the polling/piggyback which is ok when the callback
      >> is not time dependent. The client will also want to be able
      >> configure a transport where direct invocation from server to client
      >> is possible for timely responsiveness.
      >>

      Think we should put off the piggybacking for now and just make the call on the server for callbacks when doing polling. I can't think of any use case where client would ask for callbacks and not care if gets any back (even if they exist on server). Maybe later we can add piggyback and if not had a invocation (which would use the piggyback to get callbacks) within a certain amount of time, then would call to server to get them (otherwise, just return what have locally).


      >>
      >>>> The more complicated requirement is to provide a mechanism similar
      >>>> java.rmi.Remote and UnicastRemoteObject.
      >>>> With this mechanism, a remote object can be passed between jvms.
      >>>> As the object goes across the wire the object is replaced with a stub.
      >>>> With UnicastRemoteObject you don't have to explicity export the object.
      >>>> The export is done by RMI as the object is transferred.
      >>>> NOTE: Sun's current UnicastRemoteObject has a bug where it never
      >>>> releases the socket when you unexport the object.
      >>>> This implies some form of distributed garbage collection.
      >>>>
      >>>
      >>> A little confused on this. Assume you mean would take the object and create a dynamic proxy to it on the far side that would then send invocations on it across the wire to the original object? Already do this with JMX remoting being the backing sub-system for MBeans. Think AOP remoting sub-system will be used for doing this on POJOs.
      >>>
      >>
      >>
      >> This is the old MBean argument again.
      >> The client might not have AOP or an MBeanServer or if it does
      >> we don't have enough control over the environment to guarantee
      >> either would work. We need a POJO mechanism.
      >>
      >
      > The AOP stuff is designed to work in an NON-AOP environment. It relies on the classloading of the remoting layer to load proxy classes. This would be another interesting requirement for AOP Remoting though. That when a particular POJO instance is marshalled, a stub is put in its place if it is a remote object.
      >
      > How would you implement? Extend ObjectOutputStream. Before any writeObject, ask the subsystem handler whether it should be replaced?
      >

      We can handle this within remoting (already have some stuff for this), but this only gets us part of the way. More to remoting objects than just making a remote proxy. Have to have some kind of lookup/registry, garbage collecting, etc. To make it work end-to-end, will have to have all of this in place.

      >>
      >>>> The AOP remoting subsystem currently registers objects enhanced
      >>>> with the remote aspect in a registry (Dispatcher).
      >>>> This mechanism can only be used in environments where aop is
      >>>> enabled.
      >>>>
      >>>> To summarise what I would like to see is that if an object
      >>>> has a tagging interface (it could be java.rmi.Remote),
      >>>> remoting replaces the object with a proxy that does one of the
      >>>> following depending upon the transport/configuration:
      >>>>
      >>>> 1) The proxy talks back using the locator provided
      >>>> 2) The proxy can link back to the transport when it is bidirectional
      >>>> 3) The proxy adds the callback invocations to the client's session
      >>>> where the client side can retrieve them using polling/piggyback.
      >>>>
      >
      > You also need to be able to attach interceptors to the proxy as well. So I suggest the above implementation. Have an extended ObjectOutputStream that calls back to the subsystem handler for the creation of the proxy. What throws a wrench in all of this is non-Java clients like IIOP. Maybe Remoting provides an interface the proxy must implement so that transports like IIOP can extract an OID to stuff in the IOR.
      >
      >>>> On the security issue, RMI only allows remote class loading
      >>>> when a security manager is installed. It runs the code using the
      >>>> security configuration against the codebase provided to load the class.
      >>>>
      >>>
      >>> Think I have a solution to the classloading security problem where will have two payloads within invocation request; one for system and one for target. The system will be deserailized within remoting and passed along interceptor chain, where interceptors like security can do authentication. Then the target payload can be deserialized within the target context so that can use the target's classloader. There is still a good bit to iron out here.
      >>
      >>
      >>
      >>
      >> The key issue is that the class should run in a sandbox.
      >> It can be a sandbox that allows everything.
      >>
      >
      > Tom, we talked about this security and the problems with it. Currently EJBs in JBoss have two step marshalling, so you will need callbacks to the transport to resolve classes.


      This will be one of the things that I will be taking care of while integrating remoting into current server invokers. Will either pass on remoting classloader to subsytem to use (so if sub-system's parent classloader fails, will try the remoting one which can try to load the classes) or use the codebase uri (as Adrian suggested).

      >
      > Bill
      >
      >> Regards,
      >> Adrian
      >>
      >>
      >>>> Regards,
      >>>> Adrian
      >>>>
      >>>> On Sun, 2004-01-11 at 07:07, Tom Elrod wrote:
      >>>>
      >>>>
      >>>>> I have put together a brief plan for what I would like to do in remoting over the next few months. Let me know if you have any questions or suggestions.
      >>>>>
      >>>>> Thanks.
      >>>>>
      >>>>> -Tom
      >
      >
      >