1. 程式人生 > >多執行緒和多程序的資源消耗對比

多執行緒和多程序的資源消耗對比

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來說,多執行緒為一個更好的選擇。