干货 | Python后台开发的高并发场景优化解决方案

640?wx_fmt=jpeg


嘉宾 | 黄思涵

来源 | AI科技大本营在线公开课


互联网发展到今天,规模变得越来越大,也对所有的后端服务提出了更高的要求。在平时的工作中,我们或多或少都遇到过服务器压力过大问题。针对该问题,本次公开课邀请到了金山办公AI平台研发工程师黄思涵,他分享的主题是《Python后台开发的高并发场景优化解决方案》,为大家讲解不同业务场景下这类问题的解决思路和方案。本文是直播公开课的速记版,视频回放请见↓↓↓


  

1 背景

 

我们看一下今天的课程内容。首先我们来看一组数据。第一个数据是春晚红包,相信大家在今年春晚,大家已经用过这个功能;互动游戏数据是互动次数达到了208亿次。在晚上的短短四个小时之内,去完成了这样的请求量,说明这个互联网的规模是非常大的。把它平摊到14.8亿人的头上,平均每个人也是点击了14.8次,这当中还没有算上这些非网民的次数,所以说,整个互联网的规模是非常庞大的。

 

640?wx_fmt=jpeg

 

再接下来,我们再看一个双十一的一个数据,这个双十一的订单量,在去年数据是13.52亿订单量,我们再看一下,在这个屏幕,左边这里有一个图,从2014年,它大概是1点多亿件,到2015年会有一个增长,到了四点多亿件,到2016年,这边是逐渐的增长,直到2018年增长到了一个13亿次的一个订单量,那么有了这样的订单量,大家可以看到互联网规模的迅速发展,它是逐年在增加的,说明发展速度是非常快。

 

接下来,我们再看一个数据,那么就是微信,也是平时大家用的比较多的一个软件。微信的日活可以达到十个亿,相应的一个请求量,可能比这个更多。那么看这些数据,它有一个什么意义?这样的一些数据,它就说明了,我们的互联网的一个规模是非常庞大的。而且它的增长也是非常快的。这就引出了今天的一个问题,那么也许大家平时在一些开发过程当中,或者在大家自己的遇到的一个业务场景当中,没有前面那么多比较恐怖的数据,但是,大家知道,公司要去增长,我们的业务要增长,业务的增长,就意味着用户量会去增加,用户量增加就导致了一个请求量的增加。请求量的增加对我们开发人员来讲,或者对我们后台的服务器来讲的最直接的反映,就是服务器压力的增加。那么压力的增加就意味着对服务器来讲,它的一个请求量到达了一个比较高的水平,或者说它的压力呢,已经不能够继续往上增加了,那么请求量已经到达了一个瓶颈。

 

640?wx_fmt=jpeg

 

接下来,我们看一下,它会导致的直接的问题是什么?大家可以看到这样一个简单的模型。左边是一个客户端,右边是一个服务端。客户端向服务端发出请求,当服务端压力过大的时候,对服务器来说,那么就是请求太多,来不及处理,甚至是这样的请求呢,它还会被丢弃掉。但是,对于这个客户端来讲,或者是使用这个客户端的一个用户来讲,它可能面临的一个问题,就是等待时间过长,或者是出现错误,对客户来讲,客户端来讲,他并不知道,你这个后台是面临着这样大的一个压力,或者是你能处理的请求是多大的一个数量,他只能直观感受到,我这个请求时间长,或者我这个请求有问题。这在我们的业务场景当中都是不能接受的。

 

640?wx_fmt=jpeg

 

所以,今天我就将跟大家去探讨一下,如何尽可能多的去处理这样的一个客户端的请求,对于我们来讲,这个服务端的压力大,最简单的来讲就是资源不足。我们可能第一印象就是这个资源不足,那么资源不足呢,非常简单,就是去提升硬件配置,比如说这里CPU,或者是内存,直接去升级硬件就可以了,这样是一个简单的处理方式。但大家有没有想过,还会有一种问题,这种场景下面,就是当我资源充足的情况下,我的一个服务器的请求依然不能够进行提升,或者请求还依然维持在一个比较低的水平,不能够将我所有的资源进行一个很好的利用。这就存在着一个浪费的问题,它的性价比呢,就是不高的。


640?wx_fmt=jpeg


2 优化思路和方案

 

接下来,我们今天呢,主要就是针对下面的这种情况,会去给大家分享我们优化的思路和方案。说到服务端的压力大,最简单的可能想到的一个原因,就是CPU。毕竟CPU在计算机当中处于一个非常核心的位置。

 

查看CPU使用情况


640?wx_fmt=jpeg

 

我们先来看一下CPU。我使用TOP命令在这个主机上,去查看CPU的使用情况。在这里,我截了一个图,这个图中,CPU使用率是接近于百分之百,说明CPU,已经是完全被代码,被测试程序是完全占满了。所以它就导致了请求量无法去再进行一个提升。它也就是说明我这个资源不足了。如何解决呢?那么就是去增加资源,去升级这样的一个CPU,这就是我讲的一个比较简单的一个场景。

 

640?wx_fmt=jpeg

 

