2016-04-07 13 views
0

Ich baue einen Firebird DB Transaktionsmanager in Python auf Linux mit JS + PHP-Clients. Javascript sendet alle notwendigen Informationen an PHP; PHP verschlüsselt dies und sendet es via Socket an Python, das einen Socket hat, der an einen Port gebunden ist, der ständig lauscht, und erzeugt einen neuen Thread mit Threading, um diese Anfrage asynchron zu behandeln.PHP socket_read/recv blockiert python socket.send

Die akzeptieren Schleife in Python:

while 1: 
    conn, addr = s.accept() 

    req = conn.recv(1024) 
    ret = read_headers(req) 

    threading.Thread(target=client_thread, args=(conn, addr, ret, smphr,)).start() 
s.close() 

Der Send/Leseblock in php:

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
$sockconnect = socket_connect($sock, $host, $port); 
$msg = urldecode(http_build_query($params)); 
socket_write($sock, $msg, strlen($msg)); 
$received; 
while(socket_recv($sock, $buf, 1024, 0) >= 1){ 
    $received .= $buf; 
} 
echo $received; 
socket_close($sock); 

Alles richtig zu funktionieren scheint, bis wir Tests mit größerer Anzahl von Verbindungen gestartet. Ich habe eine Schleife in der JS-Client, die sendet mehrere (25-100 sind die Zahlen, die ich bisher verwendet habe) Abfragen Anfrage mit einer Auswahl erste zufällige Anzahl von Zeilen aus einer großen Tabelle.

Die ersten Anfragen, die der Server empfängt, werden gleichzeitig verarbeitet, aber dann scheint es synchron zu werden.

Nach viel Protokollierung, festgestellt, dass nur 7/8 Threads zu jeder Zeit aktiv sind. Neue Anfragen werden nur akzeptiert und bearbeitet, nachdem eines der 7 aktuellen beendet wurde.

Wenn ich die socket_recv While-Schleife in PHP kommentieren, dann wird Python dann alles gleichzeitig ausführen und sobald wie möglich zurückgeben, was genau ich will, aber da ich den Block kommentiert habe, der tatsächlich das Ergebnis erhält, nichts wird (offensichtlich) gezeigt.

Jede Anfrage/Abfrage wird als ein anderer Skriptaufruf protokolliert (entsprechend dem Netzwerk-Entwicklungstool von Chrome), deshalb weiß ich nicht, warum sie sich gegenseitig blockieren.

Ich bin ziemlich neu bei PHP/Python und ich kann nicht für das Leben von mir herauszufinden, was los ist.

Irgendwelche Vorschläge?

Edit: ich auch verschiedene Teile des Codes lesen Sie die Antwort in PHP versucht habe (keine gearbeitet wie beabsichtigt):

$buf = 'buffer'; 
socket_recv($sock, $buf, 1024, MSG_WAITALL); 
echo $buf; 

Wie in früheren Implementierung, 08.07 Faden 'Limit'

$buf = 'buffer'; 
socket_recv($sock, $buf, 1024, MSG_DONTWAIT); 
echo $buf; 

Wie die Flagge schon sagt, wartet nicht auf eine Antwort, hat daher keine Antwort

while ($out = socket_read($sock, 1024, PHP_NORMAL_READ)) { 
    echo $out; 
} 

Gleiches Gewinde 7/8 Gewindegrenze.

Zweite edit:

Added Python druckt, falls es hilft.

Mit Lese in php:

starting select first 3000 * from receb_quotas on tr1 
starting select first 1 * from receb_quotas on tr0 
starting select first 1 * from receb_quotas on tr2 
starting select first 1 * from receb_quotas on tr4 
starting select first 3000 * from receb_quotas on tr3 
starting select first 3000 * from receb_quotas on tr5 
finishing tr4 (count: 1) | remaining threads: 7 
finishing tr0 (count: 1) | remaining threads: 7 
starting select first 150 * from receb_quotas on tr8 
starting select first 3000 * from receb_quotas on tr6 
finishing tr2 (count: 1) | remaining threads: 7 
starting select first 1 * from receb_quotas on tr7 
finishing tr7 (count: 1) | remaining threads: 7 
starting select first 3000 * from receb_quotas on tr9 
finishing tr8 (count: 150) | remaining threads: 7 
finishing tr1 (count: 3000) | remaining threads: 6 
finishing tr3 (count: 3000) | remaining threads: 5 
finishing tr6 (count: 3000) | remaining threads: 4 
finishing tr5 (count: 3000) | remaining threads: 3 
finishing tr9 (count: 3000) | remaining threads: 2 

Ohne php lesen:

starting select first 3000 * from receb_quotas on tr1 
starting select first 15 * from receb_quotas on tr0 
starting select first 15 * from receb_quotas on tr3 
starting select first 3000 * from receb_quotas on tr4 
starting select first 1500 * from receb_quotas on tr2 
starting select first 150 * from receb_quotas on tr5 
starting select first 1 * from receb_quotas on tr6 
starting select first 1500 * from receb_quotas on tr7 
starting select first 150 * from receb_quotas on tr8 
starting select first 15 * from receb_quotas on tr9 
finishing tr0 (count: 15) | remaining threads: 11 
finishing tr3 (count: 15) | remaining threads: 10 
finishing tr6 (count: 1) | remaining threads: 9 
finishing tr9 (count: 15) | remaining threads: 8 
finishing tr8 (count: 150) | remaining threads: 7 
finishing tr5 (count: 150) | remaining threads: 6 
finishing tr7 (count: 1500) | remaining threads: 5 
finishing tr2 (count: 1500) | remaining threads: 4 
finishing tr1 (count: 3000) | remaining threads: 3 
finishing tr4 (count: 3000) | remaining threads: 2 

Es scheint wirklich, dass ohne die Lese in php, werden die Abfragen alle gleichzeitig gestartet Zeit und kehrte sobald bereit.

+0

Kann nicht sicher sein, dass dies relevant ist, aber: Was ist das 'backlog' Argument, das' s.listen 'gegeben wird? –

+0

@GilHamilton s.listen ist auf 100 eingestellt –

+0

Ich würde einen großen Fett "Schlaf für immer" in den Python-Unter-Thread ('signal.pause()' oder 'time.sleep (a_large_number)') setzen. Dann senden Sie, sagen wir, 25 oder 50 Anfragen. Dann versuche herauszufinden, in welchem ​​Zustand sich diese Threads/Verbindungen befinden. Da du an diesem Punkt 25-50 verschiedene Threads haben solltest, ist es möglich herauszufinden, was passiert. Sie sagen nicht, welche Plattform, aber zumindest auf Linux, können Sie Python mit 'strace -o/tmp/xxx -ff Python ...' starten und strace alle Systemaufrufe anzeigen lassen. –

Antwort

0

Es stellte sich heraus, dass dies ein Browserproblem war. Chrome (möglicherweise andere moderne Browser) unterstützt nur bis zu 6 Ajax-Anrufe gleichzeitig.

Da hatte ich diese 7 Gewinde "Kappe", von denen einer der Hauptfaden ist. Das passt perfekt.