云计算(2)- eventlet 管理Wsgi服务

云计算(2)- eventlet 管理Wsgi服务

解决方案goocz2025-05-22 10:49:174A+A-

背景:

进程:是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单元,是应用程序运行的载体。

线程:是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分配的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间。

协程:协程是一种轻量级线程,协程的调度完全由用户控制。协程运行在单线程中,协程是组织好的代码流程,协程需要线程来承载运行,线程是协程的资源。线程的任务调度是通过操作系统来执行的,需要消耗CPU的资源,容易产生资源浪费,而协程其任务调度由用户决定,且值同时存在于一个进程之中,减少了切换的成本

并发:在多线程中,大部分操作系统的任务调度是采用时间片轮转的抢占式调度方式,就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行,直到所有线程的任务。

并行:把任务同时分配给不同的CPU,没有任务切换的过程,叫并行。

概述:

eventlet是具有支持WSGI的异步框架,一方面是用来处理和网络相关,另一方面通过协程实现并发。select库中的epoll是默认的网络通信模型,greetlet库是其并发的基础,eventlet库对其进行封装之后,就构成了GreenThread。实现并发,非阻塞。

Hub构成了Eventlet的事件循环,它分发I/O事件,调度greenthread。

Eventlet有多种hub的实现,epolls,poll,selects,pyevent。

Hub的实现是在线程内的,eventlet.hubs.use_hub()只在当前线程内起作用。当使用多线程且这些线程都有自己的hub时,需要在每个需要特定hub的线程函数前调用该函数,也可在主线程调用一次。hub有一个主线程,当运行中的协程需要进行I/O操作时,它会在hub中注册一个listener,然后切换到MAINLOOP。如果有其他准备运行的协程,MAINLOOP会切换到,当他们完成执行或需要执行I/O时,又会将控制权切换到MAINLOOP,MAINLOOP确保了每一个协程在自己有事要完成的时间都能够得到调度。

协程:

实现协程的几种方式:

  • yield
  • greenlet 封装yield实现
  • gevent 封装greenlet进行自动切换
  • asyncio(python3.4)
  • async,await (python3.5)

安装:

pip install -U eventlet
pip install -U https://github.com/eventlet/eventlet/archive/master.zip

接口解释:

  • eventlet.listen(bind_addr, family, backlog=backlog)

创建socket,监听端口。

  • eventlet.wsgi.server() 调用Wsgi服务
eventlet.wsgi.server(
socket,   # Server socker 已经绑定一个端口且监听中
site,		# 实现WSGI应用的函数
log=None,  日志输出的位置
environ=None,   添加到每一次请求的environ字典中的额外参量
max_size=None,   允许的最大客户端连接数
max_http_version='HTTP/1.1', 
protocol=<class eventlet.wsgi.HttpProtocol at 0x7f4f68192f58>, 
minimum_chunk_size=None, 
log_x_forwarded_for=True, 
custom_pool=None,   # 一个定制的GreenPool实例,用来孵化客户端的greenthreads。eventlet.GreenPool(pool_size)
keepalive=True, 
log_output=True, 
log_format='%(client_ip)s - - [%(date_time)s] "%(request_line)s"
%(status_code)s %(body_length)s %(wall_seconds).6f', 
url_length_limit=8192,   # 请求URL的最大长度,如果超长,返回414错误。
debug=True, 
socket_timeout=None,   # 客户端联机的套接字操作超时限制
capitalize_response_headers=True)
  • eventlet.wrap_ssl(dup_socket, **ssl_kwargs)

创建安全的server

  • eventlet.greenpool

class eventlet.greenpool.GreenPool(size=1000)

该类的对象是green threads的池子。

  1. free() 返回当前对象中可用的greenthreads,如果为0或更少,那么spawn和spawn_n将会阻塞调用greenthread直到有新的可用的greenthread为止。
  2. resize() 改变当前允许同时工作的greenthreads最大数量。
  3. running() 返回当前池子中正在执行任务的greenthreads。
  4. spawn() 从当前的池子中孵化一个可用的greenthread,执行函数。可以通过greenthread对象获取function的返回值。
  5. spawn_n() 创建一个greenthread来运行function,返回值为None。
  6. waitall() 等待池子中的所有greenthreads完成工作。
  7. waiting() 返回当前等待孵化的greenthreads数。
  • GreenPile

pile=eventlet.GreenPile(pool)

pile.spawn_n(func, value) #值可以重用

调用范例

% python
>>> import eventlet
>>> from eventlet.green import urllib2
>>> gt = eventlet.spawn(urllib2.urlopen, 'http://eventlet.net')
>>> gt2 = eventlet.spawn(urllib2.urlopen, 'http://secondlife.com')
>>> gt2.wait()
>>> gt.wait()
import eventlet
eventlet.monkey_patch()  #必须要加这段代码,引用下path

with eventlet.Timeout(3, False):    # 等待3秒,如果3秒内第8-9行代码执行没有执行完,则跳过
    time.sleep(4)                   # 等待4秒
    print('结果1')                   # 因为等待了4秒,大于超时时间,所以’结果1‘不打印

参考资料

https://www.cnpython.com/pypi/eventlet

https://docs.python.org/zh-cn/dev/library/asyncio-task.html

点击这里复制本文地址 以上内容由goocz整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

果子教程网 © All Rights Reserved.  蜀ICP备2024111239号-5