在Python的gevent框架下执行异步的Solr查询的教程
我经常需要用Python与solr进行异步请求工作。这里有段代码阻塞在Solrhttp请求上,直到第一个完成才会执行第二个请求,代码如下:
importrequests #Search1 solrResp=requests.get('http://mysolr.com/solr/statedecoded/search?q=law') fordocinsolrResp.json()['response']['docs']: printdoc['catch_line'] #Search2 solrResp=requests.get('http://mysolr.com/solr/statedecoded/search?q=shoplifting') fordocinsolrResp.json()['response']['docs']: printdoc['catch_line']
(我们用Requests库进行http请求)
通过脚本把文档索引到Solr,进而可以并行工作是很好的。我需要扩展我的工作,因此索引瓶颈是Solr,而不是网络请求。
不幸的是,当进行异步编程时python不像Javascript或Go那样方便。但是,gevent库能给我们带来些帮助。gevent底层用的是libevent库,构建于原生异步调用(select,poll等原始异步调用),libevent很好的协调很多低层的异步功能。
使用gevent很简单,让人纠结的一点就是thegevent.monkey.patch_all(),为更好的与gevent的异步协作,它修补了很多标准库。听起来很恐怖,但是我还没有在使用这个补丁实现时遇到问题。
事不宜迟,下面就是你如果用gevents来并行Solr请求:
importrequests fromgeventimportmonkey importgevent monkey.patch_all() classSearcher(object): """Simplewrapperfordoingasearchandcollectingthe results""" def__init__(self,searchUrl): self.searchUrl=searchUrl defsearch(self): solrResp=requests.get(self.searchUrl) self.docs=solrResp.json()['response']['docs'] defsearchMultiple(urls): """Usegeventtoexecutethepassedinurls; dumptheresults""" searchers=[Searcher(url)forurlinurls] #Gatherahandleforeachtask handles=[] forsearcherinsearchers: handles.append(gevent.spawn(searcher.search)) #Blockuntilallworkisdone gevent.joinall(handles) #Dumptheresults forsearcherinsearchers: print"SearchResultsfor%s"%searcher.searchUrl fordocinsearcher.docs: printdoc['catch_line'] searchUrls=['http://mysolr.com/solr/statedecoded/search?q=law', 'http://mysolr.com/solr/statedecoded/search?q=shoplifting']
searchMultiple(searchUrls)
代码增加了,而且不如相同功能的Javascript代码简洁,但是它能完成相应的工作,代码的精髓是下面几行:
#Gatherahandleforeachtask handles=[] forsearcherinsearchers: handles.append(gevent.spawn(searcher.search)) #Blockuntilallworkisdone gevent.joinall(handles)
我们让gevent产生searcher.search,我们可以对产生的任务进行操作,然后我们可以随意的等着所有产生的任务完成,最后导出结果。
差不多就这样子.如果你有任何想法请给我们留言。让我们知道我们如何能为你的Solr搜索应用提供帮助。