2012-11-23 14 views
7

SocketServer.ThreadingMixin kullanan bir SimpleXMLRPCServers zinciri kullanırken aralıklı olarak bir httplib.CannotSendRequest özel durumu alıyorum.python: iş parçacığı oluştururken httplib.CannotSendRequest SimpleXMLRPCServers

Bir SimpleXMLRPCServer bir işlevi çağırmak için xmlrpclib kullanan bir istemci komut dosyası vardır: Ben 'zincir' kastım

şudur. Bu sunucu, sırayla başka bir SimpleXMLRPCServer çağırır. Kulağa ne kadar sarsıldığının farkındayım, ama bu mimarinin seçilmesinin iyi nedenleri var ve bunun mümkün olmaması için bir neden göremiyorum. Ben SocketServer.ThreadingMixin kullanmazsanız

(testclient)client_script ---calls--> 
    (middleserver)SimpleXMLRPCServer ---calls---> 
     (finalserver)SimpleXMLRPCServer --- does something 
  • sonra bu sorun oluşmaz (ama yani bu yardımcı olmuyor çok kanallı olması isteklerini gerekir.) Ben sadece varsa
  • Tek bir hizmet seviyesi (yani, doğrudan sunucuya doğrudan son çağrı yapan müşteri komut dosyası) bu gerçekleşmez.

Sorunu aşağıdaki basit test kodunda yeniden üretebiliyorum. Üç parçacıkları vardır:

finalserver:

import SocketServer 
import time 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 

class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 

# Create server 
server = AsyncXMLRPCServer(('', 9999), SimpleXMLRPCRequestHandler) 
server.register_introspection_functions() 

def waste_time(): 
    time.sleep(10) 
    return True 

server.register_function(waste_time, 'waste_time') 
server.serve_forever() 

middleserver:

import SocketServer 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 
import xmlrpclib 

class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 

# Create server 
server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler) 
server.register_introspection_functions() 

s = xmlrpclib.ServerProxy('http://localhost:9999') 
def call_waste(): 
    s.waste_time() 
    return True 

server.register_function(call_waste, 'call_waste') 
server.serve_forever() 

Testclient:

import xmlrpclib 
s = xmlrpclib.ServerProxy('http://localhost:8888') 
print s.call_waste() 

yeniden oluşturmak için aşağıdaki adımlar kullanılmalıdır:

  1. Çalıştır piton finalserver.py
  2. Çalıştır piton middleserver.py
  3. Çalıştır piton testclient.py
  4. (3) hala, piton testclient.py başka bir örneğini

