多线程和多进程的资源消耗对比

1、测试环境配置如下:

        虚拟机:Ubuntu16.04     4G内存    双核处理器

        运行环境python+flask+gunicorn+nginx 

        flask 、nginx和 gunicorn 安装方法都非常简单粗暴:sudo apt-get install 就好

        附上一个安装教程点击打开链接

        这里我们为了使用一个域名来代替访问默认的127.0.0.1:8080,将配置nginx如下:

在/etc/nginx/conf.d 下新建文件flask_nginx.conf
添加如下内容:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
server { 
        listen  80; 
        server_name www.flasktest.com; 
        location / { 
            proxy_pass  http://127.0.0.1:8080; 
            access_log /home/api_access.log; 
            proxy_read_timeout 300; 
            } 
 
 
}
在/etc/hosts文件中新增一行 127.0.0.1  www.flasktest.com

通过如上配置,我们就可以通过访问www.flasktest.com域名来访问127.0.0.1:8080端口下的内容啦~

2、具体代码:

from flask import Flask,request,jsonify
from flask_restful import reqparse, abort, Api, Resource
import time



app = Flask(__name__)
api = Api(app)

# 这是第一个接口
class task_1(Resource):
    def get(self):  #这里的get函数,指定处理get请求
        parser = reqparse.RequestParser()
        parser.add_argument("url", type=str, location="args", required=False)
        parser.add_argument("type", type=int, location="args", required=False)
        parser.add_argument("id", type=str, location="args", required=False)

        params = parser.parse_args(strict=False)
        print(params)
        if params['action'] == 'fresh':
            #run something
            return 'vuln.cn demo 1'
        else:
            #run something
            return 'hello vuln.cn'
            


# 这是第二个接口
class task_2(Resource):
    #global num
    #num = 1000
    
    def get(self):
        #global num 
        #num -= 1
        s = time.time()
        count = 0
        for i in range(0,1000000): //实现cpu计算
            count += i
        #time.sleep(2)   //实现I/O
        parser = reqparse.RequestParser()
        parser.add_argument("id", type=str, location="args", required=False)
        params = parser.parse_args(strict=False)
        #run something
        e = time.time()
        run_time = e - s
        res = {}
        res['time'] = run_time
        #res['num'] = num
        return res
        
        
        
#路由地址分别对应处理的类
api.add_resource(task_1, '/demo1/')	#实现接口:http://127.0.0.1:8080/demo1/?url=xxx&type=xxx&id=xxx
api.add_resource(task_2, '/demo2/')	#实现接口:http://127.0.0.1:8080/demo2/?id=xxx

if __name__ == '__main__':
    app.run(debug=True)

这里我们只使用了接口二:同时因为我们之前在nginx下的配置,我们也可以通过访问http://www.flasktest.com/demo2/?id=xxx来进行实验。

程序中for循环是为了获得cpu计算所消耗的时间,而sleep则是为了获得I/O所消耗的时间。

3、使用gunicorn在服务器端启动多进/线程

    启动多个进程:

        gunicorn -w 40 -t 60000 flask_rest_test:app -b 0.0.0.0:8080

        参数解释:-w 指定启动的进程数

                        -t  指定超时时间  默认30s

                        flask_rest_test:app  前半部分为文件名称,后半部分为app的名字,对应代码中app = Flask(__name__)

                        -b 指定IP和端口号执行 0.0.0.0 表示接受所有IP访问

    启动多个线程:

            gunicorn -w 1 --threads 40 -t 60000 flask_rest_test:app -b 0.0.0.0:8080

            参数解释:与上面相比多出了一个threads参数

                        --threads 指定启动的线程数

4、使用CURL发起多并发请求

    脚本如下:新建formuti.sh,内容如下:

    

stime=$(date +%s);
#echo "${stime}";
for((i=0;i<700;i++));
do
{

curl -v http://www.flasktest.com/demo2/?id=2222;

}&
done
wait

etime=$(date +%s);
((run_time = etime - stime));
#((run_time = run_time * 1000))
echo "${run_time}"s;
#echo $num;

这段代码表示同时发起700个并发请求,程序中&表示 去并发提交函数中的内容,而不是执行完一个,再去循环执行下一个。

wait表示前面的程序全部执行完,才会继续执行下面的命令。

5、实验结果

0-1000000加法:

sleep2秒的时间消耗:

6、总结

        对于cpu计算来说,越高并发并且开启的进/线程越多,同等情况相比较而言,线程执行时间越短。其他情况则进程执行时间较短。对于cpu计算来说,并发数和开启进/线程都较低的情况,选用多进程为更好的选择,若并发数目过高和开启的进/线程较多的情况,易选用多线程。

       对于I/O来说,并发数目和开启的进/线程较少的情况下,运行时间相差无几。当并发数远远大于开启的进/线程时,进程运行时间较短,但是存在访问被丢弃。其他情况则线程运行时间较短。另外开启进程数目过多,非常容易卡死。所以对于I/O来说,多线程为一个更好的选择。






        



阅读更多

没有更多推荐了,返回首页