JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

阿弟:从300qps至3000qps的优化之路

wys521 2024-10-07 16:38:48 精选教程 17 ℃ 0 评论

原文链接:http://www.postgres.cn/news/viewone/1/283原作者:阿弟 创作时间:2017-08-16 23:40:18

前言

现在的并发文章动不动就系统架构,虚得不行。网友阿弟写的这篇反而从零开始步步实操,是篇好文章,相当值得借鉴

背景

一个车货匹配项目,初步估计有100万司机。支持每秒500次查询最新货源列表,业务高峰时每分钟大约10万司机(包括大量无注册司机)在线查询最新的货源订单。即1500qps,当然还有很多低频率的业务,如每秒几笔货源订单。

环境准备: 测试资源是线下开发机,非生产环境

数据库服务器

CPU:至强 4核 单线程

RAM:32G

硬盘:7200转SAS 1T 2个做了raid1

OS:Centos 6.4

网卡:1000M

IP:192.168.1.6

应用服务器

CPU:至强 4核 单线程

RAM:32G

硬盘:7200转SAS 1T 2个做了raid1

OS:Centos 7.0

网卡:1000M

IP:192.168.1.10

交换机

H3C 1000M

平台初步技术方案

基于公司目前技术储备,我们可以选择使用的组件有nginx/apache/php/go/pgbouncer/pg,这些组件可以组合的架构还是很丰富的,原则上能满足业务需求的情况下,架构是越简单越好。复杂的架构出问题的机率越高

但很明显,整个系统的瓶颈肯定是在各种Api与数据库通信这一环节上面,这是优化的重中之重

测试环境服务组件版本号

PostgreSQL 9.4.1、nginx-1.6.2、apache-2.2.31、php-5.5.38、pgbouncer-1.5.4、golang-1.7.3

1、PostgreSQL 9.4.1

编译安装

初始化

参数配置

其它参数全部先默认

2、apache-2.2.31

编译安装

选择worker-mpm模式

参数配置

其它参数全部先默认

3、php-5.5.38

编译安装

参数配置

4、nginx-1.6.2

编译安装

参数配置

5、pgbouncer-1.5.4

pgbouncer连接池也装在应用服务器上面

编译安装

安装pgbouncer需要libevent包

参数配置

运行参数文件/home/ad/pgbouncer/pgbouncer.ini

用户及口令文件/home/ad/pgbouncer/user.txt

6、golang-1.7.3

直接安装

测试数据及脚本

1、数据库环境

2、测试程序

性能校准

1、apache+php

短连接测试

配置apache,关闭长连接配置

重启服务

在另外一台电脑上使用wrk工具进行测试

使用atop查看服务器的资源使用情况

http连接断开等待情况

长连接测试

非全程长连接

跑wrk测试

使用atop查看服务器的资源使用情况

全程长连接

跑wrk测试

使用atop查看服务器的资源使用情况

从上面测试的结果来看,在高并发,高压力的情况下,进程复用可以提高一倍的系统性能。短连接时产生了大量的TIME_WAIT进程,产生的原因主要是客户端不断的连接和断开,在高并发的情况下,服务器迟迟没收到客户端断开连接的第四次握手信号造成的,这些进程会一直占用locale port, 导致本地端口号给消耗光了。可以设置下面的内核参数来提高locale port的使用效率

net.ipv4.tcp_syncookies = 1 #表示开启SYN Cookies,可防范少量SYN攻击,默认为0

net.ipv4.tcp_tw_reuse = 1 #允许将TIME-WAIT sockets重新用于新的TCP连接,默认是0

net.ipv4.tcp_tw_recycle = 1 #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认是0

net.ipv4.ip_local_port_range = 1024 65535 #增大locale port数量,默认是从32768开始

不过这几个参数是治标不治本,最终还是要回到提升api本身的处理能力.另外对于动态的api接口业务,如果你的客户端直接与apache进行通信,现实中基本都是短连接业务,所以用apache+php跑个13000已经是极限了。

2、nginx+apache+php

nginx与apache短连接通信

下面我们来看看nginx+apache+php在短连接的情况下,locale port是怎样给消耗光的,nginx+apache+php见上面的配置

使用wrk工具对nginx进行压力测试

使用atop查看服务器的资源使用情况

在测试到一半的时候再打开一个终端,测试一下服务器是否还有接受请求的能力,发现连接超时,使用top查看系统负载情况,竟然没负载

1871次/秒的处理能力,还有timeout情况,是不是怀疑nginx有问题,其实这不是nginx的问题,主要是nginx处理能力太强了,而apache跑php弱了,导致进程一直占用socket port,我们只需要做一下这样的调整,服务器的处理能力就上来了

nginx与apache长连接通信

使用atop查看服务器的资源使用情况

客户端与nginx长连接通信,nginx与apache长连接通信

看上去数据变化不大,但是TIME_WAIT量明显减少了

由于nginx和apache是跑在同一个节点上,cpu互相争用,所以并发数下来,如果跑在不同的机器上,nginx代理的损耗其实是非常小的,看看下面的测试就会知道