Oldukça çalıştırmak çalışırken

  • iken Genellikle (hemen hemen her zaman), 4. adımı çalıştırmayı denediğinizde ilk hatanın altına düşersiniz. İlginçtir, hemen (4) adımını çalıştırmayı denerseniz, hata oluşmaz.

    Traceback (most recent call last): 
        File "testclient.py", line 6, in <module> 
        print s.call_waste() 
        File "/usr/lib64/python2.7/xmlrpclib.py", line 1224, in __call__ 
        return self.__send(self.__name, args) 
        File "/usr/lib64/python2.7/xmlrpclib.py", line 1578, in __request 
        verbose=self.__verbose 
        File "/usr/lib64/python2.7/xmlrpclib.py", line 1264, in request 
        return self.single_request(host, handler, request_body, verbose) 
        File "/usr/lib64/python2.7/xmlrpclib.py", line 1297, in single_request 
        return self.parse_response(response) 
        File "/usr/lib64/python2.7/xmlrpclib.py", line 1473, in parse_response 
        return u.close() 
        File "/usr/lib64/python2.7/xmlrpclib.py", line 793, in close 
        raise Fault(**self._stack[0]) 
    xmlrpclib.Fault: <Fault 1: "<class 'httplib.CannotSendRequest'>:"> 
    

    internet bu istisna GetResponse çağrıları müdahale etmeden httplib.HTTPConnection.request için birden aramaların neden olabilir söylemek görünmektedir. Ancak, internet bunu SimpleXMLRPCServer bağlamında tartışmıyor. Httplib.CannotSendRequest sorununu çözme yönünde herhangi bir işaretçi takdir edilecektir.

    ================================= YANIT:

    Tamam, biraz aptalım. Ben çok uzun bir süre için kod dik dik baktığımı düşünüyorum bir süre içinde yüzüne dik dik bakıyordu açık çözüm özledim (gerçekten tam anlamıyla, gerçek soru yanıttır.)

    Temel olarak, CannotSendRequest oluşur Bir httplib.HTTPConnection araya giren bir 'istek' işlemi tarafından kesintiye uğradığında.Her bir httplib.HTTPConnection.request bir .getresponse() çağrısı ile eşleştirilmelidir. Bu eşleştirme başka bir istek işlemiyle kesintiye uğrarsa, ikinci istek CannotSendRequest hatasını üretecektir. Bu nedenle, herhangi bir yanıt verilmeden önce aynı bağlantıda iki isteğiniz olduğundan, başarısız olacaktır. Böyle bağlantıları yapılıyor üç programlarında

    1. tek yer serverproxy çağrılarında şunlardır: Sorumun Sözünü geri Bağlama

      .

    2. Sorun yalnızca iş parçacığı sırasında ortaya çıkıyor, bu nedenle büyük olasılıkla bir yarış durumu. Bir serverproxy çağrı paylaşılır
    3. tek yer, çözelti daha sonra middleserver.py

    olduğu her iş parçacığı kendi serverproxy var oluşturmasını sağlamak için belli ki. middleserver sabit versiyonu altında ve çalışır: kendi xmlrpclib.serverproxy sahip her dizisindeki bu sürüm sonuçları yana

    import SocketServer 
    from SimpleXMLRPCServer import SimpleXMLRPCServer 
    from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 
    import xmlrpclib 
    
    class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 
    
    # Create server 
    server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler) 
    server.register_introspection_functions() 
    
    def call_waste(): 
        # Each call to this function creates its own serverproxy. 
        # If this function is called by concurrent threads, each thread 
        # will safely have its own serverproxy. 
        s = xmlrpclib.ServerProxy('http://localhost:9999') 
        s.waste_time() 
        return True 
    
    server.register_function(call_waste, 'call_waste') 
    server.serve_forever() 
    

    , serverproxy ait çağırma aynı örneğinin riski HTTPConnection.request fazlası var art arda bir kez. Programlar amaçlandığı gibi çalışır.

    Rahatsız ettiğim için özür dilerim.

  • cevap

    11

    Tamam, biraz aptalım. Ben yüzüme bakıyordu bariz çözüm cevapsız bir süre uzun süren etmek için kod bakıyordu düşünüyorum (cevap fiili söz konusu aslında, çünkü tam anlamıyla.)

    Temelde, CannotSendRequest oluşur Bir httplib.HTTPConnection araya giren bir 'istek' işlemi tarafından kesintiye uğradığında. Temel olarak, her bir httplib.HTTPConnection.request bir .getresponse() çağrısı ile eşleştirilmelidir. Bu eşleştirme başka bir istek işlemiyle kesintiye uğrarsa, ikinci istek CannotSendRequest hatasını üretecektir. Bu nedenle, herhangi bir yanıt verilmeden önce aynı bağlantıda iki isteğiniz olduğundan, başarısız olacaktır. Böyle bağlantıları yapılıyor üç programlarında

    1. tek yer serverproxy çağrılarında şunlardır: Sorumun Sözünü geri Bağlama

      .

    2. Sorun yalnızca iş parçacığı sırasında ortaya çıkıyor, bu nedenle büyük olasılıkla bir yarış durumu. Bir serverproxy çağrı paylaşılır
    3. tek yer, çözelti daha sonra middleserver.py

    olduğu her iş parçacığı kendi serverproxy var oluşturmasını sağlamak için belli ki. middleserver sabit versiyonu altında ve çalışır:

    kendi xmlrpclib.serverproxy sahip her dizisindeki bu sürüm sonuçları yana
    import SocketServer 
    from SimpleXMLRPCServer import SimpleXMLRPCServer 
    from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 
    import xmlrpclib 
    
    class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 
    
    # Create server 
    server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler) 
    server.register_introspection_functions() 
    
    def call_waste(): 
        # Each call to this function creates its own serverproxy. 
        # If this function is called by concurrent threads, each thread 
        # will safely have its own serverproxy. 
        s = xmlrpclib.ServerProxy('http://localhost:9999') 
        s.waste_time() 
        return True 
    
    server.register_function(call_waste, 'call_waste') 
    server.serve_forever() 
    

    , yürütmesini serverproxy HTTPConnection.request kez arka arkaya birden fazla riski yoktur. Programlar amaçlandığı gibi çalışır.

    Rahatsız ettiğim için özür dilerim.

    İlgili konular