高并发的哲学原理(二)-- Apache 的性能瓶颈与 Nginx 的性能优势

news2024/11/25 18:30:09

每一名后端开发可能都知道 Nginx 比 Apache 性能强,但是为什么强,强在哪里,接下来我们动手实验解答这个问题。

Nginx 利用了新的 Linux kernel API

Nginx 利用了 Linux 内核引入的 epoll 事件驱动 API,大幅降低了海量 TCP 连接下的 CPU 负载,提升了单个系统的 TCP 响应容量,这是 Nginx 性能更好的本质原因:时代在进步。

每一篇技术文章都会说,Nginx 的 epoll 比 Apache 的 select 性能高,但为什么,却几乎没人解释。下面我来尝试解释。

epoll 简单解释

众所周知,epoll 是一种高性能事件驱动 IO 多路复用机制,那他和 select 这种原始 IO 多路复用机制比有什么优势呢?简单来说,就是:转守为攻。

epoll 化被动为主动,以前需要两次遍历才能实现的网络数据包和线程的匹配,现在通过事件驱动的方式主动献上指针,性能暴增。这就像云原生时代的 Prometheus 监控:化主动上传为被动查询,大幅提升单个采集节点的性能上限,成功解决了监控领域的高并发性能问题。

在 5K 个 TCP 连接的情况下,每收到一个数据包,Nginx 找到对应线程的速度比 Apache 高了两个数量级,即便是 event 模式下的 Apache,性能依然远低于 Nginx,因为 Nginx 就是专门为“反向代理”设计的,而 Apache 本质是个 web 应用容器,无法做到纯粹的事件驱动,性能自然无法和 Nginx 相比。

Apache 的原始并发模型

Apache 支持三种进程模型:preforkworkerevent,在此我们简单讨论一下这三种模式的优缺点。

  1. prefork 是进程模式,需要消耗更多的内存,每次接到一段新的数据,需要使用 select 模型,遍历 TCP连接数 x 进程数 这么多次才能找到匹配的进程,在数千个 TCP 连接下,光是寻找线程就需要消耗掉一个 CPU 核心,单机性能达到极限,无法利用更多的 CPU 资源
  2. worker 是线程模式,依旧使用 select 模型来遍历 TCP 请求和线程,性能上限和 prefork 一致,区别是内存消耗量有了一些降低,初始 TCP 承载能力稍好,请求数突然增加的场景下,开新线程的速度反而比 prefork 更慢,且基础延迟比 prefork 模式更高
  3. event 模式采用和 Nginx 一致的 epoll 模型承载,理论上表现和 Nginx 一致,但由于 Apache 大概率是和 mod_php(插件)模式的 PHP 一起部署,再加上 PHP 阻塞运行的特性,性能和上面两兄弟并无明显区别。因此即便是 event 模式下的 Apache,性能依然远低于 Nginx。

接下来我们使用 jmeter 测试一下 prefork、worker、event 三种模式的性能。

压力测试

测试环境

  • 客户端:

    • i5-10400 6 核 12 线程
    • 32GB 内存
    • 千兆有线网络
    • 软件环境
      • macOS
      • Java 19.0.1
  • 服务端:

    • 物理服务器 E5-2682V4 2.5GHz 16 核 32 线程 * 2 (阿里云 5 代 ECS 同款 CPU)256GB RAM
    • 虚拟机 64 vCPU (赋予了虚拟机所有母机的 CPU 资源)
    • 虚拟机内存 32GB
    • 软件环境
      • CentOS Stream release 9
      • kernel 5.14.0-200.el9.x86_64
      • Apache/2.4.53
      • Nginx/1.20.1
      • PHP 8.0.26
    • PHP 环境:
      • Laravel 9.19
      • 给默认路由增加 sleep 500ms 的代码,模拟数据库、Redis、RPC、cURL微服务等场景
      • 执行 php artisan optimize 后测试
  • 测试代码

Route::get('/'function () {
usleep(500000);
return view('welcome');
});
  • Apache prefork 模式配置
<IfModule mpm_prefork_module>
    StartServers         100
    MinSpareServers      5
    MaxSpareServers      100
    MaxRequestWorkers    500
    MaxRequestsPerChild  100000
</IfModule>
  • php-fpm 配置
pm = static
pm.max_children = 500

实验设计