nginx与apache长连接通信(不同节点)

nginx位于应用服务器

apache位于数据库服务器

从上面的测试数据来看,建议高并发简单业务的接口采用第5种方案,如果是web网页与接口混合使用的,使用第6种模式

四、业务测试

为了测试更接近于实际业务场景,这次使用http_load工具,http_load使用单进程并发多个线程进行并发测试,访问nginx时采用的是非长连接访问,并且可以设置每秒访问接口次数,http_load测试特别说明

单进程限制每秒1000次访问

参数为-r 334(超过1000的三分之一)时,实际上能跑到500次/秒的访问量

参数为-r 501(超过1000的二分之一)时,测试端cpu会跑满

所以跑每秒500次访问时参数是-r 334, 跑每秒1000次访问时启用两个-r 334 http_load进程来测试,依此类推

模拟每秒100次访问,持续访问300秒

模拟每秒500次访问,持续访问300秒

因为测试工具占用cpu资源还是比较大,需要另外一台主机上运行,这样测试更准确

1、nginx+apache+php+pgsql

测试结果

每秒100次访问

其它略,下面是测试结果对比表

数据库服务器压力对比

应用服务器压力对比

从上面的数据来看,qps为400时数据库服务器就出现了不稳定情况,而且应用服务器的locale port会被消耗光。通过对数据的对比,发现数据库服务器sys_cpu比user_cpu占用量还要大,原因与上面应用服务性能测试时一致,就是在高并发时,进程不断连接和关闭过度消耗了cpu资源。应用服务器locale port给占完,导致http请求失败。得想办法让应用程序与pg服务连接进程可以复用,减少数据库服务器的cpu压力才行,上pgbouncer连接池吧。

下面先说一下,怎样查询pg进程有没复用,使用捉包工具tcpdump捉取两次独立请求时连接数据库的local port ,如port一致则就是进程复用,如下所示

在数据库服务器上的一个终端输入下面命令

在测试机上连续输入下面命令二次,非连接池连接

在tcpdump终端你会看到下面的信息,对应的locale port不一致

在测试机上连续输入下面命令二次,连接池连接

在tcpdump终端你会看到下面的信息,对应的locale port一致

2、nginx+apache+php+pgbouncer+pgsql

每秒100次访问

其它略,下面是测试结果对比表

数据库服务器压力对比

应用服务器压力对比

从上面的数据来看,qps为400时数据库服务器压力非常的小,但应用服务器与数据库服务器的通信效率太低,导致应用服务器的locale port被消耗光,http服务拒绝连接,瓶颈在应用与连接池的通信效率上,只能水平扩展多一些应用服务器节点了,

下面看看双应用服务器节点的性能是不是会提高

3、nginx负载双节点(apache+php)+pgbouncer+pgsql

nginx.conf配置如下

首先在数据库节点上也装上apache/php/pgbouncer

接着修改应用节点上的nginx.conf配置,如下

重启nginx服务

测试开始

每秒100次访问

其它略,下面是测试结果对比表

应用服务器压力对比

从上面的数据来看,应用服务器水平扩展之后,并发数也跟着上来了,而且数据库服务器的压力还是在可以接受的范围之内,虽然满足了业务的初步请求,但还是无法对付峰值请求,如果想处理更大的并发量,要不再水平扩展应用服务器,另一个就是想办法提高“应用程序与pg”的通信效率,下面使用go来实现这些架构,看看是不是会提高。

4、基于go的后端服务架构

这是go的服务端程序

启动服务,配置8个连接数

测试开始

每秒100次访问

其它略,下面是测试结果对比表

数据库服务器压力对比

应用服务器压力对比

从上面的测试数据我们可以看到基于go的服务端应用程序由于每次处理业务时都不需要与应用程序进行通信,也不需要与数据库进行连接,所以其sys cpu消耗的极其的低,编译型程序,执行效率也高,在并发到3000的qps时,数据库的cpu负载才过一半。由此可见使用Go服务端应用来支撑业务简单的高并发应用是非常适合的方案。

为了更友好的对外通信,统一api入口,我们使用nginx做web服务入口,再代理跑各种应用,现在来看看nginx代理跑go性能是否也能满足

5、基于nginx+go的后端服务架构

nginx上的配置,记得配置nginx与go通信采用长连接哦

下面是测试结果对比表

数据库服务器压力对比

应用服务器压力对比

加了nginx代理之后对数据库的性能没影响,只是应用服务器的cpu开销大了一点,这个损耗是在可接受范围之内的,而且也可以将nginx与应用服务节点进行分离到不同的节点上面。

五、测试结果对比

各种框架处理qps峰值--值越大越好

各种框架处理300qps时cpu压力--值越小越好

以上是对于高并发,业务极其简单的接口在通信架构上的一种优化方式,具体采用哪种构架来搭建你们的应用,需要具体业务具体优化,灵活搭配就是,另外还要考虑运维的成本。

作者:阿弟
来源:掘金
商业用途请与原作者联系,本文只做展示分享,不妥侵删!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表