나는 항상 gevent 기반 크롤러 다운로드 페이지를 가지고 있습니다.크롤러는 생산자-소비자 패턴을 채택합니다. 이 패턴은 {method:get, url:xxxx, other_info:yyyy}와 같은 데이터를 대기열에 제공합니다.
이제 일부 응답을 파일로 모으고 싶습니다.문제는 모든 요청이 끝나면 그냥 열고 쓸 수 없다는 것입니다. 비용이 많이 들고 데이터의 순서가 정확하지 않습니다.
나는 모든 요청에 번호를 매기고, 응답을 순서대로 캐시하고, 파일을 반복하고 조립하기 위해 Greenlet을 열어야 한다고 가정합니다. 의사 코드는 다음과 같습니다.
max_chunk=1000
data=[]
def wait_and_assemble_file(): # a loop
while True:
if len(data)==28:
f= open('test.txt','a')
for d in data:
f.write(d)
f.close()
gevent.sleep(0)
def after_request(response, index): # Execute after every request ends
data[index]=response # every response is about 5-25k
더 나은 해결책이 있습니까?수천 개의 동시 요청이 있으며 메모리 사용이 너무 빨리 증가하거나 한 번에 너무 많은 루프가 발생하거나 예상치 못한 일이 발생할 수 있는지 의심됩니다.
업데이트:
위의 코드는 데이터 캐싱 및 파일 쓰기가 어떻게 수행되는지 보여줍니다.실제 상황에서는 캐싱이 완료되기를 기다리고 다른 파일에 쓰기 위해 100번의 루프가 실행될 수 있습니다.
업데이트2
@IT Ninja는 대기열 시스템 사용을 제안하므로 Redis를 사용하여 대안을 작성합니다.
def after_request(response, session_id, total_block_count ,index): # Execute after every request ends
redis.lpush(session_id, msgpack.packb({'index':index, 'content':response})) # save data to redid
redis.incr(session_id+':count')
if redis.get(session_id+':count') == total_block_count: # which means all data blocks are prepared
save(session_name)
def save(session_name):
data_array=[]
texts = redis.lrange(session_name,0,-1)
redis.delete(session_name)
redis.delete(session_name+':count')
for t in texts:
_d = msgpack.unpackb(t)
index = _d['index']
content = _d['content']
data_array[index]=content
r= open(session_name+'.txt','w')
[r.write(i) for i in data_array]
r.close()
조금 더 좋아 보이지만 Redis에 대용량 데이터를 저장하는 것이 좋은 생각인지 의심스럽습니다. 더 많은 제안을 바랍니다!