我正在使用tor非典(和第三方tornadows模块)实现一个SOAP web服务。我服务中的一个操作需要调用另一个操作,所以我有了链:
因为它都在一个服务中运行,所以它在某个地方被阻塞了。我不熟悉龙卷风的异步功能。
只有一个请求处理方法(post),因为所有内容都来自单个url,然后根据SOAPAction请求头值调用特定的操作(进行处理的方法)。我用@tornado.web.asynchronous修饰了post方法,最后调用了self.finish(),但是没有骰子。
龙卷风能处理这个场景吗?如果是的话,我如何实现它?
编辑(添加代码):
class SoapHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def post(self):
""" Method post() to process of requests and responses SOAP messages """
try:
self._request = self._parseSoap(self.request.body)
soapaction = self.request.headers['SOAPAction'].replace('"','')
self.set_header('Content-Type','text/xml')
for operations in dir(self):
operation = getattr(self,operations)
method = ''
if callable(operation) and hasattr(operation,'_is_operation'):
num_methods = self._countOperations()
if hasattr(operation,'_operation') and soapaction.endswith(getattr(operation,'_operation')) and num_methods > 1:
method = getattr(operation,'_operation')
self._response = self._executeOperation(operation,method=method)
break
elif num_methods == 1:
self._response = self._executeOperation(operation,method='')
break
soapmsg = self._response.getSoap().toprettyxml()
self.write(soapmsg)
self.finish()
except Exception as detail:
#traceback.print_exc(file=sys.stdout)
wsdl_nameservice = self.request.uri.replace('/','').replace('?wsdl','').replace('?WSDL','')
fault = soapfault('Error in web service : {fault}'.format(fault=detail), wsdl_nameservice)
self.write(fault.getSoap().toxml())
self.finish()
这是来自请求处理程序的post方法。它来自我使用的web服务模块(不是我的代码),但是我添加了异步装饰器和self.finish()。它所做的基本工作就是调用正确的操作(如请求的SOAPAction中所指示的)。
class CountryService(soaphandler.SoapHandler):
@webservice(_params=GetCurrencyRequest, _returns=GetCurrencyResponse)
def get_currency(self, input):
result = db_query(input.country, 'currency')
get_currency_response = GetCurrencyResponse()
get_currency_response.currency = result
headers = None
return headers, get_currency_response
@webservice(_params=GetTempRequest, _returns=GetTempResponse)
def get_temp(self, input):
get_temp_response = GetTempResponse()
curr = self.make_curr_request(input.country)
get_temp_response.temp = curr
headers = None
return headers, get_temp_response
def make_curr_request(self, country):
soap_request = """<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:coun='CountryService'>
<soapenv:Header/>
<soapenv:Body>
<coun:GetCurrencyRequestget_currency>
<country>{0}</country>
</coun:GetCurrencyRequestget_currency>
</soapenv:Body>
</soapenv:Envelope>""".format(country)
headers = {'Content-Type': 'text/xml;charset=UTF-8', 'SOAPAction': '"http://localhost:8080/CountryService/get_currency"'}
r = requests.post('http://localhost:8080/CountryService', data=soap_request, headers=headers)
try:
tree = etree.fromstring(r.content)
currency = tree.xpath('//currency')
message = currency[0].text
except:
message = "Failure"
return message
这是web服务(get_currency & get_temp)的两个操作。所以SOAPUI点击get_temp,它向get_currency发出SOAP请求(通过make_curr_request和请求模块)。然后,结果应该被链式回发,并被发送回SOAPUI。
服务的实际操作是没有意义的(当询问温度时返回货币),但我只是想让功能正常工作,这就是我所拥有的操作。
发布于 2013-02-01 09:31:43
我不认为您的soap模块或请求是异步的。
我相信添加“异步装饰师”只是战斗的一半。现在,您没有在函数内部发出任何异步请求(每个请求都是阻塞的,这会将服务器绑定到方法完成为止)。
您可以通过使用tornados AsynHttpClient来切换。这几乎可以用作请求的准确替代。来自docoumentation示例:
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
http = tornado.httpclient.AsyncHTTPClient()
http.fetch("http://friendfeed-api.com/v2/feed/bret",
callback=self.on_response)
def on_response(self, response):
if response.error: raise tornado.web.HTTPError(500)
json = tornado.escape.json_decode(response.body)
self.write("Fetched " + str(len(json["entries"])) + " entries "
"from the FriendFeed API")
self.finish()
他们的方法是用异步来修饰的,他们正在发出asyn请求。这就是水流变得有点奇怪的地方。当您使用AsyncHttpClient时,它不会锁定事件循环(PLease我本周才开始使用龙卷风,如果我的所有术语都不正确的话,请放心)。这允许服务器自由地处理传入的请求。当您的异步请求完成后,将执行回调方法,在本例中是on_response
。
在这里,您可以很容易地用tornado客户机替换请求。然而,对于soap服务来说,事情可能要复杂得多。您可以围绕您的soap客户端进行本地the序列化,并使用tornado http客户端向其发出异步请求?
这将创建一些复杂的回调逻辑,可以使用 decorator进行修复。
发布于 2014-12-29 13:56:28
这个问题从昨天起就开始发行了。
请求:https://github.com/rancavil/tornado-webservices/pull/23
示例:这里是一个简单的webservice,它不接受参数并返回版本。注意你应该:
@gen.coroutine
装饰方法raise gen.Return(data)
代码:
from tornado import gen
from tornadows.soaphandler import SoapHandler
...
class Example(SoapHandler):
@gen.coroutine
@webservice(_params=None, _returns=Version)
def Version(self):
_version = Version()
# async stuff here, let's suppose you ask other rest service or resource for the version details.
# ...
# returns the result.
raise gen.Return(_version)
干杯!
https://stackoverflow.com/questions/14586038
复制相似问题