ietf-openproxy
[Top] [All Lists]

RE: OPES protocol, pre-draft

2003-02-19 09:48:36

On Wed, 19 Feb 2003, Oskar Batuner wrote:

1. Terminology: I'd suggest using names "OPES processor" and
"callout server", as in the architecture document. OPES server is a
bit confusing - too similar to OPES processor (which in fact is also
a server).

Will change.

I'd also suggest using transaction-id (tid) instead of buffer-id.

Transaction ID is already used to identify application transaction
(xid). Xid is [the only thing] shared among messages from and to OPES
processor.

"Buffer ID" clearly causes confusion though. Do you like Application
Message ID (amid) instead of buffer-id? An application transaction
usually involves several application messages (original and produced),
which is reflected in how "amid" (currently "bid") is used by the
protocol.

2. Transaction boundaries: in your example OPES server does not send
xaction-end. This may result in protocol stack on the callout server
keeping some tid-related data for indefinite time - in order to
correctly match possible incoming messages to the protocol state.

I'd suggest keeping clear transaction structure: each side MUST open
and close transaction with predefined start-end messages. This will
result in more stable and reliable protocol state machine.

The text should probably be polished to make it more clear. There is
absolutely NO reason for the side that receives a xaction-end message
to send a xaction-end message back. Here is why:

        - a side MUST ignore messages for unknown transactions
          (except for xaction-start messages, of course);
          doing so requires keeping state for known transactions,
          which is something that has to be done anyway; a simple
          hash table would do

        - once a side sends a xaction-end message, it deletes all
          corresponding data structures, and the corresponding
          xaction ID immediately becomes "unknown" for that side

        - if the other side responds to the xaction-end message with
          its own xaction-end message, the latter will simply be
          ignored by the first side; sending a xaction-end message to
          the side that already sent xaction-end message is a waste of
          resources

As you can see, the state machine is deterministic and simple. Once a
side says that it does not care about the transaction, there is no
reason to tell it _anything_ about that transaction. There is no way a
correct implementation can end up with xid-related data for indefinite
time because of the above optimizations -- there is no xid-related
data at the side once xaction-end message is sent by that side.

Does this clarify? Did I miss anything?

3. Client-server protocol versus independent message flow. I think
that client-server architecture (as in ICAP and HTTP) has certain
advantages. It fits well OPES dataflow model: OPES server always
initiates transaction as result of some message received from
customer. Callout server provides services that are initiated by
request made by OPES processor. This structure is simpler,

First of all, there is a terminology problem here (possibly introduced
by my own wording!). The proposed protocol uses a "pipeline" model. It
is still possible to call it a client-server protocol, I guess. The
key difference is the difference between strict "at most
one-outstanding-query" approach and a "pipeline of queries". But let's
use the client-server term to describe "at most one-outstanding-query"
approach, for now.

I do not see how a client-server model is simpler. Can you elaborate?
The proposed "pipeline" protocol has a very straightforward (simple?)
state-machine-like implementation.

Moreover, I argue that client-server model is inappropriate for OPES
because it does not handle data flow efficiently. It does not scale
with the size of the application message. Client-server model is good
for handling small atomic transactions. The proposed pipeline model is
good for handling data transfers. If we want OPES to be efficient then
we should optimize data flow, and client-server model does not allow
for that.

Client-server abstraction is OK when working on high-level and
treating each application message as a size-less blob of information:

        Time  Action
        ----  ------
        0     Read the original application message
        1     Send query: "Please modify this message"
        2     Receive response: "Here is a modified message"
        3     Write the produced application message

Once we start looking at the implementation level, the above becomes
very inefficient both because of the resources spend keeping all the
state and because of the introduced delays. This traditional approach
does not scale with the message size. ICAP tries to solve the problem
with the "preview" feature, but that solution is partial and rigid. To
get rid of large buffers and staging delays one must use a pipeline
approach:

        Time  Action
        ----  ------
        t     Read chunk #N of the original message
        t     Modify chunk #N-1 of the original message
        t     Write chunk #N-2 of the original message
        t+1   Send query: "Please modify chunk #N"
        t+1   Receive response: "Here is modified chunk #N-1
        ...

Since most of the actions are performed on small chunks and in
parallel, the buffering requirements are minimal and so is the extra
delay. Response time overhead of a good OPES implementation should not
exceed that of a [second] proxy overhead.

Historical evidence in point: Optimized HTTP proxies do not use
client-server model internally. The proxies pipeline data from the
client to server side and back. OPES is also a proxy (just look at the
architecture diagrams in the release WG IDs).

and if we need transactions initiated by callout server independent
from OPES data flow (for example request for policy information,
address book, preferences, etc.) we may use a different
unidirectional channel.

Note that the proposed protocol does not define transaction-related
messages that are spontaneously initiated by callout server,
independent from OPES data flow. The callout server always "responds"
to the stream of messages initiated by the OPES processor.

As for transaction-independent messages, yes, those can be implemented
on separate channels. Having separate channels may make priority
handling of transaction-dependent messages easier. We can discuss this
(less important design decision) later.

In our case by-directional channel may be presented as two
unidirectional ones, and as far as I can see OPES protocol fits
client-server model very well. All exchanges are taking place in the
context of some transaction, each such transaction consist of
request-response sequences, in each transaction we have a clear
division of roles: one side is a service requestor (client), another
- a service produce (server), and the protocol messages that each
side may produce are subordinate to it's role in the current
transaction. Moreover, there are distinct sets of requests that may
be send by OPES server / callout server.

I mostly agree. As I said, there seems to be a terminology problem.
The proposed approach fits your description above relatively well; the
key [difference] is that the request-response pairs are not sequential
but pipelined. Without the pipeline, the protocol does not scale with
the message size (see illustrations above). Once you accept the
pipeline idea, everything should snap into place.

In other words, the proposed protocol is closed to a traditional
client-server approach at the level of message _chunks_. The important
part is, however, not handling of individual chunks, but making an
efficient pipeline from chunk-related "queries" and "responses".

Do you agree? Can you think of a pipeline-less alternative that still
scales well with the message size?

Thank you,

Alex.

-- 
                            | HTTP performance - Web Polygraph benchmark
www.measurement-factory.com | HTTP compliance+ - Co-Advisor test suite
                            | all of the above - PolyBox appliance

<Prev in Thread] Current Thread [Next in Thread>