XML-RPC.ComUserLand
    Simple cross-platform distributed computing, based on the standards of the Internet.

Home

Spec

News

Mail List

Directory

Discuss

New Topic

HowTo

Top 50

SOAP

RSS

OPML

XML




Members
Join Now
Login

RFC: system.multicall

Previous topic
Next topic
inactiveTopic RFC: system.multicall
started 1/25/2001; 1:34:52 PM - last post 4/9/2001; 4:56:23 PM
Eric Kidd - RFC: system.multicall  blueArrow
1/25/2001; 1:34:52 PM (reads: 39386, responses: 9)
After speaking with Adrian Likins at RedHat, I've been thinking about ways to boxcar XML-RPC calls without changing the official specification.

What's "boxcarring"?

Basically, it involves packing multiple, asynchronous function calls into one big request, and shipping them all off to the server at once.

Why would anybody want to do this?

HTTP round-trip latency ranges from bad to awful. So it can be much faster to make one big request than ten little ones.

Also, some people want to use XML-RPC to script local applications. They need to perform one context-swap per request, which can really kill throughput. Again, it would be much better to make one big request than ten little ones.

Can't you do this with HTTP pipelining?

In theory, who knows? In practice, no. I spent this afternoon watching pipelined HTTP requests on the wire, and they appear to require at least one round-trip TCP packet per XML-RPC function call. If you've got a 250 millisecond ping between your sites, that means a half-second per XML-RPC call. Period.

(And if the W3C's own reference code can't do any better than this, then you can safely assume that none of us mere mortals will ever figure it out.)

But you can't change the XML-RPC specification!

I know. I don't want to patch all the clients, either. So let's look for a different solution.

The Proposal

array system.multicall(array)

Takes an array of XML-RPC calls encoded as structs of the form (in a Pythonish notation here):

{'methodName': string, 'params': array}

The array of structs may be of any length. In particular, empty lists are supported, so clients can test for the presence of the function without performing any actions.

Returns an array of responses. There will be one response for each call in the original array. The result will either be a one-item array containing the result value (this mirrors the use of <params> in <methodResponse>), or a struct of the form found inside the standard <fault> element. (Please see the example below.)

If some items in the original call array are not valid call structs (as described above), the implementation must return a struct-with-fault-information in the corresponding response position. Under no circumstances may the implementation return a list of the wrong length.

To prevent stack overflow attacks against compiled XML-RPC servers, system.multicall MAY refuse to process recursive calls to itself.

Of course, system.multicall may return a fault of its own, using the normal XML-RPC fault mechanism. This probably means it that system.multicall isn't implemented, and you'll have to send all your requests in the normal fashion.

Virtues

  • We haven't changed the XML-RPC specification.
  • We haven't required any heavy HTTP wizardry.
  • If a given XML-RPC library doesn't support this automatically, developers can provide it themselves. I'm betting this is less than twenty lines of Python.
  • Clients can test for the presence of system.multicall either by using system.listMethods or by calling system.multicall with an empty list.
  • Smart XML-RPC libraries can do all the work behind the scenes.

An Example

This example uses a Python-like notation to represent XML-RPC values. If you have any questions about what the corresponding XML looks like, please ask.

A sample argument to system.multicall:

[{'methodName': 'system.add', 'params': [2, 2]},
 {'methodName': 'test.nonexistant', 'params': [1]},
 {'methodName': 'system.multicall', 'params': []},
 {'methodName': 'system.multicall'},
 'this is not a struct',
 {'methodName': 'system.add', 'params': [4, 4]}]

The return value:

[[4],
 {'faultCode': 123,
  'faultString': 'No such method test.nonexistant'},
 {'faultCode': 456,
  'faultString': 'Recursive system.multicall forbidden'},
 {'faultCode': 789,
  'faultString': 'Missing params'},
 {'faultCode': 987,
  'faultString': 'system.multicall expected struct'},
 [8]]

Notice that regular return values are always nested inside a one-element array. This allows you to return structs from functions without confusing them with faults.

The fault codes and fault strings used in the above example are arbitrary.

Implementations

A transparent, server-side implementation of system.multicall is available in the CVS version of xmlrpc-c.

Thank you for any feedback on this proposal!

Cheers,
Eric

