rfc3117.txt

来自「RFC 的详细文档!」· 文本 代码 · 共 1,516 行 · 第 1/4 页

TXT
1,516
字号
   the fact that a lack of asynchrony in application protocols causes
   implementors to make sloppy use of the transport layer, network
   protocols are now provisioned with increasing sophistication, e.g.,
   RED [27].  Further, suggestions are also being considered for
   modification of TCP implementations to reduce concurrent learning,
   e.g., [28].

   In terms of the server, each incoming connection must be dispatched
   and (probably) authenticated against the same resources.
   Consequently, server overhead increases based on the number of
   connections established, rather than the number of remote users.  The
   same issues of fairness arise: it's much harder for servers to
   allocate resources on a per-user basis, when a user can cause an
   arbitrary number of connections to pound on the server.

   Another important aspect of scalability to consider is the relative
   numbers of clients and servers.  (This is true even in the peer-to-
   peer model, where a peer can act both in the client and server role.)
   Typically, there are many more client peers than server peers.  In
   this case, functional requirements should be shifted from the servers
   onto the clients.  The reason is that a server is likely to be
   interacting with multiple clients and this functional shift makes it
   easier to scale.




Rose                         Informational                     [Page 14]

RFC 3117         On the Design of Application Protocols    November 2001


4.2 Efficiency

   A well-designed protocol is efficient.

   For example, although a compelling argument can be made than octet-
   stuffing leads to more elegant implementations than octet-counting,
   experience shows that octet-counting consumes far fewer cycles.

   Regrettably, we sometimes have to compromise efficiency in order to
   satisfy other properties.  For example, 822 (and MIME) use textual
   headers.  We could certainly define a more efficient representation
   for the headers if we were willing to limit the header names and
   values that could be used.  In this case, extensibility is viewed as
   more important than efficiency.  Of course, if we were designing a
   network protocol instead of an application protocol, then we'd make
   the trade-offs using a razor with a different edge.

4.3 Simplicity

   A well-designed protocol is simple.

   Here's a good rule of thumb: a poorly-designed application protocol
   is one in which it is equally as "challenging" to do something basic
   as it is to do something complex.  Easy things should be easy to do
   and hard things should be harder to do.  The reason is simple: the
   pain should be proportional to the gain.

   Another rule of thumb is that if an application protocol has two ways
   of doing the exact same thing, then there's a problem somewhere in
   the architecture underlying the design of the application protocol.

   Hopefully, simple doesn't mean simple-minded: something that's well-
   designed accommodates everything in the problem domain, even the
   troublesome things at the edges.  What makes the design simple is
   that it does this in a consistent fashion.  Typically, this leads to
   an elegant design.

4.4 Extensibility

   A well-designed protocol is extensible.

   As clever as application protocol designers are, there are likely to
   be unforeseen problems that the application protocol will be asked to
   solve.  So, it's important to provide the hooks that can be used to
   add functionality or customize behavior.  This means that the
   protocol is evolutionary, and there must be a way for implementations
   reflecting different steps in the evolutionary path to negotiate
   which extensions will be used.



Rose                         Informational                     [Page 15]

RFC 3117         On the Design of Application Protocols    November 2001


   But, it's important to avoid falling into the extensibility trap: the
   hooks provided should not be targeted at half-baked future
   requirements.  Above all, the hooks should be simple.

   Of course good design goes a long way towards minimizing the need for
   extensibility.  For example, although SMTP initially didn't have an
   extension framework, it was only after ten years of experience that
   its excellent design was altered.  In contrast, a poorly-designed
   protocol such as Telnet [29] can't function without being built
   around the notion of extensions.

4.5 Robustness

   A well-designed protocol is robust.

   Robustness and efficiency are often at odds.  For example, although
   defaults are useful to reduce packet sizes and processing time, they
   tend to encourage implementation errors.

   Counter-intuitively, Postel's robustness principle ("be conservative
   in what you send, liberal in what you accept") often leads to
   deployment problems.  Why? When a new implementation is initially
   fielded, it is likely that it will encounter only a subset of
   existing implementations.  If those implementations follow the
   robustness principle, then errors in the new implementation will
   likely go undetected.  The new implementation then sees some, but not
   widespread deployment.  This process repeats for several new
   implementations.  Eventually, the not-quite-correct implementations
   run into other implementations that are less liberal than the initial
   set of implementations.  The reader should be able to figure out what
   happens next.

   Accordingly, explicit consistency checks in a protocol are very
   useful, even if they impose implementation overhead.

















