最简单的并发

import socket

response = 'HTTP/1.1 200 OK\r\nConnection:Close\r\nContent-Length:11\r\n\r\nHello World'

server = socket.socket()
server.bind(('0.0.0.0', 9527))
server.listen(1024) while True:
client, clientaddr = server.accept() #等待客户端连接,阻塞
request = client.recv(1024) #等待客户端面消息,阻塞
client.send(response) #可能会阻塞
client.close()

虽然可以处理很多请求,但它依然是一个请求一个请求执行的,而且有两个阻塞的地方,还有一个可能会阻塞的地方,为什么会是可能阻塞,在内核的socket的实现中,有一个read buffer,还有一个write buffer,过程应该是这样的:

多进程

显然,每个请求对应一个进程的话,可以解决阻塞的问题,但是进程太耗资源,而且每个进程都是独立的,无法共享,进程切换成本也高。

import socket
import signal
import multiprocessing response = 'HTTP/1.1 200 OK\r\nConnection:Close\r\nContent-Length:11\r\n\r\nHello World' server = socket.socket()
server.setsockopt(socket.SOL.SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', 9527))
server.listen(1024) def handler(client):
request = client.recv(1024)
client.send(response)
client.close() signal.signal(signal.SIGCHLD, signal.SIG_IGN) #多进程里的子进程执行完后并不会死掉,会变成僵尸进程,必须等到主进程挂掉后,才会死掉,这句可以解决这个问题 while True:
client, addr = server.accetp()
process = multiprocessing.Process(target=handler, args=(client,))
process.start()

Prefork

如上面的多进程,如果请求数多,资源占用无法控制;可以分配和cpu核数一样的进程数来有效控制资源占用

import socket
import multiprocessing response = 'HTTP/1.1 200 OK\r\nConnection:Close\r\nContent-Length:11\r\n\r\nHello World' server = socket.socket()
server.bind(('0.0.0.0', 9527))
server.listen(1024) def handler():
while True:
client, addr = server.accept()
request = client.recv(1024)
client.send(response)
client.close() processors = 8
for i in range(0, processors):
process = multiprocessing.Process(target=handler, args=())
process.start()

线程池

import queue
import socket
import threading response = 'HTTP/1.1 200 OK\r\nConnection:Close\r\nContent-Length:11\r\n\r\nHello World' server = socket.socket()
server.bind(('0.0.0.0', 9527))
server.listen(1024) def handler(queue):
while True:
client = queue.get()
request = client.recv(1024)
client.send(response)
client.close() queue_list = queue.Queue()
processors = 8 for i in range(0, processors):
thread = threading.Thread(target=handler, args=(queue_list,))
thread.daemon = True
thread.start() while True:
client, clientaddr = server.accept()
queue_list.put(client)

线程占用的资源比较少,因为资源可以共享, 但是要考虑线程安全问题和锁的性能, 而且python的解释器有GIL, 导致不能有效利用多核CPU。

epoll

import select
import select response = 'HTTP/1.1 200 OK\r\nConnection:Close\r\nContent-Length:11\r\n\r\nHello World' server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(False)
server_address = ('localhost', 9527)
server.bind(server_address)
server.listen(1024) READ_ONLY = select.EPOLLIN | select.EPOLLPRI
epoll = select.epoll()
epoll.register(server, READ_ONLY)
timeout = 60
fd_to_socket = {server.fileno(): server} while True:
events = epoll.poll(timeout)
for fd, flag in events:
sock = fd_to_socket[fd]
if flag and READ_ONLY:
if sock is server:
conn, client_address = sock.accept()
conn.setblocking(False)
fd_to_socket[conn.fileno()] = conn
epoll.register(conn, READ_ONLY)
else:
request = sock.recv(1024)
sock.send(response)
sock.close()
del fd_to_socket[fd]

用python理解web并发模型的更多相关文章

  1. 用 Python 理解 Web 并发模型

    用 Python 理解 Web 并发模型 http://www.jianshu.com/users/1b1fde012122/latest_articles   来源:MountainKing 链接: ...

  2. web并发模型

    并发:cpu划分时间片,轮流执行每个请求任务,时间片到期后,换到下一个. 并行:在多核服务器上,每个cpu内核执行一个任务,是真正的并行 IO密集型的应用,由于请求过程中很多时间都是外部IO操作,CP ...

  3. 共享内存 & Actor并发模型哪个更快?

    HI,前几天被.NET圈纪检委@懒得勤快问到共享内存和Actor并发模型哪个速度更快. 前文传送门: 说实在,我内心10w头羊驼跑过...... 先说结论 首先两者对于并发的风格模型不一样. 共享内存 ...

  4. 【并发编程】一文带你读懂深入理解Java内存模型(面试必备)

    并发编程这一块内容,是高级资深工程师必备知识点,25K起如果不懂并发编程,那基本到顶.但是并发编程内容庞杂,如何系统学习?本专题将会系统讲解并发编程的所有知识点,包括但不限于: 线程通信机制,深入JM ...

  5. Java并发指南2:深入理解Java内存模型JMM

    本文转载自互联网,侵删   一:JMM基础与happens-before 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实 ...

  6. python三大web框架Django,Flask,Flask,Python几种主流框架,13个Python web框架比较,2018年Python web五大主流框架

    Python几种主流框架 从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等. Django: Python We ...

  7. 理解Storm并发

    作者:Jack47 PS:如果喜欢我写的文章,欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 注:本文主要内容翻译自understanding-the-parall ...

  8. Server Develop (五) Linux并发模型

    Linux并发模型 目前可以实现并发程序的方法有Apache模型(Process Per Connection,简称PPC),TPC(Thread PerConnection)模型,以及select模 ...

  9. Linux并发模型

    Linux并发模型 Linux并发模型 目前可以实现并发程序的方法有Apache模型(Process Per Connection,简称PPC),TPC(Thread PerConnection)模型 ...

随机推荐

  1. hadoop HDFS 写入吞吐量

    最近一个项目 在大把大把的使用hadoop-HDFS,关于HDFS 的优势网上都快说烂了,这里不再说了,免得被.. 呵呵 废话少说,开整 1.场景描述: 服务器A 监听 服务器B分发任务socket. ...

  2. RabbitMQ 入门 Helloworld -摘自网络

    本系列教程主要来自于官网入门教程的翻译,然后自己进行了部分的修改与实验,内容仅供参考. “Hello world” of RabbitMQ 1.Windows下RabbitMQ的安装 下载Erlang ...

  3. Varnish – 高性能http加速器

    Varnish是一款高性能且开源的反向代理服务器和http加速器.与传统的Squid相比,Varnish具有性能更高.速度更快.管理更方便 等诸多优点.作者Poul-Henning Kamp是Free ...

  4. POJ 1258 Agri-Net (最小生成树)

    Agri-Net 题目链接: http://acm.hust.edu.cn/vjudge/contest/124434#problem/H Description Farmer John has be ...

  5. JVM基础知识(1)-JVM内存区域与内存溢出

    JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...

  6. poj 3026 Borg Maze (BFS + Prim)

    http://poj.org/problem?id=3026 Borg Maze Time Limit:1000MS     Memory Limit:65536KB     64bit IO For ...

  7. codeforces 630 I(规律&&组合)

    I - Parking Lot Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Subm ...

  8. codeforces 630KIndivisibility(容斥原理)

    K. Indivisibility time limit per test 0.5 seconds memory limit per test 64 megabytes input standard ...

  9. [iOS UI进阶 - 3.2] 手势识别器UIGestureRecognizer

    A.系统提供的手势识别器   1.敲击手势 UITapGestureRecognizer numberOfTapsRequired: 敲击次数 numberOfTouchesRequired: 同时敲 ...

  10. [iOS UI进阶 - 4.0] 涂鸦app Demo

    A.需求 1.超简易画图,只有一种画笔 2.清屏功能 3.回退功能 4.保存功能 5.使用了cocos2D   code source: https://github.com/hellovoidwor ...