• Gevent


    Gevent

    特点:
    	是一个基于libev的并发库 它为各种并发和网络相关的任务提供了整洁的API
    	基于libev的高效时间循环
    	基于greenlet的轻量级执行单元
    	重用Python标准库API内容(比如Event Queues)
    	socket谢童ssl
    	利用线程池或者c-cares来执行DNS查询
    

    a. 进程 线程 协程

    进程:
        概念: 进程是正在运行程序的实例
        特点: 具有独立地址空间 是操作系统资源分配的基本单元
        进程上下文: 进程的物理实体与支持进程运行的物理环境,包括:地址空间 系统栈 打开文件表 。。。
        上下文切换: 由一个进程的上下文转到另一个进程的上下文
        系统开销: 运行操作系统程序完成系统管理工作所话费的时间和空间
        一个进程可以包括多个线程
    
    线程:
    	- 线程是程序执行的最小单位
    	- 多线程的优点: 提高程序的并发性
    协程:
    	- 协程可以认为是一种用户态的线程,与系统提供的线程不同点是 他需要主动让出cpu时间,而不是由系统进行调度,即控制权在程序员手上。
    
    优缺点:
    	- 进程创建销毁成本高
    	- 线程开销比进程低,但切换成本高,线程间同步变复杂。
    	- 协程不陷入内核的情况进行上下文切换,没有同步问题,但需要手动切换。
    
    下图解释:
        进程是有状态的 刚启动时就绪态,如果进程调度算法调度到这个进程 就会变成执行态。
        分配的算法是有时间片的 当时间片使用完 会继续切回就绪态
        如果时间片没有使用完 当有IO发生就会阻塞态 阻塞完成 继续切回用户态

    b. 阻塞 非阻塞 同步 异步

    阻塞与非阻塞:
         
        网络IO
            - 对于网络IO主要指socket,socket是进程间通信的一种方法 对于阻塞与非阻塞的情况就是在使用socket中在调用它的API时它的connect read write 会发生阻塞,也可以设置为非阻塞。
            - socket会在connect/read/write时发生阻塞
        阻塞
            - 阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回
        非阻塞
            - 非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回
    
    
    同步与异步:
    
    	同步:
    		同步就是发生调用时,一定等待结果返回,整个调用才结束。
    
    	异步:
    		异步就是发生调用后,立即返回,不等待结果返回,被调用者通过状态/通知来通知调用者,或通过回调函数处理这个调用。
    
    
    	同步异步 与 阻塞非阻塞区别:
    		阻塞/非阻塞 它们是程序在等待消息(无所谓同步或者异步)时的状态。
    		同步/异步 是程序获得关注消息通知的机制。
    
    		同步阻塞: 效率最低(日志程序)
    		同步非阻塞: 效率也不高(需要轮询)
    		异步阻塞: 一般模式线程回调
    		异步非阻塞: IOCP
    connect 阻塞做的操作
    	客户端和服务端做交互的时候,客户端连接服务器,connect时候阻塞会自动打开,会向服务端发送一个序列号,服务端接受后处于阻塞。

    数据接受阻塞
    	应用层recvfrom调用过程中会发生一个系统调用。系统调用会陷入内核里面。如果没有数据准备好,会等待数据直到数据准备好,内核得到数据把数据复制到用户空间,在返回。

    c. 并发 并行

    #并发
    	并发是指两个或多个事件在同一时间间隔发生。就是同时处理很多事情,比如串行同时处理一件事情。
    	在单核系统中,为了提高cpu利用率,系统采用时间片轮询等调度方式,对多个线程轮换执行,在宏观上看线程是同时执行的 从微观上看某一时刻只执行一个线程。在发生资源竞争或者大量的上下文切换会导致性能消耗。
    

    d. monkey patch

    # monkey patch
    
    	- 在动态语言中,不去改变源码而对功能进行追加和变更就叫做 Monkey Patching(猴子补丁)
    	1. 追加功能
    	2. 功能变更
    	3. 修正程序错误
    	4. 增加钩子,在执行某个方向的同时执行一些其他的处理 如打印日志 实现AOP等
    
    	#模块
    		- socket
    		- dns
    		- time
    		- select
    		- thread
    		- os
    		- ssl
    		- subprocess
    		- sys
    		- builtins
    		- signal
    	默认阻塞的模块都被替换成非阻塞,协作式的。
    	gevent支持异步协作的域名解析系统。
    	time.sleep只是协作内休眠,并不阻塞线程。
    
    import gevent
    from gevent import monkey
    
    urls = ["http://www.baidu.com","http://www.zhihu.com","http://www.xiaohuar.com/"]
    import urllib2
    import timeit
    def print_head(url):
        print("start %s"%url)
        gevent.sleep(0)
        data = urllib2.urlopen(url).read()
        print("%s:%s bytes: %r" %(url,len(data),data[:50]))
    
    
    def test():
        jobs = [gevent.spawn(print_head,url) for url in urls]
        gevent.joinall(jobs)
    
    monkey.patch_all()      #加上这行效率明显提升
    
    print timeit.Timer(stmt='test()',setup="from __main__ import test").timeit(number=10)
    实例演示

    e. gevent.server

    # 服务器端
    import socket
    import sys
    
    host = "localhost"
    port = 5000
    
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    s.bind((host,port))
    s.listen(100)
    while True:
        conn,addr = s.accept()
        print 'connected with',addr[0], ':',str(addr[1])
        data = conn.recv(1024)
        print data
        conn.close()
    
    s.close()
    
    
    
    # 客户端
    
    from gevent import monkey
    monkey.patch_all()
    import gevent
    import socket
    
    def do_connect(addr,index):
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        sock.connect(addr)
        gevent.sleep(0.5)
        sock.send("hello world")
    
    addr = ('localhost',5000)
    
    greenlets = []
    num = 1
    for i in xrange(num):
        g = gevent.spawn(do_connect,addr,i)
        greenlets.append(g)
    gevent.joinall(greenlets)
    普通服务器 客户端
    # gevent server
    
    from gevent.server import StreamServer
    import gevent
    from gevent import monkey
    monkey.patch_all()
    import socket
    
    def handler(sock,addr):
        while True:
            data = sock.recv(1024)
            if not data:
                print addr, "closed"
                return
            print "get ",data
    
    server = StreamServer(('127.0.0.1',3000),handler)
    
    server.serve_forever()
    gevent server

    f. gevent.WSGIServer 

    WSGI 介绍
    
    	web服务器网关接口(Python Web Server Gateway Interface 缩写为WSGI) 是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口
    
    WSGI server
    
    	WSGI server所做的工作仅仅是将从客户端收到的请求传递给WSGI application,然后将WSGI application的返回值作为响应传给客户端。
    	WSGI application 可以是Flask,Diango 等web框架。
    

      

     

      

     

      

      

  • 相关阅读:
    Synchronized和Lock的实现原理和锁升级
    如何禁止CPU指令重排
    MESI缓存一致性
    归并排序
    强软弱虚四种引用和ThreadLocal内存泄露
    VINS-Mono代码分析与总结(完整版)
    IMU误差模型与校准
    小感
    K8S conul部署
    Centos Consul集群及Acl配置
  • 原文地址:https://www.cnblogs.com/golangav/p/7781505.html
Copyright © 2020-2023  润新知