Question

Je suis donc autour de python jouant de stackless, écrire un très simple serveur web pour me enseigner la programmation avec microfiletages / tasklets. Mais maintenant, à mon problème, quand je lance quelque chose comme ab -n 100000 -c 50 http://192.168.0.192/ (100k demandes, 50) accès concurrentiel banc apache je reçois quelque chose comme 6k req / s, la deuxième fois que je le lance, je reçois 5.5k, troisième fois 5k, quatrième fois, 4,5 k, etc. tout le chemin jusqu'à 100req / s ou quelque chose.

Le problème disparaît lorsque je redémarre le script python, cependant.

Maintenant, ma question est pourquoi? Est-ce que j'oubliais de supprimer tasklets? J'ai vérifié la stackless.getruncount () (et il semble toujours revenir 1, pour une raison quelconque) il ne semble pas comme il y aurait des morts tasklets traîner? Je l'ai essayé d'appeler .kill () sur tous les tasklets qui sont faites, n'a pas aidé. Je ne peux pas comprendre cela.

import socket
import select
import stackless
import time

class socket_wrapper(object):
    def __init__(self, sock, sockets):
        super(socket_wrapper, self).__init__()
        self.sock = sock
        self.fileno = sock.fileno
        self.sockets_list = sockets
        self.channel = stackless.channel()
        self.writable = False
        self.error = False

    def remove(self):
        self.sock.close()
        self.sockets_list.remove(self)

    def send(self, data):
        self.sock.send(data)

    def push(self, bytes):
        self.channel.send(self.sock.recv(bytes))

def stackless_accept(accept, handler, recv_size=1024, timeout=0):
    sockets = [accept]

    while True:
        read, write, error = select.select(sockets, sockets, sockets, timeout)

        for sock in read:
            if sock is accept:
                # Accept socket and create wrapper
                sock = socket_wrapper(sock.accept()[0], sockets)

                # Create tasklett for this connection
                tasklet = stackless.tasklet(handler)
                tasklet.setup(sock)

                # Store socket
                sockets.append(sock)

            else:
                # Send data to handler
                sock.push(recv_size)

        # Tag all writable sockets
        for sock in write:
            if sock is not accept:
                sock.writable = True

        # Tag all faulty sockets
        for sock in error:
            if sock is not accept:
                sock.error = True
            else:
                pass # should do something here if the main socket is faulty

        timeout = 0 if socket else 1
        stackless.schedule() 

def simple_handler(tsock):
    data = ""

    while data[-4:] != "\r\n\r\n":
        data += tsock.channel.receive()

    while not tsock.writable and not tsock.error:
        stackless.schedule()

    if not tsock.error:
        tsock.send("HTTP/1.1 200 OK\r\nContent-length: 8\r\n\r\nHi there")
        tsock.remove()

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("192.168.0.192", 8000))
sock.listen(5)

stackless.tasklet(stackless_accept)(sock, simple_handler)
stackless.run()
Était-ce utile?

La solution

Deux choses.

Tout d'abord, s'il vous plaît faire Nom de la classe commencent par une lettre majuscule. Il est plus classique et plus facile à lire.

Plus important encore, dans la fonction stackless_accept vous accumulez un list d'objets Sock, nommé sockets. Cette liste semble croître sans cesse. Oui, vous avez un remove, mais ce n'est pas toujours invoquaient. Si la prise obtient une erreur, il semble qu'il sera laissé dans la collection pour toujours.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top