Remote procedure calls are the basis for about everything in the Hurd.
They're based on the Mach RPC mechanism (mach msg system
call).  An RPC is made against a Mach
port, which is the gateway to the translator that
will serve the RPC.  Let's explore the case of opening a file, and advancing
(lseek) ten bytes into it.  The user program will be something like:
#include <fcntl.h>
int main(void) {
  int fd = open("test.txt", O_RDONLY);
  lseek(fd, 10, SEEK_CUR);
}
Both open and lseek are functions provided by glibc, which translates
these into the appropriate remote procedure calls.
open first has to find its way to the actual translator serving that file,
but for a file on the root filesystem, what happens boils down to calling the
dir_lookup function against the root filesystem.  This is an RPC from the
fs interface (see fs.defs).  The implementation of this
function is thus actually generated during the glibc build in
RPC_dir_lookup.c, based on the fs.defs file, using
MIG.  This generated function essentially encodes the
parameters into a data buffer, and makes a mach_msg system call to send
the buffer to the root filesystem port, with the dir_lookup RPC ID.
The root filesystem, for instance ext2fs, was sitting in its
main service loop (libdiskfs/init-first.c:master_thread_function), which
calls ports_manage_port_operations_multithread, which essentially simply
keeps making mach_msg system calls to receive messages,
and calls the demultiplexer on it, here the diskfs_demuxer.  This
demultiplexer calls the demultiplexers for the various interfaces supported by
ext2fs.  These demuxers are generated using MIG during the Hurd build.  For
instance, the fs interface demultiplexer for diskfs,
diskfs_fs_server, is in libdiskfs/fsServer.c.  It simply checks whether the
RPC ID is an fs interface ID, and if so uses the diskfs_fs_server_routines
array for calling the appropriate function corresponding to the RPC ID.  Here
it's _Xdir_lookup which thus gets called.  This one decodes the parameters
from the message data buffer, and calls diskfs_S_dir_lookup.
diskfs_S_dir_lookup in the ext2fs translator does stuff to check that the
file exists, etc. and eventually creates a new port, which will represent the
open file, and a structure to keep information about it.  It returns this new
port to its caller, _Xdir_lookup, which puts it into the reply message data
buffer and returns.  ports_manage_port_operations_multithread then calls
mach_msg to send that port to the user program.
The mach_msg call in the user program thus returns, returning the port,
decoded by dir_lookup.  glibc adds a new slot to its
file descriptor table, and records the port in it.
lseek is simpler.  The glibc implementation simply calls the __io_seek
function against the port of the file descriptor.  This is an RPC from the
?io interface (see io.defs).  As explained above, the
implementation is thus in RPC_io_seek.c, it encodes parameters and makes a
mach_msg system call to the port of the file descriptor with the io_seek
RPC ID.
In the root filesystem, it's now the demultiplexer for the io interface,
diskfs_io_server, which will recognize the RPC ID, and call _Xio_seek,
which retrieves the data structure for the port, and calls diskfs_S_io_seek.
The latter simply modifies ext2fs' internal data structure to account for the
file position change, and returns the new position.  _Xio_seek encodes the
position into the reply message, which is sent back by
ports_manage_port_operations_multithread through mach_msg.
The mach_msg call in the user program thus returns the new offset, decoded by
__io_seek.  lseek can then return it to the user application.
When hacking, one usually does not have to keep all that in mind.  All one
needs to remember (or look up) is that when the application program calls
open, the glibc implementation actually calls dir_lookup, which triggers a
call to diskfs_S_dir_lookup in the ext2fs translator.  When the application
program calls lseek, the glibc implementation calls __io_seek, which
triggers a call to diskfs_S_io_seek in the ext2fs translator.  And so on...
Questions and Answers
How do I know whether a function is an RPC or not?
Simply grep the function name (without leading underscores) in the
/usr/include/hurd/*.defs files.
Why is it a libdiskfs function that get called?
Because the filesystem serving the file, ext2fs, is libdiskfs-based (see
HURDLIBS = diskfs in ext2fs/Makefile).  Other translators are
libnetfs-based or libtrivfs-based.  grep for RPC names in those
according to what your translator is based on.
How do I know which translator the RPC gets into?
Check the type of file whose port the RPC was made on. Most files are handled by the translator which is mounted where the files are opened. Some special files are handled by particular translators:
PF_LOCAL/PF_UNIXsockets are served by pflocal, see networking;PF_INET/PF_INET6sockets are served by pfinet, see networking;- named sockets (also known as FIFOs) are served by fifo.