V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
firefox12
V2EX  ›  程序员

如果用 AWS 进行百万用户压力测试 第二部分

  •  
  •   firefox12 · 2016-05-05 23:26:51 +08:00 · 5485 次点击
    这是一个创建于 3118 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如何搭建 AWS 系统

    刚才我们已经简单使用了一下 aws ,现在开始一些准备

    获取证书

    从首页进入安全证书

    AWS 有很多种安全方法,我们选择第三个访问密钥

    然后你可以看到你现有的安全凭证

    选择生成一个安全证书,妥善的保管它!

    注意!

    安全证书很重要 很重要。网上有无数人因为证书泄漏,被人恶意的挖矿,爬虫,攻击等等,白白花费了 aws 的费用,。所以一定要保管好,要保管好,要保管好! 重要的事情说 3 遍。

    如果发现证书丢失,赶紧上网注销证书!

    申请一个密钥对

    点击 EC2 面板,选择密钥对

    生成一个密钥,给它取一个名字

    下载密钥

    这个名字很重要,编码的时候会用到

    用 linux 主机转换这个密钥 可以参考 http://blog.csdn.net/iamshaofa/article/details/7878346

    用 SecureCRT 登录, 需要根据 xxx.pem 生成一个公钥文件 xxx.pem.pub 。不过生成*.pub 还是需要 linux 下进行:

    $ chmod 700 xxx.pem

    $ ssh-keygen -y -f xxx.pem >xxx.pem.pub

    就是说,先改一下*.pem 的权限,然后再用 ssh-keygen 制作 pub 文件

    证书和密钥的区别:

    证书可以访问你的服务,权利非常大, API 开发需要利用证书,对你的请求进行签名。是你用户身份的标识 密钥对是弹性云计算中主机访问使用时候使用的密钥,没有它你无法连接上新创建的主机。

    测试过程

    一个分布式系统,从 0 开始构建,我是按照下面的步骤进行

    1. 搭建主机资源,为主机安装基本的操作系统,以及基本的网络设置如 IP,路由
    2. 配置基本的网络资源,划分子网,带宽,网络端口开放
    3. 主机上安装基本的软件,打开防火墙端口,修改内核参数
    4. 编译所有需要用的软件,准备所需要的软件包,也包括依赖的软件包
    5. 为所有的主机准备启动,停止,监控所需要的配置文件,脚本
    6. 为所有的主机部署所需要的各种软件,保证安装正确,所有的配置文件和脚本安装正确
    7. 将预制数据准备进系统
    8. 启动监控系统,
    9. 开启压力测试程序,在监控系统对进度做监控
    10. 压力测试完成后,停止所有服务
    11. 检测压力测试的数据结果,看结果是否符合要求
    12. 销毁所有主机和网络资源
    13. 检测压力测试中的系统记录数据,画出对应的状态变化曲线。

    如果是网站测试的话,我认为可以把软件安装这部分 改为为安装 http 服务器, tomcat ,数据库, Php/Java 程序,准备 Memcached/redis, LVS 代理 这样的业务。实质只是运行的软件不一样,但是流程上大同小异。

    实现的过程

    1.搭建主机:

    我们可以在网页里一步步的点,如果是这样做,云计算就完全没有存在的必要,所以我们需要使用 AWS 提供的 API 接口,创建我们的主机, VPC 网络,最后利用 API 销毁这些主机。

    2.编译所有的软件包:

    一般公司使用 jenkins 对软件包进行编译,打包,单元测试这些过程。如果是持续开发的环境,这样的系统是必备的。目前从 0 开始,我把过程简化成为一个 shell 脚本,编译完成所有的软件。

    3.为所有的主机准备脚本:

    写了一个简单的脚本,可以为系统准备随机数据,为每台服务器准备它们需要的启动脚本,停止脚本, redis 启动,清空等一系列脚本。

    4.为所有的主机安装软件和脚本:

    很明显我们需要一个开源自动化配置管理工具,选择非常多 Saltstack, cfeng, puppet 以及 ansible. 在不考虑语言本身的差异,这几个软件差异并不大,考虑到目前的实际情况,我认为在这个项目中 ansible 有一个比较好的优势:使用 ssh 无需为每台服务器安装相应的客户端,这非常方便。并且执行的批处理也很简单。所以我选择 ansible 作为部署软件。

    5.启动和停止服务:

    用 ansible 批处理的形式完成

    6.监控:

    需要一个监控的服务,可以对测试的情况做及时的捕捉,掌握状态。已经提供了部分 zabbix 系统的脚本,但是完整实现还需一些代码,所以目前写了直接写屏软件,用它记录各个服务器压力测试的状态,类似股票市场的监控图。因为服务器的各个时间点状态,都有记录所以可以在后期做测试。 它看上去是这样的

    7.事后分析:

    已经有专门的脚本支持

    整个系统的数据准备,软件编译,分发,部署,测试命令分发,我都在一台主机 10.0.1.11 上完成,这是唯一可以连接 internet 的服务器。这样其他所有的主机都无需连接 Internet ,可以节省网络费用。 fakewechat 使用是 Go 语言编写,所以不存在第三方库依赖问题,非常适合快速部署。

    题外话:

    从发布测试成熟度来看,我认为可以分为几个阶段, 第一个阶段就是茹毛饮血 hardcode 的脚本时代(就像我目前做的),第二个就是 自动脚本时代, 第三代 就是 service 时代,第四代则是智能管理时代。我觉得,在云时代,企业产品云化需要这样的服务。

    构建虚拟机环境

    脚本是一年多以前写的,语言 python, 类库 boto2 , 目前 boto 版本是 3.

    位置: https://github.com/xiaojiaqi/fakewechat/blob/master/aws/create_vpc.py

    只需要用修改几个参数就可以完成

    脚本很简单,它大概做了一下几件事情

    1. 创建一个 VPC
    2. 创建一个 Internet 的网关
    3. 将创建的网关加入 VPC
    4. 创建为网关创建一个路由
    5. 创建 4 个子网分别是 10.0.1.0/24,10.0.2.0/24,10.0.3.0/24,10.0.4.0/24
    6. 创建安全组,让所有的主机可以通信
    7. 创建一台主机 10.0.1.11
    8. 创建多台主机 IP 从 10.0.2.20 开始

    运行文件即可,大概 1 , 2 分钟。几十台服务器就已经安装,配置完成。 IP 网关也配置完成。 步骤 1 , 2 完成

    构建软件 安装

    现在使用 SecureCRT 连接服务器

    SecureCRT 的配置过程是这样的

    创建一个连接

    将主机的 IP 设置进去,(服务器 IP 可以从控制台获得,也可以用 DNS 管理)

    如果是 RHEL 则默认登录用户是 ec2-user, 大部分 Linux 是 root

    设置公钥文件,选择 刚才转换好的文件

    接受密钥,完成连接

    实践过程

    我们假设最先登录的主机为 10.0.1.11,它有外部 IP. 但是我们简称它为 10.0.1.11 主机,下面的操作都是在这台主机上完成的

    系统部署

    1. 首先安装 git 工具
    2. 在当前目录创建 gopath/src/github.com, 进入$HOME/gopath/src/github.com/ 克隆整个项目
    3. 进入$HOME/gopath/src/github.com/fakewechat/package 运行 install.sh 脚本,脚本主要做了几件事情
    • 利用 yum 安装了所需要的 gcc 等工具
    • 下载 golang 的安装包,解压,并设置环境
    • 编译项目,生成所有的可执行文件
    • 编译 redis 服务器,生成需要使用的 redis-server 和 redis-cli 可执行文件
    • 导入 RPM-GPG-KEY-EPEL-7, 并安装 ansible 包
    1. 修改 /etc/ansible/ansible.cfg 文件 大概 38 行左右,去掉这个注释。 这样 ansible 连上新的主机,就不需要确认了。

    5. 进入进入$HOME/gopath/src/github.com/fakewechat/bin 运行 deploy.sh 脚本主要完成了下面的事情 - 运行 listcm.py 脚本,为每一台主机生成它们需要的配置文件和启动脚本,关闭脚本,数据载入脚本,结果校验脚本,收集脚本这样一些列的脚本。 - 自动生成部署需要的 ansible 脚本 - 在本地生成初始数据 - 生成主机 IP 列表,并将主机 IP 列表配置到 ansible 的 hosts 文件中,这样 ansible 可以对所有主机进行控制 - 运行部署的 ansible 脚本,将所有的初始数据和程序,系统配置文件都部署到主机上,并设置权限 - 为每台主机重新设置内核参数,并关闭防火墙 - 在每台主机上,启动 redis 服务 - 在每台主机上,将初始数据载入 redis 服务器 - 启动服务器的监控服务器 - 启动服务注册发现服务 - 在每台服务器上,启动服务程序,让服务程序自动注册

    做到这一步就完成了大部分的准备工作 (默认的配置是 4 个 rg, 每个 rg 是 1000 位用户,在运行前,修改脚本 num_rg 代表 rg 的数目 rg_size 代表这个 rg 里的用户数目 如果是 100 万用户,可以采用 40 台主机,每台主机 2.5 万个用户的配置)

    系统测试

    1. 重新建立一个连接,通过 10.0.1.11 主机,跳转进入 10.0.2.20 主机,运行 monitorclient . 这样我们就可以
    2. 在 10.0.1.11 主机上利用 screen 启动所有的压力测试客户端 运行一下命令启动测试客户端 screen ansible all -f 40 -a "$HOME/bin/client.sh" 使用 screen 的原因是,我们可以将它切入后台。当我们和 10.0.1.11 的网络断开的时候,不会意外打断我们的测试。 因为测试可能要运行几个小时。
    3. 观察状态变化。当所有的客户端显示完成的时候,表示成功。
    4. 在 10.0.1.11 运行 命令,这个命令会让每个主机,对完成的结果校验,并将结果写入文件 运行以下命令启动校验结果 screen ansible all -a "$HOME/bin/checkdb.sh"
    5. 利用收集脚本将数据收集到 10.0.1.11 上面,把结果数据拖回本地
    6. 利用脚本,关闭所有的主机!这个每分钟都是钱 运行以下命令关闭所有的 ec2
    7. 慢慢的整理结果 完毕

    结果对比

    数据分布

    脚本总共生成了 100 万位用户,用户之间的相互关系 29741136 条,平均每位用户接近 30 条。其中每位用户在同一个 rg 的关系为 20 条,跨 rg 的关系为 10 条。每位用户向自己的好友发送 5 条消息,测试共产生了 1.4 亿条(148705680)条消息,并完全正确接受。经过验证数据的没有问题,每位用户都成功发送了消息,也成功接受了消息。 因为消息需要跨服务器进行交互,从侧面证明,系统不是单独在单机上运作,是全集群有消息交互的。

    性能比较

    1 台服务器 和 2 台服务器的数据可以见

    4 台服务器处理 10 万用户, 40 台服务器处理 100 万用户 对比

    可以看到 计数器显示,系统的吞吐数据有接近线性的增长,这表明软件原型 在 100 万级别有水平扩展的能力。

    教训

    仔细回想了一下,经验收获不多,但是教训有一些。列下来引以为戒吧!

    1.数据注入成为瓶颈

    最开始的设计,在 10.0.1.11 上将所有的数据准备好,然后导入 redis 服务器。开始一切都很好,当开始百万用户级别的时候,导入这些用户的时间就让人无法接受,每台主机需要接近 10 分钟才能导入完成。 40 台主机就是 400 分钟。这是极大的浪费。所以 流程改进为改完所有的数据文件,复制到每一台主机上,用 golang 的程序载入,基本做到了几十秒内完成。

    教训: 大规模并发服务,任何地方都不能单点运行,当规模扩大了,缺陷也立刻被放大。

    2.T2.Mircor 导致 CPU 挂起

    一开始希望用低端的主机,实现"蚂蚁吃大象"的办法完成百万级用户测试,但是到最后的时候,因为 CPU 分数用尽,导致系统基本停止。最后只有换比较高端的主机。

    教训 对系统的 CPU 使用情况没有仔细分析,对 AWS 主机分类理解不够

    3.配置 bug 导致端口冲突

    生成配置的脚本 bug ,导致某台主机的端口冲突,引起某个服务自动下线。最后在监控上发现服务数目不够,才查到了原因。

    教训 监控需要更加智能,更细致。

    4.网络不畅导致断线

    连接 AWS 的网络连接并不稳定,结果某次断线,导致测试中断,最后重新测试

    教训: 需要长期运行的程序 应该用 screen 这样的程序放到后台, 更好的办法是 service 化。 此外如果程序不是无状态的,就无法重试继续,需要对流程进行改进。

    5.小细节导致流量暴增

    本来监控程序的刷新频率,靠业务数据驱动,每次有更新就自动刷新,用户少的时候,没有问题。当 40 台服务器一起更新的时候,刷新速度就没办法看了,导致流量涨得太高。 只能改成每 3 秒刷新一下

    教训 品质细节需要实践

    6.进程部署是瓶颈

    虽然使用了 ansible 分发程序,但是可以看得出分发过程,仍然是系统的瓶颈,同时也是个单点故障。这套部署架构并不适合更多的主机。

    教训 大规模云计算系统里应该利用 p2p 进行程序部署,分发。

    账单问题

    AWS 的账单可以从这里看

    账单的组成部分:

    点击查看详单

    流量部分

    主机部分

    价格可以从这里看

    http://aws.amazon.com/cn/ec2/pricing/

    总之,用完以后,立刻删除所有的资源!

    最后提醒一下, AWS 的客服非常好!有任何问题都可以直接和他交流,可以很快得到解决。

    如果觉得对项目有兴趣可以访问 https://github.com/xiaojiaqi/fakewechat 本文地址 https://github.com/xiaojiaqi/fakewechat/wiki/Stress-Testing-in-the-Cloud 会持续更新

    如果觉得有收获,让我知道 0.01 元

    支持一下你的项目 1.00 元

    8 条回复    2016-05-06 10:34:03 +08:00
    alang
        1
    alang  
       2016-05-06 00:30:33 +08:00
    如果?如何?
    现在的年轻人真的不注意标题错别字么?
    binux
        2
    binux  
       2016-05-06 00:42:26 +08:00
    既然都用 AWS 了,你可以用 Launch Configuration 的 user data 自动部署啊。
    还是那句话,你这样的玩法,和随便到哪申请一大批 VPS 没有区别。
    isnowify
        3
    isnowify  
       2016-05-06 00:47:54 +08:00 via iPhone
    自己压力测试后申请退款??
    imlonghao
        4
    imlonghao  
       2016-05-06 00:54:30 +08:00 via Android
    通常来说,是十分不建议直接用根证书的,一旦泄露整个账号就 GG 。推荐使用的是 IAM ,赋予好相应的权限,安全性很好一些。
    ---
    凭什么免单?难道这算是 unexpected charges 么?
    azh7138m
        5
    azh7138m  
       2016-05-06 08:12:13 +08:00 via Android
    申请退款是不是不太厚道啊
    Citrus
        6
    Citrus  
       2016-05-06 08:28:04 +08:00 via iPhone
    如果最后一个申请真的是测完要求退款的话,那问题就有点严重了。。。
    firefox12
        7
    firefox12  
    OP
       2016-05-06 10:21:23 +08:00
    no, 我申请按照普通 t2.mirco 收费,而不是 RHEL, 因为我看到 Linux 是 0.02$. RHEL 我自然认为是一种 Linux 。
    并且计费时间有出入, 40 个 instance 我认为没有使用这么多时间,最后客服直接给免了。

    这个申请是在测试以前,你没看到所有的 instance 类型都是 t2.micro 吗?
    ladyv2
        8
    ladyv2  
       2016-05-06 10:34:03 +08:00
    aws 的性能比 azure 还是差太多。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   884 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 22:21 · PVG 06:21 · LAX 14:21 · JFK 17:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.