文章发布时间:2009/4/10/3/21
Python
多线程XML-RPC的实现
一、
引言
用Python的SimpleXMLRPCServer实现的XML-RPC服务器只能是单线程,一个一个的处理请求,对于操作中耗时较长的操作会阻塞其他用户请求,使服务质量下降,因此有没有办法让SimpleXMLRPCServer成为多线程服务器呢?
主要有两种实现方法:修改SimpleXMLRPCServer的实现代码,用ThreadingMixIn或
ForkingMixIn。
二、
修改SimpleXMLRPCServer的实现代码
SimpleXMLRPCServer的实现如下:
class SimpleXMLRPCServer(SocketServer.TCPServer,
SimpleXMLRPCDispatcher):
如果我们将其继承的SocketServer.TCPServer,改为支持线程处理的ThreadingTCPServer,即可将SimpleXMLRPCServer变成多线程的服务器,如下:
class SimpleXMLRPCServer(SocketServer.ThreadingTCPServer,
SimpleXMLRPCDispatcher):
三、
用ThreadingMixIn实现
SocketServer模块中就支持对线程(Threading)或进程(Fork)的支持,典型代码如下:
import
SimpleXMLRPCServer
,
SocketServer
import
win32api
,
thread
#The server object
class
Server
:
count
=
0
def
__init__
(
self
):
pass
def
echoString
(
self
,
strs
):
mutex
.
acquire
()
#用mutex锁住数据
Server
.
count
+=
1
#更改静态数据
t
=
time
.
strftime
(
"Serve at %I:%M:%S Id is "
)
+
str
(
Server
.
count
)
print
"Serve Id "
+
str
(
Server
.
count
)
mutex
.
release
()
#释放锁
#win32api.Sleep(20000)
return
t
#多线程实现
class
RPCThreading
(
SocketServer
.
ThreadingMixIn
,
SimpleXMLRPCServer
.
SimpleXMLRPCServer
):
pass
global
mutex
mutex
=
thread
.
allocate_lock
()
server_object
=
Server
()
server
=
RPCThreading
((
"localhost"
,
8888
))
server
.
register_instance
(
server_object
)
#Go into the main listener loop
print
"Listening on 8888"
server
.
serve_forever
()
|
通过上面的代码也可以实现XML-RPC的多线程支持而不用修改Python的
SimpleXMLRPCServer库。
转:下面顺便转个压缩发送的:
compression.
(Disclaimer : I'm not a python expert in any way, just sharing...)
xmlrpc is great, easy, dynamic but is not effecient as binary
methods (see "The Python Web services developer: Messaging technologies
compared" at
http://www.ibm.com/developerworks/library/ws-pyth9/).
For example, it can take minutes to transfer 100MB of data between client and server.
Therefore, I added compression, using
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/355486.
This shortened the transfer time to 15 seconds. Example server
function (returns an arbitrary chunk of bytes, possibly with random
values):
from
array
import
array
from
random
import
randint
import
zlib
,
base64
def
get_data
(
self
,
default_byte_value
=
0x00
,
num_bytes
=
1024
,
use_rand
=
False
):
data
=
array
(
'B'
,
[
default_byte_value
]
*
num_bytes
)
if
(
use_rand
):
for
i
in
range
(
num_bytes
):
data
[
i
]
=
randint
(
0
,
255
)
data
,
csum
=
asciiCompress
(
buffer
(
data
))
return
data
Example client side (request a 1MB chunk of bytes using 0x11 as default value for each byte (non random)).
data
=
server
.
get_data
(
0x11
,
1
*
10
**
6
,
False
)
data
,
csum
=
asciiDecompress
(
data
)
arr
=
array
(
'B'
,
data
)
Note that we originate from a python array at the server and end up with an array at the client.
Just my 2 cents :)
compression. (Disclaimer : I'm not a python expert in any way, just sharing...)
xmlrpc is great, easy, dynamic but is not effecient as binary methods (see "The Python Web services developer: Messaging technologies compared" at http://www.ibm.com/developerworks/library/ws-pyth9/).
For example, it can take minutes to transfer 100MB of data between client and server.
Therefore, I added compression, using http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/355486.
This shortened the transfer time to 15 seconds. Example server function (returns an arbitrary chunk of bytes, possibly with random values):
from random import randint
import zlib , base64
def get_data ( self , default_byte_value = 0x00 , num_bytes = 1024 , use_rand = False ):
data = array ( 'B' , [ default_byte_value ] * num_bytes )
if ( use_rand ):
for i in range ( num_bytes ):
data [ i ] = randint ( 0 , 255 )
data , csum = asciiCompress ( buffer ( data ))
return data
Example client side (request a 1MB chunk of bytes using 0x11 as default value for each byte (non random)).
data , csum = asciiDecompress ( data )
arr = array ( 'B' , data )
Note that we originate from a python array at the server and end up with an array at the client.
Just my 2 cents :)