Foundations of Python Network Programming

(WallPaper) #1

Chapter 18 ■ rpC


346


The fact that RPyC works successfully like this against vanilla Python functions and objects, without any
requirement that they inherit from or mix in any special network capabilities, is an incredible testament to the power
that Python gives us to intercept operations performed on an object and handle those events in our own way—even
by asking a question across the network!


RPC, Web Frameworks, and Message Queues

Be willing to explore alternative transmission mechanisms for your work with RPC services. The classes provided in
the Python Standard Library for XML-RPC, for example, are not even used by many Python programmers who need
to speak that protocol. After all, one often deploys an RPC service as part of a larger web site, and having to run a
separate server on a separate port for this particular type of web request can be quite annoying.
There are three useful ways you can look into moving beyond overly simple example code that makes it look as
though you have to bring up a new web server for every RPC service you want to make available from a particular site.
First, look into whether you can use the pluggability of WSGI to let you install an RPC service that you have
incorporated into a larger web project you are deploying. Implementing both your normal web application and your
RPC service as WSGI servers beneath a filter that checks the incoming URL enables you to allow both services to live
at the same hostname and port number. It also lets you take advantage of the fact that your WSGI web server might
already provide threading and scalability at a level the RPC service itself does not provide natively.
Putting your RPC service at the bottom of a larger WSGI stack can also gives you a way to add authentication if
the RPC service itself lacks such a facility. See Chapter 11 for more information about WSGI.
Second, instead of using a dedicated RPC library, you may find that your web framework of choice already
knows how to host an XML-RPC, JSON-RPC, or some other flavor of RPC call. This means that you can declare RPC
endpoints with the same ease that your web framework lets you define views or RESTful resources. Consult your web
framework documentation and do a web search for RPC-friendly third-party plug-ins.
Third, you might want to try sending RPC messages over an alternate transport that does a better job than the
protocol’s native transport of routing the calls to servers that are ready to handle them. Message queues, which were
discussed in Chapter 8, are often an excellent vehicle for RPC calls when you want a whole rack of servers to stay busy
sharing the load of incoming requests.


Recovering from Network Errors

Of course, there is one reality of life on the network that RPC services cannot easily hide: the network can be down
when you attempt to initiate a call, or it can even go down in the middle of a particular RPC call.
You will find that most RPC mechanisms simply raise an exception if a call is interrupted and does not complete.
Note that an error, unfortunately, is no guarantee that the remote end did not process the request—maybe it actually
did finish processing it, but then the network went down right as the last packet of the reply was being sent. In this
case, your call would have technically occurred, and the data would have been successfully added to the database or
written to a file or whatever the RPC call does. However, you will think the call failed and want to try it again—possibly
storing the same data twice. Fortunately, there are a few tricks you can use when writing code that delegate some
function calls across the network.
First, try to write services that offer idempotent operations that can safely be retried. Although an operation
like “remove $10 from my bank account” is inherently unsafe, because retrying it might remove another $10 from
your account, an operation like “perform transaction 583812 which removes $10 from my account” is perfectly safe
because the server can, by storing the transaction number, determine that your request is actually a repeat and can
report success without actually repeating the deduction.
Second, take the advice offered in Chapter 5: instead of littering your code with a try...except everywhere that
an RPC call is made, try using try and except to wrap larger pieces of code that have a solid semantic meaning and
can more cleanly be reattempted or recovered from. If you guard each and every call with an exception handler, you
will have lost most of the benefit of RPC: your code is supposed to be convenient to write and not make you constantly
attend to the fact that function calls are actually being forwarded over the network! In cases where you decide that

Free download pdf