Rose                         Informational                     [Page 16]

RFC 3117         On the Design of Application Protocols    November 2001


5. The BXXP Framework

   Finally, we get to the money shot: here's what we did.

   We defined an application protocol framework called BXXP (the Blocks
   eXtensible eXchange Protocol).  The reason it's a "framework" instead
   of an application protocol is that we provide all the mechanisms
   discussed earlier without actually specifying the kind of messages
   that get exchanged.  So, when someone else needs an application
   protocol that requires connection-oriented, asynchronous
   interactions, they can start with BXXP.  It's then their
   responsibility to define the last 10% of the application protocol,
   the part that does, as we say, "the useful work".

   So, what does BXXP look like?

           Mechanism  BXXP
       --------------  ----------------------------------------
             Framing  counting, with a trailer

            Encoding  MIME, defaulting to text/xml

           Reporting  3-digit and localized textual diagnostic

          Asynchrony  channels

      Authentication  SASL

             Privacy  SASL or TLS


5.1 Framing and Encoding

   Framing in BXXP looks a lot like SMTP or HTTP: there's a command line
   that identifies the beginning of the frame, then there's a MIME
   object (headers and body).  Unlike SMTP, BXXP uses octet-counting,
   but unlike HTTP, the command line is where you find the size of the
   payload.  Finally, there's a trailer after the MIME object to aid in
   detecting framing errors.

   Actually, the command line for BXXP has a lot of information, it
   tells you:

   o  what kind of message is in this frame;

   o  whether there's more to the message than just what's in this frame
      (a continuation flag);




Rose                         Informational                     [Page 17]