大家有没有想过另外一种情况,假如说我的CPU它的利用率是在非常低的水平,比如这里,它只有这样一个大概1/10的一个利用率,但是在这个情况下,我的一个请求数量依然不能够增加,我的服务器的压力依然很大。如果在这种情况下,要去给老板说,我这个请求无法提升,我需要去增加配置,这样的话,老板看到这样的情况肯定不会很满意,因为你资源明显没有占满,你还要去申请这样的一个机器。我们继续去查看它的详情,在这里我使用这个TOP命令,在这个之后继续去按一个一,就可以展开四个CPU的一个详情,这里呢,我的CPU是四核心的,看到这里有四个CPU的核心数在这里运行,大家可以看到在这里,第一个确实是占满了第一个核心,但是呢,后面的三个是在这里,空闲的,这说明了一个什么问题呢?就是在前面的这个程序当中,实际上它对整个CPU的一个利用,只是用了它的一部分,而没有全部用,没有全部去用上,那么这种情况,解决方案就变得比较简单了。大家可以想一下,如何去解决呢?很显然,就是要将这样的一个CPU,其他的核心数,全部用起来。另外在现在的CPU几乎都是多核心的,这里我们要尽可能的多的使用我们已有的资源。这里有同学说的多进程,所以我们就可以考虑使用多进程,将所有的CPU去给它利用起来,尽可能的多的使用我们已有的资源。

 

多进程

       640?wx_fmt=jpeg 

接下来,我使用Python去给大家讲解一下,如何去使用多进程,来利用这样的一个资源。这里我贴了一段代码,这个代码是Python去实现的一个多进程,然后来利用多核CPU完成任务。

        640?wx_fmt=jpeg


这里我大概给大家讲一下。在Python当中,我们使用multiprocessing这个库去完成这样的一个多进程,这里有一个-1大家要注意一下,通常我们会去留下这么一些核心数,去用作其他的一些任务,防止整个所有的核心数被占满导致其他的任务不能够正常运行。这里算出一个核心的CPU数。下面我是用了一个进程池,进程池大概是一个什么概念呢?这里用了Pool函数,这个函数,会创建出这样一个进程池。创建出了这样的进程池之后,下面它会在当中去加入这样的一些任务,这个Task它实际上是写的一个函数。在这里,就将它加入到这样的一个进程池当中。


实际上,它是异步加入的,会有一个队列,这些任务都会被在非常短的时间内加载到下面的这样的一个队列当中,由于这上面已经有了进程池,这个multiprocessing帮我们实现好了。它会去创建好一些进程,创建好之后,它会自动去把这些加入进来的任务呢,放到这个进程当中去进行调度,然后执行。当前面的一些执行完了之后,后面的议程会再次被调度进去,这个进程池它相对于普通的直接去创建进程的方式有什么好处呢?如果我们直接去创建这样进程,比如有一个任务,我就创建一个进程,然后当这个任务执行结束之后呢,我再销毁这个进程,这样创建和一个删除的过程都会有这样一个开销,这里使有进程池,它就会很好的去解决这样一个问题。接下来,Close,就是去当你不需要加入的时候,就对它进行一个Close掉,Join在这里是进行一个阻塞等待,这里给大家讲了这一段代码,大概做了一个什么事情。

       640?wx_fmt=jpeg


下面,我就给大家看一下我是如何去测试这样的一个多进程,如何去进行一个对比的。我执行的测试流程,是这样的一个流程:首先我会创建了一个队列,这个队列是一个全局的一个队列,而且它在这些进程当中是进行共享,当然它是用的multiprocessing当中的一个队列去实现的。然后,下面会有一个循环,当然这个是单进程的时候,下面会有一个循环,然后循环每次从这个队列当中,这个队列当中去拿一个操作号,这个队列它是从0到9这样的一个数组,从0、1、2、3、4一直到9,这样的一个序列。后面,我在这里会拿到了一个执行号之后,然后再去执行的一个函数,执行了这个函数;下一次循环,就是再次从这个队列当中去再拿出一个执行号,拿出执行号之后,再执行一下这样的一个函数,最终执行结束,当队列为空的时候这里就执行结束了。

 

这里我再给大家说一下,这个函数是一个什么函数呢?是这边定义的一个计算斐波那契数列的一个函数,这个函数使用递推实现的。说到这个斐波那契数列可以给大家提一下,斐波那契数列大概是长这个样子,写出来可能大家就知道了,第一,1、2、3、5,然后是8,这样的一个数列。就是前两个数相加就等于后一个数,这样的一个数列。我实现它的方式是实现递推实现的,为什么使用这样一个函数在这里呢?比较简单的一个理由,就是它比较耗时,我没有进行优化。耗时的话,我这里就可以去清楚地来对比单进程和多进程它们之间的一个优化的一个那个结果,那么多进程的时候,同样是有一个全局的队列。全局的队列之后呢,下面会有多个进程,同时在这个队列当中去拿这个操作号,依然是0到9操作号。拿了操作号之后,每一个进程独立的去拿到进程号之后,独立的去执行斐波那契数列,直到这个执行为空,这个队列为空的时候,就算作是整体执行结束。

 

这里讲了我的—个测试脚本的流程之后,我们来看一下它的结果。在单核的时候,它也就是前面我执行这个单进程的时候,它依然是把一个核心代码,这样我是展开来看的,一个核心代码。后面使用多核的时候,大家可以看到,它将所有的核心数几乎都是再一个比较高的使用水平上面,这里呢,我的代码呢,它并没有去留下一个核心数来作为预留,因为我为了去测试它的效果,让它看起来更明显,我直接将四个核心都用上了,这里大家也可以看到它的执行时间的结果,当使用单线程的时候是15秒,使用多进程的时候是在4.8秒。它看起来大致是在一个4倍的一个左右的时间,当中要考虑这个进程的开销,它这个4倍是一个理论值。

 

这里讲到多进程,大家可能有些同学也会有有想,既然多进程可以,那么我们是否可以用多线程实现呢?是的,多线程也能完成这样的一个工作。

 

多线程


接下来我们看一下多线程如何去执行,首先在这个进程的使用进程的时候,它的进程时间的通信是比较不方便的,因为大家知道这个进程是系统分配资源的一个最小单位,所以说呢,它这个一些变量,包括你要在进程之间去进行共享数据,这样的时候

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值