Eric Kidd - XML-RPC Benchmark  blueArrow
1/25/2001; 8:32:13 PM (reads: 9929, responses: 3)
Methodology

I used Python and Fredrik Lundh's xmlrpclib to prepare a 1,200 item multicall. Each item was an invocation of 'sample.add' with two arbitrary integer parameters. I dumped this call to disk and added an appropriate HTTP/1.0 header. The body of the request was 316,031 bytes long.

On the server side, I used a one-page xmlrpc-c CGI and the Apache webserver.

I sent the data to the server using 'nc', a network-aware 'cat' program from l0pht. I also used 'nc' to dump the response back to disk.

I ran the test over the loopback interface on a RedHat Linux 6.2 machine with a single 233MHz Pentium II.

Time

0.70 seconds elapsed.

This works out to slightly over 1,700 boxcarred XML-RPC calls per second on obsolete hardware.

Cheers,
Eric

Hung Jung Lu - Re: RFC: system.multicall  blueArrow
1/26/2001; 7:25:58 PM (reads: 9178, responses: 0)
Glad that someone else is thinking in the same direction. I've said this already a few times, especially about boxcarring (multiple calls, compound calls). The thing is, more and more people will start to wake up and say: heck, we've gone down the wrong path all along! The protocol is not the issue. The fact is, Parameter Structure (PS) allows you to anything you want, and more. Including boxcarring and asynchronous calls. Newbies out there keep complaining about "limitations" of XML-RPC, and that XML-RPC needs to be extended. To me, XML-RPC is too complicated already. The fact is, Parameter Structure itself can define all calling features that anybody can ever want and can ever think of. Parameter Structure is basically composed of (1) Dictionary/Associated-Array/HashMap, (2) regular List/Array, (3) datatypes like numbers, strings, base64. Parameter structure itself actually can define all the calling features. Moreover, since it is a layer on top of protocols, hooking a PS up to a protocol like XML-RPC or SOAP is easy. Which allows you a high degree of protocol-independence. Imagine you write something in XML-RPC and tomorrow everyone is using SOAP, or if you write something in SOAP and tomorrow everyone is using XXXYYYZZZ. What do you do? That's the danger of relying on specific protocols. Also, once you have some features with a protocol, there will ALWAYS be people that want some more features. ALWAYS. Look at SOAP spec and you can see the sad state of affair... it's not SOAP anymore, it's COAP (Complicated Object Access Protocol.) So, isn't it clear that protocols are not the way to go? Why not build calling features on a higher layer like the PS, and achieve standardization there? Anyway, all this is kind of ahead of time, but more and more people will wake up soon. Soon enough. PS is just a simpler and better design pattern. Move the complicated, vendor-specific things into PS, and keep the protocol simple. As I said, more and more people will wake up and say: heck, why didn't I think of that before?

Dave Winer - Subscription and notification in C?  blueArrow
1/27/2001; 10:46:29 AM (reads: 13433, responses: 2)
Eric, first thanks for all you're doing for XML-RPC. It's truly awesome.

I've been busy fighting fires for the last few days but observing your fast progress.

It seems like you're looking for cool sexy projects to do with XML-RPC that take advantage of the performance you can get from writing a server in C.

If so, I have one, and it could help us scale up a process that needs scaling, already, we now have a small fraction of the users we will eventually have for this service, and our Frontier-based "cloud" is already having trouble keeping up with them.

Here's the scenario 

I am the author of a resource. It could be an XML file (in our case it is) or a GIF or a MP3, or whatever, it doesn't matter.

The resource has a URL. (Of course.)

My content system wants to register this resource with a "cloud".

boolean iAmAResource (url)

