1 2 Previous Next 21 Replies Latest reply on May 24, 2006 5:27 PM by ovidiu.feodorov

    Forward/backward server-client compatibility

    ovidiu.feodorov

      Scott wrote:


      I have looked through the current jboss-jms tree usage of serialization and we are making the same mistake with respect to versioning of the stream format. There is no versioning. Each writeExternal/readExternal pair should have a version number that allows for the contents to evolve over time in a backward compatible way. Adding data that can be reasonably defaulted is a backward compatibile change that we need to support.


      Ovidiu wrote:

      Thanks
      I'll make sure we fix this.


      Tim wrote:

      I'd like to explore the compatibility requirements for JBossMessaging a bit more as this is currently a bit of a grey area for me.

      I'm assuming a version x client should work with any version y server where y >= x.

      Should a version x client work with a version y server where x > y ?

      When can we make changes to interface/wire format? Is it only on major releases?

      I'd like to get a better understanding of this so we can make sure we're building it in properly.


      Scott wrote:

      The requirement is long term compatibility or else the messaging framework is not suitable for the backbone of an ESB which by definition will operate in a heterogeneous environment. If an binary incompatible change has to be introduced, this is really a new invoker protocol that needs to be a derivative of the existng protocol. This is like introducing UIL2 in addition to UIL. Both will need to be supported at that point. Certinly one can have features never available in the other.

      There is no x, y for which interoperability does not exist.


      Ovidiu wrote:

      In other words, total backward compatibility.

      Of course, we need to add tests for that (TODO)


      Adrian wrote:

      But more importantly. Scott wants forwards compatibility as well ;-)

      Depending on how this is designed/works, the protocol/version could be negotiated once at initial connection rather than passing it on every request.


      Adrian wrote:

      There's some "interesting" edge cases when a client wants to know if it can take advantage of certain features in the later versions of the protocol.

      The problem being if it is talking to a cluster with transparent failover and the cluster is heterogenous in terms of versions supports.



      Ovidiu wrote:

      Interesting. How about client and the server that are "open" to the protocol they use, they negociate this using some sort of handshake.

      Or even better, the client has the wiring to "adapt" its wire protocol based on the information it finds in the ConnectionFactory. The server "advertises" the wire protocol it understands, and the client has a built-in mechanism to adapt to that.

      I (we) need to think about this.



        • 1. Re: Forward/backward server-client compatibility
          timfox

          Yes, I'm thinking some kind of handshake to agree on the lowest .
          common denominator version that's done only once on connection setup.

          Client publishes "I support version a". Server responds "I support version b". They agree on Math.min(a, b).

          This means when we make any changes to the wire format, we also have to preserve the old changes. I.e. behaviour of read/write external depends on variable version negotiated in handshake.

          On a related subject, what about "self updating clients"? If the server and client decide the client version is older than the client could the client not load the new version of the client classes over the network and run them.... Hmmm just a thought.. This could be an alternative to using lowest common denominator version. Need to think this one through more since it's probably not appropriate in a lot of cases.




          • 2. Re: Forward/backward server-client compatibility
            timfox

            I have an initial implementation working.

            It basically doe the following:

            The ConnectionFactory object which is placed in the jndi tree by the server, contains the server's version S

            The client knows it's own version C

            When the client gets hold of a connection factory from jndi it now knows the server version.

            For any connections created using that connection factory the client will use version X, where X is Math.min(S, C).

            This means a client can support many different versions concurrently for different connections depending on the server versions for the respective connection factories.

            In the marshaller, every invocation from client to server is prefixed on the wire by a byte containing the value X.

            Any response is also prefixed with the value X.

            This means the entire wire format can evolve over time, this include the remote Java API, and the wire format of objects.

            • 3. Re: Forward/backward server-client compatibility
              genman


              Just curious. If both client/server know they are using version X, then why put it in every packet between the two?

              • 4. Re: Forward/backward server-client compatibility
                timfox

                The version byte goes at the beginning of each request or response (it doesn't go in each TCP packet - a request / response can be composed of many such packets).

                This is so the server knows how to deal with the request (or the client with the response).

                Imagine in version 1.x we have a wireformat for a send request like the following:

                byte 0: "23" - represents a send request
                bytes 1... serialized form of the message

                and the format for an ack was:

                byte 0: "27" - represents ack
                bytes 1.. message id etc.

                but in version 2.x we changed it to, for a send:

                byte 0: "27" represents send
                bytes 1... serialized form of the message

                Now a client sends a version 1.x send request to the server.

                All the server knows about is the stream of bytes it's receiving so if we don't add version info to the stream then the server doesn't know whether the request is a version1.x send or a version 2.x ack.

                We could fix some of the stuff, e.g. the request codes across all versions and just vary, say, the serialized form of the request body between versions, which would allow us to avoid pasing the version number.

                However this would be far less flexible and prevent us from being able to change the remote API over time.

                • 5. Re: Forward/backward server-client compatibility
                  genman


                  The server knows what byte "27" means since it knows which client it is talking to and what version that client is using. You already established the versions in the beginning, sending it in every message is redundant.

                  • 6. Re: Forward/backward server-client compatibility
                    timfox

                    How does it know which client is talking to it?

                    All it has is the stream of bytes.

                    • 7. Re: Forward/backward server-client compatibility
                      timfox

                      I'll try and make this clearer.

                      A server receives requests which can come from many different clients each using a different version of the protocol.

                      Think of the request as a sequence of bytes.

                      The client doesn't automatically know which request came from which client therefore *does not* know advance the version of the client.

                      So it's not redundant.

                      • 8. Re: Forward/backward server-client compatibility
                        starksm64

                        In terms of the version specification in the connection factory, is this the full x.y.z.q version string? It should be.

                        The per message version as a byte seems too small. jgroups is using a short which requires a compression of the full version string into this value.

                        • 9. Re: Forward/backward server-client compatibility
                          timfox

                          The version byte is just an incrementing version number starting at zero.

                          So for every new wireformat version that we want support we just increment by one.

                          If a release doesn't change the wireformat then we don't change the byte.

                          This means we can support up to 256 changes to the wireformat. We only want to allow changes to the wireformat at major releases.

                          So this would be good for up to 256 major releases.

                          • 10. Re: Forward/backward server-client compatibility
                            timfox

                            Even if we incremented it if we didn't change the wire format it would be good for 256 releases.

                            I guess the questions is do we think there will ever be more than 256 versions of JBossMessaging in existence?

                            • 11. Re: Forward/backward server-client compatibility
                              starksm64

                              Is there a capbility to deal with object evolution (adding fields) in the current wire format? If there is, and the wireformat could evolved to in fact have an additional version byte then this should be fine.

                              • 12. Re: Forward/backward server-client compatibility
                                timfox

                                The entire wire format (with the exception of the first version byte) is free to change completely between versions, so yes we could add a second version byte if necessary if we exceed 256 versions without breaking compatibility with other versions.

                                So, something like:

                                So if version byte 1 is between 0 and 254 the version is given by just that byte.

                                If version byte 1 = 255 then also look at the second byte to get the actual version.

                                • 13. Re: Forward/backward server-client compatibility
                                  starksm64

                                  Then it does not really matter. There still is the question of how the version is described in the connection factory. The version in a connection factory really should be more than just the wire format though.

                                  • 14. Re: Forward/backward server-client compatibility
                                    timfox

                                    The version in the connection factory is an instance of class org.jboss.jms.server.Version, which currently contains the major version and minor version.

                                    It should be fairly easy to extend this so it contains x.y.z.q.

                                    1 2 Previous Next