Distributed Program Construction
Fall 1999
Lecture 4: Client-Server Model and RPC
COMP 413
Client-Server Model
-
Networking protocols are responsible
only for data transmission
-
No mechanisms for automatically starting
processes
-
No policies regarding who starts and
who waits
-
There is a need for an interaction
model
-
Goal: enable 2 processes
to synchronize in order to perform a cooperative computation
-
One of the processes must wait for
the other (server, or inetd)
-
Client initiates interaction and server
replies with results
-
Requires 2 mandatory types of messages:
-
request (client-2-server)
-
reply (server-2-client)
-
Requires 2 types of system calls:
-
send (dst, buf)
-
recv (src, buf)
basic interaction:
Client
Server
.
send(request)
.
.
.
.
recv(request)
wait
process request
.
send(reply)
.
.
recv(reply)
.
COMP 413
Client-Server communication
semantics
Addressing:
-
machine_ID:process_ID (location-dependent)
-
machine_ID:port (e.g., sockets. location-dependent,
process-independent)
-
logical server name - location independent,
but requires name server
-
on recv, address may be ANY
Blocking (synchronous) vs. non-blocking:
-
fully blocking send: wait until
message arrived (ack.)
-
blocking send (OS view):
wait until message sent
-
non-blocking send: copy to kernel
space, wait only until copy completed (why?)
-
fully non-blocking send: return
immediately, interrupt when sent
-
Unix Socket send:
-
default: blocking with copy (if not
enough buffer space, wait)
-
non-blocking mode (via fcntl):
return with EWOULDBLOCK, use poll or select
-
blocking recv: wait until message
arrived (common)
-
non-blocking recv: return immediately,
use select
-
Unix Socket supports both modes (Java
currently supports blocking only)
Buffered vs. unbuffered
-
To allow send before recv, message addressed
to mailbox, not to process
-
still, if buffer full, message might get lost
COMP 413
Client-Server Issues
-
Conventional client-server:
-
Blocking (but not fully-blocking)
send,
blocking
and buffered recv
-
Reply from server used as an ack.
-
Another approach (ADA):
-
fully blocking send, blocking
recv
-
after rendevouz, both processes know
that message was received
-
Also: non-fully-blocking send,
non-blocking recv
-
Stateless vs. stateful servers:
-
stateless preferred
-
if state is maintained, need idempotent
operations
-
Applications may involve components
that are both clients and servers
-
A server may need services of other
servers
-
A client may need to wait (act as a
server)
-
Care must be taken to avoid circular
dependencies (deadlock)
-
Multi-threading important for effective
client-server applications (else need to use non-blocking I/O everywhere)
COMP 413
Remote Procedure Call (RPC)
-
Client-server computing depends on
I/O (sending messages)
-
not natural in centralized computing,
thus violates programming transparency
-
Idea: allow programs to call procedures
on remote machines as if they were local
-
communication around procedure calls,
as in centralized computing
-
attempt to provide "programming transparency"
-
Problems in masking distribution:
-
different memory spaces
-
parameter passing
-
binding
-
failures
-
Various implementations exist:
-
Xerox (as usual - first, but hardly
heard of)
-
Sun RPC (most widely used, used by
NFS)
-
ANSA
-
DCE (OpenGroup)
-
FireFly
COMP 413
Basic RPC Operation
-
Calling procedure is not aware that called procedure executes
remotely, and vice-versa.
-
Similar to system call wrapper (e.g.,
read)
-
put parameters on stack
-
call read library function,
which calls READ system call by trapping to the kernel and returns result
to caller on the stack
-
RPC read implemented as:
-
put parameters on stack
-
call client-stub of read,
which
packs a message and traps the kernel to send the message to server, then
calls recv
-
remote kernel passes message to (waiting)
server-stub,
which
unpacks the message and puts parameters on stack, invoking server procedure
normally
-
when control returns to stub, packs
message and sends back to client-stub, which unpacks results and returns
control (and output) to caller
-
Stub generation:
-
an Interface Definition Language file
contains RPC specification:
-
program name, procedure number, version
number
-
procedure signatures (including in-out)
-
specification of data structures, in
standard representation (e.g., XDR)
-
IDL compiler (e.g., RPCGEN) generates
"matching" client and server stubs
COMP 413
COMP 413
How does a client locate
a server ?
-
Stubs are generated from a formal specification of a server's
interface:
-
procedure names, signatures, in/out, version, etc.
-
When server is initialized, it exports
its interface by registering at a binder program with a handle
(e.g., ip address and port)
-
Upon a remote-procedure call, if client
not-bound yet, it imports interface from binder
-
Advantages:
-
location independence
-
can balance load
-
fault tolerance
-
authentication, version validation
-
Disadvantage:
-
costly (first lookup)
-
bottleneck, single-point of failure
COMP 413
Main difference between local and remote
invocation is wrt (partial) failure
Many errors that do not exist in
local invocation:
-
client cannot locate the server
-
similar to system calls (-1, "errno")
-
more general solution is use of
exceptions
-
not all languages have them
-
not transparent to the application
programmer
-
Lost request
-
use timeout and retransmission
-
Lost replies
-
requires idempotency
-
sequence numbers
-
server crashes
-
problem: can crash after processing
of request, or before; client can't tell the difference (e.g., printer
request)
-
Solutions:
-
at least once - retry until a reply
is received (e.g., wait for reboot)
-
at most once - return immediately
-
client crashes
-
problem: computation finished, but
client crashed before return (orphan)
-
solutions:
-
write log record to disk, and exterminate
after reboot - expensive
-
Reincarnation - after reboot, broadcast
new epoch
COMP 413