我们将测试三种配置下的性能表现差异:

  1. Apache 标准模式:prefork + mod_php 插件式运行 PHP
  2. Nginx + php-fpm 专用解释器
  3. Nginx 作为 HTTP 反向代理服务器后接 Apache prefork 模式 + mod_php 插件式运行 PHP

请求计划

  1. 客户端新线程开启后,每隔 5 秒发送一个请求
  2. jmeter 用 50 秒开 5000 个线程,持续压测 100 秒,最大请求 QPS 为 1000

为什么这么设计?

单独对比 Nginx 和 Apache 性能的文章很多,数据结果也大同小异,无非是 Nginx 的 QPS 更高,但是 “为什么是这样?” 却没人回答,我本次的实验设计就是要回答这个问题。

Apache 标准模式:prefork + mod_php

alt alt

nginx + php-fpm

alt alt

nginx 反向代理 Apache 标准模式

alt alt

结果分析

我们可以很明显地看出,Apache + prefork 的问题在于它对数千个 TCP 连接的处理能力不足。

  1. Nginx + fpm 一共发出了 59146 个请求,成功了五万个
  2. Nginx + Apache 一共发出了 56464 个请求,成功了五万两千个,比 fpm 还多一些
  3. fpm 模式最大 QPS 为 800 但比较稳定,Nginx + Apache 最大 QPS 1000 但不够稳定
  4. 至于 Apache 标准模式,显然它的技术架构不足以处理 5000 个 TCP 连接下 1000 QPS 的状况,QPS 低且不稳定,错误率高达 43%

结论:

  1. Nginx 处理海量用户的海量 TCP 连接的能力超群
  2. 提升 Apache 性能只需要在前面加一个 Nginx 作为 HTTP 反向代理即可,因为此时 Apache 只需要处理好和 Nginx 之间的少量 TCP 连接,性能损耗较小
  3. php-fpm 和 mod_php 在执行 PHP 的时候没有任何性能差异

Nginx epoll 和 Apache prefork 模型相比,优势劣势如下:

优势
  1. Nginx 每个 worker 进程可以 handle 上千个 TCP 连接,消耗很少的内存和 CPU 资源,可以让单台服务器承接比 Apache 多两个数量级的用户量,相比于 Apache 单机 5K 的 TCP 连接数上限(对应的是 2000 个在线用户),是一个巨大的进步
  2. Nginx 对 TCP 的复用使它非常善于应对海量客户端的直接连接,根据我的实测,在 HTTP 高并发下 Nginx 的活跃 TCP 连接数可以做到 Apache 的五分之一,而且用户量越高,复用效果越好
  3. 在架构上,基于 FastCGI 网络协议进行架构扩展,也可以更轻易地利用多台物理服务器的并行计算能力,提升整个系统的性能上限
劣势
  1. 在低负载下,Nginx 事件驱动的特性使得每个请求的响应时长比 Apache prefork 模式略长一些(14ms vs 9ms)

我的真实经验

新冠时期的爱情机遇

疫情初期,我司的私域电商业务兴起于草莽之间,在 3 月中旬才上班的情况下,半个月的 GMV 超过了前面一年,4 月就完成了全年目标,电商系统性能压力陡增。

当时我们的电商系统是购买的一个 PHP 单体系统,天生不具有扩展性,外加业务模式是团购秒杀,可要了亲命了。客户端为微信小程序,服务端主要提供两种业务:开团瞬间的海量 HTTP API 请求,以及每一个页面都非常消耗资源的订单管理后台。

当时我面临的第一个问题是数据库顶不住,我找到请求数最高的接口:商品详情,为它增加了一层保持时长为一分钟的 Redis 缓存,开团瞬间数据库的压力降低了很多。

而且幸运的是当时阿里云刚刚将 PolarDB 商用几个月,我用它顶住了开团三分钟内涌入的大约 4000 名用户,但是当我把虚拟机升级到 16 核 32G 内存的时候出现了一个非常诡异的现象:

  1. CPU 和内存占用率分别只有 8% 和 6%
  2. 但大量的新用户就是无法建立 TCP 连接,首次连接的客户端表现为长时间的等待
  3. 如果运气好在等待一段时间后成功进去了,那访问便会一直如丝般顺滑,每个接口的返回时间都非常短