The cloud returns true if it was able to add it to the database, false otherwise. It takes note of the IP address of the sender and stores it in the database. It makes sure that the URL points to a resource on that machine. (You can't register a resource that lives elsewhere. Other restrictions might be necessary to preclude easy DOS attacks.)

Now it gets more interesting.

I am a user of that resource 

I send a message to the cloud saying:

boolean pleaseNotify (notifyProcedure, port, path, protocol, urllist)

The first three parameters identify a handler running on my machine.

The fourth parameter says what protocol to use. For your app it would always be "xml-rpc". (Other possible values are "soap" and "http-post".)

The fifth param is an <array> of strings containing the URLs that you would like to receive notification on.

Again the IP address is associated with the request, and notifications only go to that machine. You can not dupe the cloud into spamming someone else.

Back to the resource owner

Periodically it sends a message to the cloud asking it to:

array tellMeWhoSubscribed (url)

The cloud sends back an <array> of <struct>s containing information about each of the subscribers.

The name of the struct is the IP address of the user of the resource.

Inside the struct are the first four params to pleaseNotify.

From there, when the resource changes, the author's agent (in our case Radio) sends notification events to each of the subscribers.

Why in C? 

Because it gets complicated when the second cloud comes into the mix. We want to postpone that as far into the future as possible. Also, we're not that rich and we want to save money.

Background is here..

http://www.thetwowayweb.com/stories/storyReader$20

What do you think?

Dave

Eric Kidd - Re: Subscription and notification in C?  blueArrow
1/27/2001; 6:21:57 PM (reads: 12546, responses: 0)
What do you think?

I think I get it! The cloud is essentially passive--it keeps track of who's subscribed to what, but doesn't do any content delivery or crawling.

Very interesting. I need to think about this. :-)

Cheers,
Eric

Brad Pettit - Re: Subscription and notification in C?  blueArrow
1/30/2001; 2:12:43 PM (reads: 12018, responses: 0)
Have you considered using UPnP for this API? Don't let the name (Universal Plug 'n Play) fool you. Your description of registration, resource availability notification, and querying a cloud for who/what is present -- using XML -- is all covered.

http://www.upnp.org/
http://www.microsoft.com/hwdev/upnp/ <---SDK

Dave Winer - Re: RFC: system.multicall  blueArrow
4/9/2001; 9:38:49 AM (reads: 9120, responses: 1)
Eric, thanks for posting the spec for system.multiCall. We could implement it as-is in Frontier/Radio, but it would require restructuring our server code. I would like to see if it would be possible for us to not have to do that.

Basically, we have a single entry-point, betty.rpc.server, that handles all incoming XML-RPC messages.

on server (xmlText, adrParamTable)

As you can see it requires the XML text, basically the body of the HTTP-POST. The second parameter, adrParamTable points to something unrelated to the XML-RPC request.

So, in retrospect we would have preferred if system.multicall were to receive an array of XML serializations of procedure calls, and returned an array of XML-serialized responses.

Also note that Radio is available as a free download if anyone wants to help with this (and other) work.

Eric Kidd - Re: RFC: system.multicall  blueArrow
4/9/2001; 10:47:48 AM (reads: 9971, responses: 0)
Eric, thanks for posting the spec for system.multiCall. We could implement it as-is in Frontier/Radio, but it would require restructuring our server code. I would like to see if it would be possible for us to not have to do that.

Avoiding restructuring is definitely good. :-)

So, in retrospect we would have preferred if system.multicall were to receive an array of XML serializations of procedure calls, and returned an array of XML-serialized responses.

This would be easy to do in Python and Perl. It would require significant (but isolated) engineering effort in C. (I'd have to upgrade all three of these libraries myself.) I don't know which approach would be easier in Java.

My gut feeling: 'system.multicall' isn't worth major engineering investment until your users start complaining about latency from lots of little requests. It's there if you need it--and already supported in three languages--but please don't feel obliged to implement it. After all, applications which use system.multicall should know how to fall back to using separate calls if necessary.

Cheers,
Eric

Eric Kidd - system.multicall update & test suite  blueArrow
4/9/2001; 12:11:12 PM (reads: 9356, responses: 1)
I've updated the system.multicall RFC to include an example and some clarifications.

You can also find a test suite at the XML-RPC Hacks page.

Hope this helps!

Cheers,
Eric

Dave Winer - Re: system.multicall update & test suite  blueArrow
4/9/2001; 4:56:23 PM (reads: 10069, responses: 0)
I believe we got the Frontier implementation to work.

How about that! I ran some Python code.

© Copyright 2004-2006 Scripting News, Inc.
© Copyright 1998-2004 UserLand Software, Inc.
XML-RPC is a trademark of UserLand Software, Inc.
Last update: Monday, April 9, 2001 at 4:56:23 PM Pacific.

Create your own Manila site in minutes. Everyone's doing it!