RFC 3117         On the Design of Application Protocols    November 2001


   o  how to distinguish the message contained in this frame from other
      messages (a message number);

   o  where the payload occurs in the sliding window (a sequence number)
      along with how many octets are in the payload of this frame; and,

   o  which part of the application should get the message (a channel
      number).

      (The command line is textual and ends in a CR-LF pair, and the
      arguments are separated by a space.)

   Since you need to know all this stuff to process a frame, we put it
   all in one easy to parse location.  You could probably devise a more
   efficient encoding, but the command line is a very small part of the
   frame, so you wouldn't get much bounce from optimizing it.  Further,
   because framing is at the heart of BXXP, the frame format has several
   consistency checks that catch the majority of programming errors.
   (The combination of a sequence number, an octet count, and a trailer
   allows for very robust error detection.)

   Another trick is in the headers: because the command line contains
   all the framing information, the headers may contain minimal MIME
   information (such as Content-Type).  Usually, however, the headers
   are empty.  That's because the BXXP default payload is XML [30].
   (Actually, a "Content-Type: text/xml" with binary transfer encoding).

   We chose XML as the default because it provides a simple mechanism
   for nested, textual representations.  (Alas, the 822-style encoding
   doesn't easily support nesting.) By design, XML's nature isn't
   optimized for compact representations.  That's okay because we're
   focusing on loosely-coupled systems and besides there are efficient
   XML parsers available.  Further, there's a fair amount of anecdotal
   experience -- and we'll stress the word "anecdotal" -- that if you
   have any kind of compression (either at the link-layer or during
   encryption), then XML encodings squeeze down nicely.

   Even so, use of XML is probably the most controversial part of BXXP.
   After all, there are more efficient representations around.  We
   agree, but the real issue isn't efficiency, it's ease of use: there
   are a lot of people who grok the XML thing and there are a lot of XML
   tools out there.  The pain of recreating this social infrastructure
   far outweighs any benefits of devising a new representation.  So, if
   the "make" option is too expensive, is there something else we can
   "buy" besides XML? Well, there's ASN.1/BER (just kidding).






Rose                         Informational                     [Page 18]

RFC 3117         On the Design of Application Protocols    November 2001


   In the early days of the SNMP [31], which does use ASN.1, the same
   issues arose.  In the end, the working group agreed that the use of
   ASN.1 for SNMP was axiomatic, but not because anyone thought that
   ASN.1 was the most efficient, or the easiest to explain, or even well
   liked.  ASN.1 was given axiomatic status because the working group
   decided it was not going to spend the next three years explaining an
   alternative encoding scheme to the developer community.

   So -- and we apologize for appealing to dogma -- use of XML as the
   favored encoding scheme in BXXP is axiomatic.

5.2 Reporting

   We use 3-digit error codes, with a localized textual diagnostic.
   (Each peer specifies a preferred ordering of languages.)

   In addition, the reply to a message is flagged as either positive or
   negative.  This makes it easy to signal success or failure and allow
   the receiving peer some freedom in the amount of parsing it wants to
   do on failure.

5.3 Asynchrony

   Despite the lessons of SMTP and HTTP, there isn't a lot of field
   experience to rely on when designing the asynchrony features of BXXP.
   (Actually, there were several efforts in 1998 related to application
   layer framing, e.g., [32], but none appear to have achieved orbit.)

   So, here's what we did: frames are exchanged in the context of a
   "channel".  Each channel has an associated "profile" that defines the
   syntax and semantics of the messages exchanged over a channel.

   Channels provide both an extensibility mechanism for BXXP and the
   basis for parallelism.  Remember the last parameter in the command
   line of a BXXP frame? The "part of the application" that gets the
   message is identified by a channel number.

   A profile is defined according to a "Profile Registration" template.
   The template defines how the profile is identified (using a URI
   [33]), what kind of messages get exchanged, along with the syntax and
   semantics of those messages.  When you create a channel, you identify
   a profile and maybe piggyback your first message.  If the channel is
   successfully created, you get back a positive response; otherwise,
   you get back a negative response explaining why.

   Perhaps the easiest way to see how channels provide an extensibility
   mechanism is to consider what happens when a session is established.
   Each BXXP peer immediately sends a greeting on channel zero



Rose                         Informational                     [Page 19]

RFC 3117         On the Design of Application Protocols    November 2001


   identifying the profiles that each support.  (Channel 0 is used for
   channel management -- it's automatically created when a session is
   opened.) If you want transport security, the very first thing you do
   is to create a channel that negotiates transport security, and, once
   the channel is created, you tell it to do its thing.  Next, if you
   want to authenticate, you create a channel that performs user
   authentication, and, once the channel is created, you tell it to get
   busy.  At this point, you create one or more channels for data
   exchange.  This process is called "tuning"; once you've tuned the
   session, you start using the data exchange channels to do "the useful
   work".

   The first channel that's successfully started has a trick associated
   with it: when you ask to start the channel, you're allowed to specify
   a "service name" that goes with it.  This allows a server with
   multiple configurations to select one based on the client's
   suggestion.  (A useful analogy is HTTP 1.1's "Host:" header.) If the
   server accepts the "service name", then this configuration is used
   for the rest of the session.

   To allow parallelism, BXXP allows you to use multiple channels
   simultaneously.  Each channel processes messages serially, but there
   are no constraints on the processing order for different channels.
   So, in a multi-threaded implementation, each channel maps to its own
   thread.

   This is the most general case, of course.  For one reason or another,
   an implementor may not be able to support this.  So, BXXP allows for
   both positive and negative replies when a message is sent.  So, if
   you want the classic client/server model, the client program should
   simply reject any new message sent by the server.  This effectively
   throttles any asynchronous messages from the server.

   Of course, we now need to provide mechanisms for segmentation and
   flow control.  For the former, we just put a "continuation" or "more
   to come" flag in the command line for the frame.  For the latter, we
   introduced the notion of a "transport mapping".

   What this means is that BXXP doesn't directly define how it sits of
   top of TCP.  Instead, it lists a bunch of requirements for how a
   transport service needs to support a BXXP session.  Then, in a
   separate document, we defined how you can use TCP to meet these
   requirements.

   This second document pretty much says "use TCP directly", except that
   it introduces a flow control mechanism for multiplexing channels over
   a single TCP connection.  The mechanism we use is the same one used




Rose                         Informational                     [Page 20]

RFC 3117         On the Design of Application Protocols    November 2001


   by TCP (sequence numbers and a sliding window).  It's proven, and can
   be trivially implemented by a minimal implementation of BXXP.

   The introduction of flow control is a burden from an implementation
   perspective -- although TCP's mechanism is conceptually simple, an
   implementor must take great care.  For example, issues such as
   priorities, queue management, and the like should be addressed.
   Regardless, we feel that the benefits of allowing parallelism for
   intra-application streams is worth it.  (Besides, our belief is that
   few application implementors will actually code the BXXP framework
   directly -- rather, we expect them to use third-party packages that

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?