这是为什么呢?这是因为新用户无法和服务器建立 TCP 连接!

默认情况下,CentOS 7.9 的最大文件打开数(ulimit)为 1024,一切皆文件,每个 TCP 连接也是一个文件,所以也被锁定在了 1024 个。一般大家都会把这个数字设置为 65535,但是我观察到,这台虚拟机此时的 TCP 连接数只能跑到 5-6K 之间,远远达不到用户的需求,无论是采用 prefork、worker 还是 event 都是这样。而原因就是我们上面实测过的:此时 Apache 花费了一颗核心的全部时间片来进行数据包和线程的匹配,已经忙不过来了。

后来,我在这台机器上安装了一个 Nginx,反向代理全部的用户请求再发送给 Apache:请求一下子舒畅了,而且 Nginx 使用的最大活跃 TCP 连接数量也只有 1K,就完全满足了三分钟 4000 用户的需求。

还记得我们的目标吗?一百万 QPS

在 2022 年的主流云服务器硬件上,经过 OPCache 性能优化的 PHP 应用,只需要 2 vCore 便可以达到 5K 的单机 Apache TCP 上限,此时 QPS 在 200 左右,单纯提升核心数量无法让这个数字大幅增加。而通过使用 Nginx,我们可以将单系统的 QPS 上限从 200 提升到 1000。

出自:https://github.com/johnlui/PPHC

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/746722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA+springboot+ssm+layui+mysql高校宿舍管理系统源码

IDEAspringbootssmlayuimysql高校宿舍管理系统源码 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.宿舍列表3.预分配宿舍4.宿舍分配信息5. 留校管理6. 报修管理7. 留言管理8.卫生管理9.我的宿舍10.我的报修11.卫生检查记录12.离校登记13.留校申请14.返校登记15.留言板16.…

IDEA+springboot + ssm +shiro+ easyui +mysql实现的进销存系统

IDEAspringboot ssm shiro easyui mysql实现的进销存系统 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.首页3.修改密码4.系统日志5. 用户管理6. 角色管理7. 进货入库8.退货出库9.进货单据查询10.退货单据查询11.当前库存查询12.销售出库13.客户退货14. 销售单据查询15…

消息中间件选型RabbitMQ基础入门

1. 消息中间件(MQ) 1.1 概述 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用解耦&#xff0c;异步消息&#xff0c;流量削锋等问题&#xff0c;实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构 目前使用较多的消息队列有ActiveMQ&#xff…

使用 Docker 在 Windows、Mac 和 Linux 系统轻松部署 PostgreSQL 数据库

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

本地运行Segment Anything

按原项目GitHub - facebookresearch/segment-anything: The repository provides code for running inference with the SegmentAnything Model (SAM), links for downloading the trained model checkpoints, and example notebooks that show how to use the model.步骤 Ins…

Apache Phoenix(1):Phoenix介绍

Phoenix官方网址&#xff1a;http://phoenix.apache.org/ 1 简介 Phoenix官网&#xff1a;「We put the SQL back in NoSQL」 Apache Phoenix让Hadoop中支持低延迟OLTP和业务操作分析。 提供标准的SQL以及完备的ACID事务支持通过利用HBase作为存储&#xff0c;让NoSQL数据库具…

一些三维点云去噪算法

1 什么是去噪 1.1 噪声 噪声&#xff1a;也称为孤立点/离群点/异常点&#xff0c;是指点云数据中的不相关或不希望存在的干扰信号或误差。噪声来源&#xff1a;环境光线的明亮程度、测量设备精度及系统误差、物体材料及表面的纹理和人为抖动等因素影响。 1.2 噪声来源 环境…

【雕爷学编程】Arduino动手做(138)---64位WS2812点阵屏模块2

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

6.EFLFK(EFLK+kafka)

文章目录 EFLFK(EFLKkafka)zookeeper概述Zookeeper 特点数据结构和工作场景选举机制&#xff08;重要&#xff09;总结部署Zookeeper kafka为什么用消息队列&#xff08;MQ&#xff09;中间件使用消息队列的好处消息队列模式消息队列总结&#xff1a;kafka概述Kafka特性Kafka架…

Layui之选项卡案例 详细易懂

