문제

Linux에서 Django를 실행하고 있으며보기가 있다고 가정하고 해당보기가 호출되는 하위 프로세스의 데이터를 반환하기를 원합니다. CMD 예를 들어 뷰가 생성하는 파일에서 작동합니다 (예 : likeso).

 def call_subprocess(request):
     response = HttpResponse()

     with tempfile.NamedTemporaryFile("W") as f:
         f.write(request.GET['data']) # i.e. some data

     # cmd operates on fname and returns output
     p = subprocess.Popen(["cmd", f.name], 
                   stdout=subprocess.PIPE, 
                   stderr=subprocess.PIPE)

     out, err = p.communicate()

     response.write(p.out) # would be text/plain...
     return response

이제 가정 해 CMD 시작 시간은 매우 느리지 만 작동 시간이 매우 빠르며 기본적으로 데몬 모드가 없습니다. 이 견해의 응답 시간을 개선하고 싶습니다.

나는 많은 인스턴스를 시작하여 전체 시스템을 훨씬 더 빨리 실행하고 싶습니다. CMD 작업자 풀에서 입력을 기다리게하고 Call_Process 해당 작업자 풀 프로세스 중 하나가 데이터를 처리합니다.

이것은 실제로 두 부분입니다.

파트 1. 호출하는 함수 CMD 그리고 CMD 입력을 기다립니다. 이것은 파이프로 수행 될 수 있습니다

def _run_subcmd():
    p = subprocess.Popen(["cmd", fname], 
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    out, err = p.communicate()
    # write 'out' to a tmp file
    o = open("out.txt", "W")
    o.write(out)
    o.close()
    p.close()
    exit()

def _run_cmd(data):
    f = tempfile.NamedTemporaryFile("W")
    pipe = os.mkfifo(f.name)

    if os.fork() == 0:
        _run_subcmd(fname)
    else:
        f.write(data)

    r = open("out.txt", "r")
    out = r.read()
    # read 'out' from a tmp file
    return out

def call_process(request):
    response = HttpResponse()

    out = _run_cmd(request.GET['data'])

    response.write(out) # would be text/plain...
    return response

파트 2. 데이터를 기다리는 백그라운드에서 실행하는 일련의 작업자. 즉, 하위 프로세스가 이미 실행될 수 있도록 위를 확장하려고합니다. 예를 들어 Django 인스턴스가 초기화 될 때 Call_Process 먼저 호출되고,이 노동자 세트가 만들어집니다.

WORKER_COUNT = 6
WORKERS = []

class Worker(object):
    def __init__(index):
        self.tmp_file = tempfile.NamedTemporaryFile("W") # get a tmp file name
        os.mkfifo(self.tmp_file.name)
        self.p = subprocess.Popen(["cmd", self.tmp_file], 
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        self.index = index

    def run(out_filename, data):
        WORKERS[self.index] = Null # qua-mutex??
        self.tmp_file.write(data)
        if (os.fork() == 0): # does the child have access to self.p??
            out, err = self.p.communicate()
            o = open(out_filename, "w")
            o.write(out)
            exit()

        self.p.close()
        self.o.close()
        self.tmp_file.close()
        WORKERS[self.index] = Worker(index) # replace this one
        return out_file

    @classmethod
    def get_worker() # get the next worker
    # ... static, incrementing index 

다음과 같이 어딘가에 근로자의 초기화가 있어야합니다.

def init_workers(): # create WORKERS_COUNT workers
    for i in xrange(0, WORKERS_COUNT):
        tmp_file = tempfile.NamedTemporaryFile()
        WORKERS.push(Worker(i))

자, 내가 위에서 가지고있는 것은 무언가가됩니다.

def _run_cmd(data):
     Worker.get_worker() # this needs to be atomic & lock worker at Worker.index

     fifo = open(tempfile.NamedTemporaryFile("r")) # this stores output of cmd

     Worker.run(fifo.name, data)
     # please ignore the fact that everything will be
     # appended to out.txt ... these will be tmp files, too, but named elsewhere.

     out = fifo.read()
     # read 'out' from a tmp file
     return out


def call_process(request):
     response = HttpResponse()

     out = _run_cmd(request.GET['data'])

     response.write(out) # would be text/plain...
     return response

이제 질문 :

  1. 이것이 효과가 있습니까? (방금 머리 꼭대기에서 Stackoverflow로 입력 했으므로 문제가 있다고 확신하지만 개념적으로는 작동 할 것입니다)

  2. 찾아야 할 문제는 무엇입니까?

  3. 이것에 대한 더 나은 대안이 있습니까? 예를 들어 스레드도 잘 작동 할 수 있습니까 (데비안 레니 리눅스)? 이와 같은 병렬 프로세스 작업자 풀을 처리하는 라이브러리가 있습니까?

  4. 내가 의식해야 할 Django와의 상호 작용이 있습니까?

읽어 주셔서 감사합니다! 나는 당신이 이것을 내가하는 것처럼 흥미로운 문제라고 생각하기를 바랍니다.

브라이언

도움이 되었습니까?

해결책

이 제품을 펀칭하고있는 것처럼 보일 수 있습니다.이 제품을 추천 한 두 번째로 응답 한 것은이 제품이 두 번째로 응답 한 것 같습니다.

그러나 메시지 대기 서비스, 특히 분산 메시지 대기열이 필요한 것 같습니다.

ERE는 작동하는 방법입니다.

  1. Django 앱이 CMD를 요청합니다
  2. CMD가 대기열에 추가됩니다
  3. CMD는 여러 작품으로 밀려납니다
  4. 실행되고 결과가 상류로 반환됩니다

이 코드의 대부분은 존재하며 자신의 시스템을 구축 할 필요가 없습니다.

Django와 함께 처음 지어진 Celery를 살펴보십시오.

http://www.celeryq.org/ http://robertpogorzelski.com/blog/2009/09/10/rabbitmq-celery-and-django/

다른 팁

Issy는 이미 Celery를 언급했지만 의견은 코드 샘플과 잘 작동하지 않기 때문에 대신 답변으로 답장을 드리겠습니다.

AMQP 결과 저장소와 동기식으로 Celery를 사용해야합니다. 실제 실행을 다른 프로세스 또는 다른 컴퓨터에 배포 할 수 있습니다. 셀러리에서 동시에 실행하는 것은 쉽습니다.

>>> from celery.task import Task
>>> from celery.registry import tasks

>>> class MyTask(Task):
...
...     def run(self, x, y):
...         return x * y 
>>> tasks.register(MyTask)

>>> async_result = MyTask.delay(2, 2)
>>> retval = async_result.get() # Now synchronous
>>> retval 4

AMQP 결과 저장소는 결과를 매우 빠르게 전송하지만 현재 개발 버전에서만 사용할 수 있습니다 (Code-Freeze에서 0.8.0이되기 위해).

하위 프로세스 호출을 사용하는 "데몬 화"는 어떻습니까? 파이썬 데몬 또는 후계자, grizzed.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top