Многопоточность и прокси добавляет задержку 30 секунд. Что я могу сделать, чтобы избежать - PullRequest
1 голос
/ 21 февраля 2011

Я использую PyQt, QThreads и couchdb-python для связи с экземпляром couchDB в локальной сети.

Чтобы проверить, что многопоточность будет работать, если сеть работает медленно, я поместил прокси между графическим интерфейсом и кушеткой.

Сеть зарегистрирована.Журнал начинается с

13:52:46.303 (1) send: HEAD /cubic HTTP/1.1CRLFHost: localhost:5981CRLFContent-Length: 0CRLFAccept: application/jsonCRLFUser-Agent: CouchDB-Python/0.8CRLFCRLF

13:52:46.308 (1) recv: HTTP/1.1 200 OKCRLFServer: CouchDB/1.0.1 (Erlang OTP/R13B)CRLFDate: Mon, 21 Feb 2011 13:47:18 GMTCRLFContent-Type: application/jsonCRLFContent-Length: 219CRLFCache-Control: must-revalidateCRLFCRLF
13:53:16.312 (1) recv: link closed
13:53:16.319 (2) send: GET /cubic/_design/Company/_view/by_name HTTP/1.1CRLFHost: localhost:5981CRLFContent-Length: 0CRLFAccept: application/jsonCRLFUser-Agent: CouchDB-Python/0.8CRLFCRLF
13:53:16.330 (2) recv: HTTP/1.1 200 OKCRLFTransfer-Encoding: chunkedCRLFServer: CouchDB/1.0.1 (Erlang OTP/R13B)CRLFEtag: "243QGZGN1ETGA4VN9H1OMB86Z"CRLFDate: Mon, 21 Feb 2011 13:47:48 GMTCRLFContent-Type: application/jsonCRLFCache-Control: must-revalidateCRLFCRLF
13:53:16.331 (2) recv: a0CRLF{"total_rows":9,"offset":0,"rows":[CRLF{"id":"c182c1a2f71c3547ccee45556300770e","key":["A first Company","231","345 East of Eden" ,"Manchester",null],"value":null}CRLF
13:53:16.332 (2) recv: 77CRLF,CRLF{"id":"c182c1a2f71c3547ccee455563001254","key":["C-U-B","1","9-11 March Business Centre","March",null],"value":null}CRLF72CRLF,CRLF{"id":"421261e8a3311c356c4900185800d976","key":"Four","104","4 Fourth street","Four Score",null],"value":null}CRLF74CRLF,CRLF{"id":"c182c1a2f71c3547ccee455563003de8","key":["Fred Smith","431","30 High street","Somehow",null],"value":null}CRLF
13:53:16.334 (2) recv: 83CRLF,CRLF{"id":"7bc7f2014593d108b5b681fe03002ad6","key":["Ian Hobson","1002","31 Sheerwater Dr","Northampton, Nhants",null],"value":null}CRLF76CRLF,CRLF{"id":"c182c1a2f71c3547ccee455563003139","key":["Julie Bloggs","302","30 Back Lane","Somewhere",null],"value":null}CRLF7cCRLF,CRLF{"id":"c182c1a2f71c3547ccee455563002e87","key": "Kingfisher Group","323","33 Westmister Rd","Londonx",null],"value":null}CRLF
13:53:16.335 (2) recv: 7aCRLF,CRLF{"id":"c182c1a2f71c3547ccee455563005894","key":["New Company","212","34 Back Street","Another Town",null],"value":null}CRLF72CRLF,CRLF{"id":"421261e8a3311c356c4900185800d7e2","key":["Three","103","3 High Street","Liverpool 8",null],"value":null}CRLF4CRLFCRLF]}CRLF1CRLFLFCRLF0CRLFCRLF
13:53:46.337 (2) recv: link closed

Это точно так, как и ожидалось, за исключением того, что после открытия базы данных в 13: 52: 46.308 происходит задержка в 30 секунд, а время ожидания ссылки recv истекает.Пока это не произойдет, код не сможет открыть представление, которое происходит в 13: 53: 16.319

Однако прокси-сервер использует другой поток {(2) not (1)}.Часть приложения работает без прокси, поэтому я подозреваю, что прокси.

Код прокси основан на микропрокси и имеет значение ниже

import re, sys, datetime
import socket 
import threading 
PORT = 5981
class ConnectionThread(threading.Thread): 
    def __init__(self, (conn,addr),id): 
        self.conn = conn 
        self.addr = addr
        self.id = id
        threading.Thread.__init__(self)

    def report(self,data,dir):
        txt = data.replace("\n",'LF')
        txt = txt.replace("\r",'CR')
        now = datetime.datetime.now()
        print "%s (%s) %s: %s" % (now.isoformat()[11:23],self.id,dir,txt)      

    def run(self): 
        data = self.conn.recv(1024*1024) 
        request = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        request.connect(('192.168.0.1',5984)) 
        self.report(data,'send')
        request.send(data) 
        while True: 
            temp = request.recv(1024) 
            if ('' == temp):
                self.report('link closed','recv')
                break 
            self.report(temp,'recv')
            self.conn.send(temp)
        self.conn.close()

class ProxyThread(threading.Thread): 
    def __init__(self, port): 
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        self.sock.bind(('localhost', port))
        self.count = 1
        threading.Thread.__init__(self) 
    def run(self): 
        self.sock.listen(3) 
        while True:
            temp = ConnectionThread(self.sock.accept(),self.count)
            temp.start()   # each message handled in own thread
            self.count += 1
if __name__ == "__main__": 
    print "Starting a proxy on port", PORT
    proxy = ProxyThread(PORT) 
    proxy.run() 

И запрос на открытие базы данных, и запрос на представление выполняются в одном и том же потоке (без графического интерфейса).Почему задержка должна произойти?

А как я могу что-то изменить, чтобы это не изменилось?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2011

Ваш цикл читает только с одного конца подключаемого соединения. Таким образом, когда ответ пересылается с сервера на клиент, а клиент отключается, код не замечает отключение клиента и продолжает ожидать ответа или отключения сервера.

Чтобы исправить это, необходимо прочитать данные из сокетов сервера (запрос) и клиента (self.conn). Проще всего это сделать с помощью неблокирующих сокетов.

0 голосов
/ 21 февраля 2011

Состояния HTTP (раздел 9.4)

Метод HEAD идентичен GET, за исключением того, что сервер НЕ ДОЛЖЕН возвращать тело сообщения в ответе.

Это означает, что после CRLFCRLF ничего не происходит, но ваш прокси-сервер ожидает данные, а не читает из входящего соединения.Я подозреваю, что библиотека couchdb пытается использовать соединение keep-alive, но вы наблюдаете не тот сокет.

Ваша основная проблема в том, что вы утверждаете, что говорите с HTTP 1.1, но вы этого не делаете.Вы должны следить за последовательностью CRLFCRLF заголовка размера контента.Если вы обнаружите, что кто-то прочитал столько данных, то вырвитесь из цикла, если его нет, немедленно прервитесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...