虚拟机类型
Name | RAM | VCPUs | Volume |
---|---|---|---|
m1.tiny | 512MB | 1 | 10GB |
m1.small | 2GB | 1 | 10GB |
m1.medium | 4GB | 2 | 10GB |
m1.large | 8GB | 4 | 10GB |
测试指标
- 随机读写的性能
- 连续读写的性能
- web服务性能(nginx)
a. 直接返回
b. 静态文件(图片,或者txt)
c. 动态资源(动态渲染)
自己写个web application 然后使用模板渲染
测试方法与结果
读写性能
测试工具:fio
安装方法:
wget http://brick.kernel.dk/snaps/fio-2.2.5.tar.gz
yum install libaio-devel
tar -zxvf fio-2.2.5.tar.gz
cd fio-2.2.5
make
make install
使用方法:
- 随机读:(可直接用,向磁盘写一个2G文件,10线程,随机读1分钟,给出结果)
fio -filename=/dev/vda -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest
- 随机写:
fio -filename=/dev/vda -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest
- 连续读:
fio -filename=/dev/vda -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest
- 连续写:
fio -filename=/dev/vda -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest
- 混合随机读写:
fio -filename=/dev/vda -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest -ioscheduler=noop
说明:
filename=/dev/sdb1 测试文件名称,通常选择需要测试的盘的data目录。
direct=1 测试过程绕过机器自带的buffer。使测试结果更真实。
rw=randwrite 测试随机写的I/O
rw=randrw 测试随机写和读的I/O
bs=16k 单次io的块文件大小为16k
bsrange=512-2048 同上,提定数据块的大小范围
size=5g 本次的测试文件大小为5g,以每次4k的io进行测试。
numjobs=30 本次的测试线程为30.
runtime=1000 测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止。
ioengine=psync io引擎使用pync方式
rwmixwrite=30 在混合读写的模式下,写占30%
group_reporting 关于显示结果的,汇总每个进程的信息。
测试结果:
类型 | 随机读 | 随机写 | 连续读 | 连续写 |
---|---|---|---|---|
m1.tiny | IO带宽:111.4MB/s, IOPS:7131 | IO带宽:111.2MB/s, IOPS:7118 | IO带宽:111.6MB/s, IOPS:7144 | IO带宽:111.5MB/s, IOPS:7137 |
m1.small | IO带宽:111.3MB/s, IOPS:7124 | IO带宽:111.3MB/s, IOPS:7127 | IO带宽:111.4MB/s, IOPS:7134 | IO带宽:111.4MB/s, IOPS:7128 |
m1.medium | IO带宽:111.3MB/s, IOPS:7124 | IO带宽:111.4MB/s, IOPS:7130 | IO带宽:111.5MB/s, IOPS:7137 | IO带宽:111.5MB/s, IOPS:7136 |
m1.large | IO带宽:111.5MB/s, IOPS:7132 | IO带宽:111.4MB/s, IOPS:7123 | IO带宽:111.7MB/s, IOPS:7144 | IO带宽:111.4MB/s, IOPS:7131 |
整体来看,各类型的虚拟机读写性能都差不多,似乎和CPU、RAM等性能参数没什么关系,但如果同时跑性能测试就都会同时下降。
web服务性能(nginx)
nginx.conf:
user nginx;
worker_processes 1;(可以为CPU核心数)
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 10240;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
#include /etc/nginx/conf.d/ *.conf;
upstream tornado_online {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
} (进程数可以为CPU核心数)
server {
listen 80;
location = /detect {
add_header Content-Type "text/plain;charset=utf-8";
return 200 "Success";
}
location /html/ {
root /usr/share/nginx;
index index.html;
}
location / {
proxy_pass http://tornado_online/;
}
}
}
启动 nginx 服务:
systemctl enable nginx
systemctl start nginx
在 /etc/sysconfig/iptables 中开放80端口:
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A OUTPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
在 /etc/sysctl.conf 中添加内容:
net.ipv4.tcp_syncookies = 0(是否打开SYN Cookie功能,该功能可以防止部分SYN攻击)
# net.ipv4.conf.default.rp_filter = 1
# net.ipv4.conf.all.rp_filter = 1
# net.ipv6.conf.all.disable_ipv6 = 1
# net.ipv4.tcp_max_syn_backlog = 819200
# net.ipv4.tcp_synack_retries = 1
# net.ipv4.tcp_max_tw_buckets = 819200
# net.ipv4.tcp_tw_reuse = 1
# net.ipv4.tcp_tw_recycle = 1
加载运行 sysctl:
sysctl -p
测试工具:ab
安装方法:
yum install httpd-tools
使用方法:
ab -n 100000 -c 1000 http://172.65.1.16/
其中-n表示请求数,-c表示并发数
请求数 n 为常量10k。
测试结果:
1. 直接返回
测试命令:
ab -n 100000 -c 1000 http://172.65.1.16/detect
测试数据:
1. 请求失败数
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 0 | 0 | 0 | 0 | 0 | 3584 | 7552 | 11584 | 15488 |
m1.medium | 0 | 0 | 0 | 0 | 0 | 3584 | 13504 | 35949 | 47616 |
m1.large | 0 | 0 | 0 | 0 | 0 | 4928 | 8576 | 15488 | 27872 |
2. 吞吐率(#/sec)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 11718 | 11624 | 9287 | 10644 | 9662 | 9762 | 9858 | 9000 | 8558 |
m1.medium | 12931 | 12112 | 13645 | 13617 | 13817 | 13489 | 13209 | 12440 | 13793 |
m1.large | 14069 | 13476 | 13100 | 12214 | 13217 | 13723 | 12487 | 13883 | 13264 |
3. 用户平均请求等待时间(ms)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 170 | 344 | 646 | 751 | 1034 | 1229 | 1419 | 1777 | 2103 |
m1.medium | 154 | 330 | 439 | 587 | 723 | 889 | 1059 | 1286 | 1304 |
m1.large | 142 | 296 | 458 | 654 | 756 | 874 | 1121 | 1177 | 1357 |
4. 用户最长请求等待时间(ms)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 7421 | 7227 | 8623 | 8626 | 9424 | 10219 | 9453 | 9426 | 10239 |
m1.medium | 3113 | 3297 | 3377 | 3767 | 3815 | 3804 | 2040 | 2159 | 2085 |
m1.large | 3087 | 3332 | 3489 | 3890 | 3731 | 1846 | 2186 | 2160 | 2479 |
5. 传输速率(Kb/sec)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 2323 | 2304 | 1841 | 2110 | 1915 | 1935 | 1880 | 1680 | 1696 |
m1.medium | 2563 | 2401 | 2705 | 2699 | 2739 | 2629 | 2441 | 2031 | 2083 |
m1.large | 2789 | 2671 | 2596 | 2421 | 2620 | 2653 | 2369 | 2484 | 2278 |
- 实测过程中,m1.tiny 可能由于 RAM 太小了只有512MB,所以很难支撑得起1万以上的请求量,错误信息为“apr_socket_recv: Connection reset by peer (104)”。
- 随着并发数增大,请求失败数会增大,吞吐率会降低,用户平均请求等待时间、最长等待时间都会变长,传输速率会降低。
- 多核与单核对比,请求失败数增多。
- 四核与双核对比,请求失败数减少。
- CPU 核心数越多,吞吐率、传输速率会变大,用户请求平均等待时间、最长等待时间都会缩短,用户请求等待时间方差会变小。
2. 静态文件(图片,或者txt)
测试命令:
ab -n 100000 -c 1000 http://172.65.1.16/html/
测试数据:
1. 请求失败数
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 0 | 0 | 0 | 0 | 0 | 3584 | 7552 | 11584 | 15360 |
m1.medium | 0 | 0 | 0 | 0 | 0 | 6464 | 21884 | 35194 | 48168 |
m1.large | 0 | 0 | 0 | 0 | 0 | 2752 | 6976 | 15552 | 27104 |
2. 吞吐率(#/sec)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 6271 | 6222 | 6539 | 6150 | 5891 | 5992 | 5948 | 6837 | 6364 |
m1.medium | 14258 | 13842 | 12293 | 13166 | 12726 | 13376 | 12683 | 13652 | 13223 |
m1.large | 14044 | 13323 | 13280 | 12815 | 12489 | 13161 | 12575 | 13110 | 13303 |
3. 用户平均请求等待时间(ms)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 318 | 642 | 917 | 1300 | 1697 | 2002 | 2353 | 2340 | 2808 |
m1.medium | 140 | 288 | 488 | 607 | 785 | 897 | 1103 | 1171 | 1361 |
m1.large | 142 | 300 | 451 | 624 | 800 | 911 | 1113 | 1220 | 1353 |
4. 用户最长请求等待时间(ms)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 15833 | 15841 | 13841 | 15845 | 15839 | 15843 | 15847 | 13832 | 13838 |
m1.medium | 3117 | 3287 | 3431 | 3595 | 3733 | 3721 | 4049 | 4549 | 4319 |
m1.large | 3087 | 3332 | 3489 | 3890 | 3731 | 1846 | 2186 | 2160 | 2479 |
5. 传输速率(Kb/sec)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 5175 | 5134 | 5396 | 5996 | 4861 | 4856 | 4723 | 5315 | 4848 |
m1.medium | 11766 | 11422 | 10144 | 10865 | 10502 | 10681 | 9321 | 9283 | 8309 |
m1.large | 11589 | 10994 | 10959 | 10574 | 10306 | 10711 | 10015 | 9977 | 9489 |
- 相对于直接返回测试,静态文件测试的文本传输量比较大,测试结果也稳定了很多,也基本验证了以上结论。
- 双核开2个nginx进程可以提升性能1倍,四核同理,不过四核开4个nginx进程没有明显的性能提升。
3. 动态资源(动态渲染)
安装 pip 并使用 pip 安装 Tornado、Mako、Supervisor(用于管理 Tornado 进程):
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py
pip install tornado
pip install mako
pip install supervisor
echo_supervisord_conf > /etc/supervisord.conf
mkdir /etc/supervisord.d/
在 /etc/supervisord.conf 里添加:
[include]
files = /etc/supervisord.d/*.conf
进入 /etc/supervisord.d/ 添加 tornado.conf:
[group:tornadoes]
programs=tornado-8000,tornado-8001,tornado-8002,tornado-8003
[program:tornado-8000]
command=python /var/www/main.py --port=8000
directory=/var/www
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info
[program:tornado-8001]
command=python /var/www/main.py --port=8001
directory=/var/www
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info
[program:tornado-8002]
command=python /var/www/main.py --port=8002
directory=/var/www
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info
[program:tornado-8003]
command=python /var/www/main.py --port=8003
directory=/var/www
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/tornado.log
loglevel=info
从我的 github 上下载测试所需的资源(一个 Tornado 应用文件和一个 html 页面):
wget https://github.com/linyihan2013/Toys/archive/master.zip
unzip master.zip
cd Toys-master/test
mkdir /var/www
cp -rf * /var/www
测试用的 html 文件 mybidong.html 就不在这里展示了,使用了 Mako 渲染引擎,以下是 Tornado 应用文件 main.py:
#-*- coding: utf-8 -*-
import os.path
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.options
import mako.lookup
import mako.template
from tornado.options import define, options
define("port", default=8888, help="run on the given port", type=int)
class BaseHandler(tornado.web.RequestHandler):
def initialize(self):
template_path = self.get_template_path()
self.lookup = mako.lookup.TemplateLookup(directories=[template_path], input_encoding='utf-8', output_encoding='utf-8')
def render_string(self, filename, **kwargs):
template = self.lookup.get_template(filename)
namespace = self.get_template_namespace()
namespace.update(kwargs)
return template.render(**namespace)
def render(self, filename, **kwargs):
self.finish(self.render_string(filename, **kwargs))
class MainHandler(BaseHandler):
def get(self):
self.render('mybidong.html',days='10',hours='6', coin='12')
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r'/',MainHandler),
]
settings = {
'template_path' : os.path.join(os.path.dirname(__file__),'templates')
}
tornado.web.Application.__init__(self, handlers,**settings)
def main():
tornado.options.parse_command_line()
application = Application()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
使用 supervisor 启动 tornado 进程:
supervisord
测试命令:
ab -n 100000 -c 1000 http://172.65.1.16/
测试数据:
1. 请求失败数
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 7116 | 18264 | failed | failed | failed | failed | failed | failed | failed |
m1.medium | 1191 | 4744 | failed | failed | failed | failed | failed | failed | failed |
m1.large | 8 | 19 | 112 | 515 | 50 | 934 | 454 | 2349 | 478 |
2. 吞吐率(#/sec)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 236 | 252 | failed | failed | failed | failed | failed | failed | failed |
m1.medium | 341 | 367 | failed | failed | failed | failed | failed | failed | failed |
m1.large | 639 | 621 | 614 | 590 | 592 | 650 | 605 | 551 | 651 |
3. 用户平均请求等待时间(ms)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 8446 | 15862 | failed | failed | failed | failed | failed | failed | failed |
m1.medium | 5855 | 10870 | failed | failed | failed | failed | failed | failed | failed |
m1.large | 3126 | 6433 | 9760 | 13545 | 16833 | 18453 | 23126 | 28986 | 27638 |
4. 用户最长请求等待时间(ms)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 91082 | 91239 | failed | failed | failed | failed | failed | failed | failed |
m1.medium | 126611 | 127171 | failed | failed | failed | failed | failed | failed | failed |
m1.large | 77900 | 125709 | 103526 | 155936 | 127823 | 126285 | 164847 | 180735 | 137254 |
5. 传输速率(Kb/sec)
类型 | 并发数2000 | 并发数4000 | 并发数6000 | 并发数8000 | 并发数10000 | 并发数12000 | 并发数14000 | 并发数16000 | 并发数18000 |
---|---|---|---|---|---|---|---|---|---|
m1.small | 1182 | 1058 | failed | failed | failed | failed | failed | failed | failed |
m1.medium | 1709 | 1779 | failed | failed | failed | failed | failed | failed | failed |
m1.large | 3237 | 3146 | 3108 | 2975 | 2996 | 3262 | 3051 | 2732 | 3281 |
- 四核的抗压能力比单核、双核好多了。
- nginx 进程并不需要为 cpu 核心数,因为主要是 tornado 后端进程比较繁忙,就算是四核,1个 nginx 进程也够了。
- tornado 进程数最好为 cpu 核心数,少则性能降低,多则没有提升。