gunicorn分析 基于 tag0.2

来源:互联网 发布:python sorted key 编辑:程序博客网 时间:2024/06/14 06:19

gunicorn 工作原理

1.工作模型

    gunicorn采用的是master-worker模型,一个master进程,多个worker进程。master进程负责管理worker进程
    def spawn_workers(self):        workers = set(w.id for w in self.WORKERS.values())        for i in range(self.num_workers):            if i in workers:                continue            worker = Worker(i, self.pid, self.LISTENER, self.modname,                        self.timeout)            pid = os.fork()            if pid != 0:                self.WORKERS[pid] = worker                continue                        worker_pid = os.getpid()            try:                self.log.info("Worker %s booting" % worker_pid)                worker.run()                sys.exit(0)            except SystemExit:                raise            except:                self.log.exception("Exception in worker process.")                sys.exit(-1)            finally:                worker.tmp.close()                self.log.info("Worker %s exiting." % worker_pid)

下面我来个简化版的:
main.py
import os, socket, sysfrom worker import Workerprint os.getpid(), 'process start'sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)sock.setblocking(0)sock.bind(("127.0.0.1", 5000))sock.listen(2048)for i in range(3):    w = Worker(i, os.getpid(), sock)    pid = os.fork()    if pid != 0:        continue    try:        w.run()        sys.exit(0)    except SystemExit:        raise    except:        sys.exit(-1)# for read consoleimport timetime.sleep(200)print 'end!'

worker.py
# -*- coding: utf-8 -import errnoimport osimport selectimport socketCHUNK_SIZE = (16 * 1024)def read_partial(sock, length):    while True:        try:            ret = select.select([sock.fileno()], [], [], 0)            if ret[0]: break        except select.error, e:            if e[0] == errno.EINTR:                continue            raise    data = sock.recv(length)    return dataclass Worker(object):    def __init__(self, workerid, ppid, socket):        self.id = workerid        self.ppid = ppid        self.socket = socket        self.timeout = 10        self.alive = True    def run(self):        while self.alive:            nr = 0            while self.alive:                try:                    client, addr = self.socket.accept()                    buf = ''                    while True:                        data = read_partial(client, CHUNK_SIZE)                        if not data: break                        buf += data                    print buf                    nr += 1                except socket.error, e:                    if e[0] in (errno.EAGAIN, errno.ECONNABORTED):                        print 'socekt.error'                        break  # Uh oh!                    raise                if nr == 0: break            while self.alive:                try:                    ret = select.select([self.socket], [], [],                                        self.timeout)                    if ret[0]:                        break                except select.error, e:                    if e[0] == errno.EINTR:                        print 'select error', os.getpid()                        break                    raise


Linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN)
这表明你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误,
这个错误不会破坏socket的同步,可以不用管它,循环接着recv就可以。

0 0
原创粉丝点击