在 Swoole 服务器程序中如何实现压力反馈

为什么要反馈压力

服务端程序在遇到高并发请求时,一旦超过程序所能处理的极限,可能会导致崩溃,引发线上服务的大规模雪崩。压力反馈(Back Pressure)是一种由服务端主动告知客户端自身资源不足,无法提供服务的一种手段。在 Web 服务中可以返回 HTTP 503Service Unavailable)告知客户端当前服务器处于比较高的负载状态。这时客户端可以选择:

  1. 等待一定时间后进行重试
  2. 切换其他负载较低的节点或者服务器上
  3. 暂时停止使用此服务,对相关的业务进行降级处理

PHP-FPM 如何反馈压力

在传统 Nginx+PHP-FPM 服务端程序中,底层有 3 个关键的配置影响压力反馈:

  1. php-fpm.confpm.max_chindren 配置的最大进程数,如配置为 200 表示最大启动 200 个进程,一旦超过最大进程数,新的请求将不会被 Accept,而是进入到 Listen Backlog 队列中进行排队,直到有空闲进程才会从队列弹出一个新的请求进行处理
  2. php-fpm.conflisten.backlog 配置 Listen Backlog 队列长度,如配置为 512 ,则表示若没有空闲进程时,最大允许有 512 个请求排队
  3. 内核参数 net.core.somaxconnlisten.backlog 设置的数值不一定是有效的,这取决于内核参数 net.core.somaxconn 的设置,实际队列长度为 min(listen.backlog, net.core.somaxconn),例如 net.core.somaxconn=128listen.backlog=512,实际的队列长度为 128 而不是 512

因此在 Nginx+PHP-FPM 程序中,最大并发为 pm.max_chindren + min(listen.backlog, net.core.somaxconn),一旦超过之后,就会拒绝新的请求,返回 502 错误,向客户端反馈压力。实际项目中,应当设置为一个合适的值,不宜过大或过小。否则就出产生客户端等时间过长,低负载拒绝请求两种问题。

Nginx 无法区分 502503 错误,这是一个缺点

Swoole 程序如何反馈压力

由于 Swoole 是完全异步的架构,并发能力更强,在机器资源未耗尽的前提下,是可以无限接受、处理请求的。相比 Nginx+PHP-FPM 不好实现压力反馈,一般需要框架层面或者应用层代码中自行抛出 503 错误。Swoole 底层提供了多项配置可以解决一部分问题。

max_connection

限制最大连接数, 超过最大连接数之后,会拒绝新的连接。返回 502 错误给 Gateway

max_coroutine

限制最大进程数,Swoole 会在接收到客户端请求时创建一个新的协程进行处理,超过最大协程数之后,就会向客户端发送 HTTP 503 错误

max_concurrency

限制最大并发 HTTP 请求数,当前正在处理的请求数超过 max_concurrency 后,底层会立即向客户端发送 HTTP 503 错误,并关闭连接。

use Swoole\Http\Server;

$http = new Server('127.0.0.1', 9501);

$http->set([
    'max_connection' => 10000,
    'max_coroutine' => 50000,
    'max_concurrency' => 500,
]);

$http->on('start', function ($server) {
    echo "Swoole http server is started at http://127.0.0.1:9501\n";
});

$http->on('request', function ($request, $response) {
    Co::sleep(0.1); // sleep 100ms 模拟请求处理的过程
    $response->header('Content-Type', 'text/plain');
    $response->end('Hello World');
});

$http->start();

启动服务器后使用 abwrk 压测。

wrk -c 1000 -d 5s http://127.0.0.1:9501/
Running 5s test @ http://127.0.0.1:9501/
  2 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    70.89ms  132.48ms   1.10s    95.39%
    Req/Sec     7.99k     3.68k   13.03k    66.32%
  77521 requests in 5.09s, 5.41MB read
  Socket errors: connect 0, read 55182, write 0, timeout 0
  Non-2xx or 3xx responses: 55182
Requests/sec:  15242.49
Transfer/sec:      1.06MB

可以看到 5秒 之内,共发送了 77521 个请求,但是有 55182 个请求返回了 503 。这部分请求就是超过负载后压力反馈的结果。


Swoole
PHP的协程框架
avatar
韩天峰
Swoole 开源项目创始人

Swoole 开源项目创始人

7.8k 声望
11.1k 粉丝
0 条评论
推荐阅读
Swoole 5.1 增加更多数据库协程客户端支持
在 5.1 版本中增加了多种数据库协程客户端的支持,并且全部以 PDO 接口的方式提供,旧的业务代码无需做任何更改即可一键切换为协程模式,异步非阻塞地并发执行。

韩天峰

初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go4阅读 1.8k评论 2

封面图
一分钟搞明白!快速掌握 Go WebAssembly
最近因为各种奇怪的原因,更多的接触到了 WebAssembly。虽然之前很多博客也翻过写过各种文章,但总感觉欠些味道。于是今天梳理了一版,和大家一起展开学习。

煎鱼4阅读 2.3k

Laravel入门及实践,快速上手ThinkSNS+二次开发
【摘要】自从ThinkSNS+不使用ThinkPHP框架而使用Laravel框架之后,很多人都说技术门槛抬高了,其实你与TS+的距离仅仅只是学习一个新框架而已,所以,我们今天来说说Laravel的入门。

ThinkSNS1阅读 2.5k

悬赏任务源码+开源威客系统网站源码+部署教程
威客悬赏任务发布系统源码是用来进行日常在线任务接单处理的威客系统。系统可以用来发布或处理悬赏任务,甚至可以知道一个帐户的信息,如任务类型和处理状态等,它们很方便,易于使用,它允许雇主和威客执行快速...

火爆的筷子1阅读 3.8k评论 1

我让chatGPT用PHP写一个MVC框架,不仅写出来,还能跑!
没想到写出来的框架确实挺简单的,但是又没觉得哪里不对,于是我尝试把这个框架放到服务器试试能不能跑起来,最后还真的可以跑起来,为了让大家能够看到这个框架的演示,我直接爬一个热搜,然后便于展示数据。

TANKING1阅读 1.7k

封面图
开发一个全网搜索引擎的大致流程
由于对搜索引擎技术很感兴趣,便开始尝试开发一个搜索引擎。在参考了网上有限的资料后,加上自己钻研,最终开发出了一个小型的全网搜索引擎,底部有项目地址和搜索测试图片。

会飞的鸟1阅读 5.8k评论 1

avatar
韩天峰
Swoole 开源项目创始人

Swoole 开源项目创始人

7.8k 声望
11.1k 粉丝
宣传栏