⭐ 本期精彩&#xff1a; 利用Layui框架实现动态选项卡 ⭐ 继上一篇已经实现了左边的树形菜单栏&#xff0c;这一关卡我们已通过&#xff0c;接下来就是实现右边的动态选项卡的关卡,上个关卡的效果及链接 ⭐ 链接&#xff1a;http://t.csdn.cn/tYccL 目录 ⭐ 本期精彩&#xf…

2023秋招,网络安全面试题

Hello&#xff0c;各位小伙伴&#xff0c;我作为一名网络安全工程师曾经在秋招中斩获&#x1f51f;个offer&#x1f33c;&#xff0c;并在国内知名互联网公司任职过的职场老油条&#xff0c;希望可以将我的面试的网络安全大厂面试题和好运分享给大家~ 转眼2023年秋招已经到了金…

E510-A1S-I0/A0插头式连接比例放大器

E510-A1S-U0/A1、E510-A1S-I4/A1、E510-A1S-U0/B2、E510-A1S-I4/C0、E510-A1S-U0/A2、E510-A1S-I0/A0、E510-A1S-U0/A3&#xff08;BEUEC&#xff09;插头式比例阀放大器内部装有一个STM微处理器接受两个来自外部输入的模拟量指令信号和三个设定参数的内置电位器模拟量&#xf…

前端 - 接口请求抓包 Status Canceled 分析

问题描述 上图是来自于百度的抓包请求分析状态&#xff0c;一般常见的有 status 200&#xff0c;500&#xff0c;404&#xff0c;504&#xff0c;403&#xff0c;302……但这次遇到一个 status canceled&#xff08;第一次遇见还真一脸懵~&#xff09; 原因分析 那响应statu…

MySQL 的内连接、左连接、右连接有有什么区别?

MySQL的连接主要分为内连接和外连接&#xff0c;外连接常⽤的有左连接、右连接。 inner join 内连接&#xff0c;在两张表进行连接查询时&#xff0c;只保留两张表中完全匹配的结果集&#xff1b;left join左连接在两张表进行连接查询时&#xff0c;会返回左表所有的行&#x…

安卓OpenCV开发(六)图片处理(1)

使用OpenCV进行图片处理&#xff08;1&#xff09; 基础知识可以回顾我之前写的文章&#xff1a; OpenCV导入 OpenCV人脸检测 OpenCV竖屏检测 OpenCV人脸识别 OpenCV小狗识别 本文将提供一下openCv处理图片的处理&#xff0c;文末附上代码链接。 &#xff08;1&#xff09;灰…

kali NetHunter刷入

准备 安卓frida逆向协议与分析第一章中提供的刷机教程&#xff0c;Nexus 5X手机一部&#xff0c;kali NetHunter镜像&#xff0c;kali Linux(因为很多命令需要LInux命令不能直接用windows) 命令开发包下载 adbfastboot https://developer.android.com/studio/releases/platf…

执行Spark应用架构需要经历哪几个阶段?

将程序切换到【Executors】Tab页面时&#xff0c;我们可以看到Spark Application运行到集群上时&#xff0c;由两部分组成&#xff1a;Driver Program和Executors。 从图中可以看到Spark Application运行到集群上时&#xff0c;由两部分组成&#xff1a;Driver Program和Execut…

Holoens证书过期

1. 删除Assets\WSATestCertificate.pfx证书文件。 2. 在Player Settings的Publishing Settings下找到Certificate,选择一个有效的证书。 3. 如果没有其他有效证书,需要生成一个新的测试证书: - Windows: MakeCert.exe -r -pe -n "CNTemporary Certificate" -ss MY …

融合ELO机制的销售能力评估方案

ELO排位赛算法 文章目录 ELO排位赛算法一. ELO机制二. 销售能力抽象为ELO排位赛设计2.1 基础设计2.2 存在问题 三. 优化措施3.1 如何解决新销售存在冷启动问题新老人动态K值调整假设检验衡量赢的程度 3.2 如何解决转化率存在不置信的问题ELO升级为MultiELO 一. ELO机制 ELO等级…

代码随想录day15

102. 二叉树的层序遍历 这里如果使用递归法会更好的理解&#xff0c;当我们储存每一层的答案数组的长度等于当前的level层数&#xff0c;说明我们这一层的节点都已经遍历完了&#xff0c;然后我们的下一次递归的level可以直接1。 递归三要素&#xff1a; 递归终止条件&#xf…