received at the next machine. It says
nothing about the actual delivery of the
message to the destination and even
less about any processing the application may do with the message. This is
even more complicated if there is an
intermediate application that subcontracts the work to another application
service (see Figure 7). Transport and
plumbing acknowledgments cannot
be visible to applications or there may
be bugs introduced when the destination service is reconfigured. The ACK
tells Service A’s plumbing that Service
B’s plumbing has the message, but
does not tell Service A anything about
Service C’s receipt of the message. Service A must not act on the ACK.
ACK means sending the message again
won’t help. If the sending application
is made aware of the ACK and acts on
that knowledge, then it may cause bugs
if and when the real work fails to materialize.
figure 8. the first message sent to a service must be idempotent.
Must be
Idempotent
Must be
Idempotent
Must be
Idempotent
Must be
Idempotent
Service-A
Service-B
Service-A
Service-B
Service-B
Service-A
Request-
Response
Service-B
Service-A
Fire-And-
Forget
figure 9. the first messages to a scalable service must be idempotent
Server Foo-A
Server Foo-N
2
5
Do work from
#1, 2, 3
Do work from
#1, 2, 3
Service
“Foo”
1
Plumbing Can mask Ambiguities
of Partnership (but rarely does)
It is possible for the message-delivery
plumbing to have a formalized notion
of a long-running dialog. The plumbing must define and implement the following:
˲ State. How is the state information
from a partially completed dialog represented by the application? Remember, either the state must survive failures of a component or the dialog must
cleanly fail as a consequence of the failure—just forgetting the early messages
is bad.
˲ Routing. How do later messages
find a service (and server) that can locate the state and correctly process the
new message without amnesia about
the earlier messages?
˲ Dialog semantics. How can the
dialog provide correct semantics even
when the real work of the dialog is
subcontracted to somebody way the
heck over yonder? Part of this is properly masking transport issues (such as
ACKs) that will only cause problems if
seen by the application.
Thus, it seems that messaging semantics are intimately tied to naming,
routing, and state management. This
inevitably means the application designer is faced with challenges when
the database comes from a plumbing
supply house that is different from that
Unresolved Name:
Foo-A
3
Unresolved: Foo
Seq #1
4
6
Unresolved: Foo
Seq #1
Unresolved Name:
Foo-N
Lost!
Unresolved: Foo
Seq #2
Unresolved: Foo
Seq #2
Unresolved: Foo
Seq #3
Retry
Unresolved: Foo
Seq #3
Initiating Service
of the messaging system. One system
that does provide crisp dialog semantics is SQL Service Broker.
4 It does so by
holding the messaging and dialog state
in the SQL database.
talking to a service
Services are designed to be black box.
You know the service address, start
working with it, chatter back and forth,
and then finish. It turns out that, even
with the support of some plumbing to
provide you with dialogs, there are issues with repeated messages and lost
messages. These challenges are compounded when the target service is
implemented in a scalable fashion. Of
course, that means you may start out
interacting with a service that is not yet
scalable, and, as it grows, certain new
obstacles arise.
A dialog goes through three stages in
its lifetime:
˲ Initiation. Messages are sent from
the dialog initiator to the target of the
dialog. The initiator does not know if
the target is implemented as a single
server or a load-balanced pool.
˲ Established. Messages may flow
in both directions in full-duplex fashion. The messaging system has now
ensured that either multiple messages
will land at the same server in a load-balanced pool or the server processing
the message will accurately access the
state remembered from the previous
messages (and behave as if it were the
same server).
˲ Closing. The last message (or messages flowing together in the same direction) gets sent.
Each of these stages of communication offers challenges, especially the
initiation and closing stages.
When the first message in a dialog
is sent, it may or may not need retrying.