Credit: Graham Dumpleton
You need to allow some distributed services to supply methods, and other distributed services to access and use those methods, in a location-independent way by writing a suitable central exchange (middleware) server.
The OSE package also supports the request/reply architecture. First, we need a central middleware process to which all others connect:
# The central.py script -- needs the OSE package from http://ose.sourceforge.net import netsvc import signal dispatcher = netsvc.Dispatcher( ) dispatcher.monitor(signal.SIGINT) exchange = netsvc.Exchange(netsvc.EXCHANGE_SERVER) exchange.listen(11111) dispatcher.run( )
Next, we need a server that supplies methods through the middleware:
# The server.py script -- needs the OSE package from http://ose.sourceforge.net import netsvc import signal class Service(netsvc.Service): def _ _init_ _(self): netsvc.Service._ _init_ _(self, "math") self.joinGroup("web-services") self.exportMethod(self.multiply) def multiply(self, x, y): return x*y dispatcher = netsvc.Dispatcher( ) dispatcher.monitor(signal.SIGINT) exchange = netsvc.Exchange(netsvc.EXCHANGE_CLIENT) exchange.connect("localhost",11111,5) service = Service( ) dispatcher.run( )
Then, we need a client that consumes methods through the middleware:
# The client.py script -- needs the OSE package from http://ose.sourceforge.net import netsvc import signal import random class Client(netsvc.Service): def _ _init_ _(self): netsvc.Service._ _init_ _(self, "") self.startTimer(self.call, 1, "1") def call(self,name): service = self.serviceEndPoint("math") if service != None: x = int(random.random( )*1000) id = service.multiply(x, x) self.monitorResponse(self.result, id) self.startTimer(self.call, 1, "1") def result(self,square): print square dispatcher = netsvc.Dispatcher( ) dispatcher.monitor(signal.SIGINT) exchange = netsvc.Exchange(netsvc.EXCHANGE_CLIENT) exchange.connect("localhost", 11111, 5) client = Client( ) dispatcher.run( )
We can also write a gateway exposing an XML-RPC service for the same methods:
# The gateway.py script -- needs the OSE package from http://ose.sourceforge.net import signal import netsvc import netsvc.xmlrpc dispatcher = netsvc.Dispatcher( ) dispatcher.monitor(signal.SIGINT) httpd = netsvc.HttpDaemon(8000) rpcgw = netsvc.xmlrpc.RpcGateway("web-services") httpd.attach("/xmlrpc/service", rpcgw) httpd.start( ) exchange = netsvc.Exchange(netsvc.EXCHANGE_CLIENT) exchange.connect("localhost", 11111, 5) dispatcher.run( )
This recipe is a simple example of setting up a distributed message-oriented request/reply architecture. It shows the creation of a central exchange service that all participating processes connect to. Services assign themselves a name and export the methods that are remotely accessible. Client services can then make calls against the exported methods.
This recipe provides an alternative to systems dependent on XML-RPC and SOAP, which only create connections to other processes when required. In this architecture, the processes are always connected through the central exchange process, avoiding the cost of setting up and ripping down the socket connections for each request. That said, an XML-RPC or SOAP gateway can also be connected to the system to allow similar remote access using the HTTP protocol. Although each service is shown in a separate process, they could just as well be in the same process, as the means of communication is the same. The services shown may also publish data, which other services can subscribe to if required, as shown in Recipe 13.8.
The
central.py
script is the same as in Recipe 13.8, which
highlights how the central middleware in OSE architectures is
independent from the contents of the application and can offer both
publish/subscribe and request/reply mediation. The
server.py
script defines a subclass of Service
and calls the
joinGroup
and exportMethod
methods, which we already examined in Recipe 13.5. The
client.py
script uses Service
’s
startTimer
method for periodic invocation of its
own call
method. This method in turn uses
serviceEndPoint
to access the specific service
named 'math'
, calls the
multiply
method on the latter, and calls
monitorResponse
to get its own method
result
called back when the server responds with a
result.
The
gateway.py
script shows how OSE lets you use the same infrastructure to expose
the same services via the Web, as we already illustrated in
Recipe 13.5.
Recipe 13.5; Recipe 13.8 describes a different feature of the OSE package; the OSE package (http://ose.sourceforge.net).
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.