1、django和python的缺陷分析
django作为一个python实现的web服务器,它的性能其实是没有多大保证的。这是因为python的线程是不能共享机器资源的(因为万恶的GIL),线程们只是通过频繁切换控制权,来分享一个core上的时间片,让你看起来是并发在跑,但是其实同一个时间只有一个线程在跑。那python是不是在自欺欺人?不是的。看你程序的类型:
1)IO密集型
IO密集型程序的耗时基本都在打开文件/打开句柄进行读写,也就是消耗在IO上。这种类型的程序,当线程阻塞在IO上时,交出线程控制权,给其他线程运行,当IO完成后再获得控制权继续跑,这样的话,可以在IO的时候跑其他的线程,其实是可以提高代码运行效率的。
2)计算密集型
你的程序基本就没有IO,而是在跑一个算法。那么对不起,这种类型的程序,你通过python多线程编程无法提升效率,甚至会再频繁切换线程控制权时,损失效率。
3)协线程greenlet
python的这种类型的线程(我们姑且叫他线程),只在IO阻塞的情况下进行线程控制权的切换。而gevent就是协线程的一个实现。
启动方式
nohup gunicorn –worker-class=gevent dmonitor.wsgi:application -b 0.0.0.0:8009 -w 4 &
–worker-class:指定了异步方式,使用的是gevent方式实现的异步,也就是每个worker(进程)中线程之前切换使用的是协线程切换。
dmonitor.wsgi:application:dmonitor是django工程的名称,你的django工程中要有wsgi.py文件。
-b:你的进程服务绑定哪个ip和端口
-w:启动几个worker
介绍一下gunicorn
1)主从结构
gunicorn其实是个pre-fork的主从结构:一个master进程管理着多个worker进程,之前我们起了4个进程,但是实际上有5个就是因为有一个是master进程。
master进程不对外提供api,只是进行集群的管理,核心就是探活,一旦发现有worker进程挂掉了,那么master会把它拉起来。
2)worker数量的选择
官方给出的公式是worker_num = (2 x $num_cores) + 1,num_cores是机器核数。
官方又说了,一般配置的数量是4-12个,就能够支持上万QPS。当然前提是你的web服务能处理的过来。
在说nginx部署之前,先说一些废话。
可能大家有个疑问,gunicorn和nginx有啥区别?或者说我使用了gunicorn已经启动了多个实例,并且进行了负载均衡,我为什么要需要nginx呢?
一般来说是需要nginx的,原因有这几点:
1)你的服务有没有静态文件?
2)你需不需要做灰度,需不需要拦截功能等等等?
3)你能保证你的服务能抗的住高峰压力?
nginx的强大能让你拥有上述的能力。当然nginx作为一个已经在无数生产环境中验证过的web容器,还是很省心的。
回到这个系列,我们是想解决高并发异步场景,那么对高并发使用nginx有什么好处呢?
nginx可以做为一个缓冲器,nginx在接收完request之后,才开始转发,如果nginx后面的服务疲于相应,nginx就会缓存request,等待空闲来到再进行转发。这样提高了系统的弹性。
部署nginx其实并没有什么区别,因为通过gunicorn启动的服务对外也只有一个ip:port
注意:我们这里是把静态文件直接通过nginx进行转发的,而不是通过web服务的模板引擎。这充分利用了nginx的高性能。
1 |
|
热加载配置文件
1 |
|
高性能
简单的系统更容易达到高性能
早期的计算机系统 是没有操作系统的 只有输入 输出 计算
手工输入的速度远低于计算机的计算速度
于是出现了批处理操作系统 缺点是只能有一个任务 当系统进行I/O处理的时候 CPU是空闲的
后来发明了进程 一个进程代表了一个任务 多个进程通过分时操作能让用户认为并行操作多任务 进程之间的资源是独立单元 但是可以通过介质进行通信(但是只能串行处理 无法很好分工合作)
后来就有了操作系统调度的最小单元线程 线程能够使进程内的子任务能够共享进程内的资源 并并行工作 大大提高性能
线程是任务调度的最小单元 共用进程内的资源
进程是资源分配的最小单元 与其他进程资源相互独立
高可用
系统无中断地执行其功能的能力 代表系统的可用性程度 是进行系统设计时的准则之一
本质上都是通过“冗余”来实现高可用
可扩展性
低成本、安全、规模