谈一谈生产环境中swoole协程创建数量控制机制

在swoole官方文档中,有提及“协程开销”。简单引用如下:

  • 在 PHP-7.2 版本中底层会分配 8K 的 stack 来存储协程的变量,zval 的尺寸为 16字节,因此 8K 的 stack 最大可以保存 512 个变量。协程栈内存占用超过 8K 后 ZendVM 会自动扩容。
  • PHP-7.1PHP-7.0 默认会分配 256K 栈内存

本文以php7.2为例,因为笔者当前使用的php版本也是7.2。 

为了验证php7.2中,创建一个协程是否默认为8K,可以写个demo简单测试一下

<?php

$begin_memory = memory_get_usage();
go(function () {
    co::sleep(10);
    echo co::getCid() . PHP_EOL;
});

var_dump(memory_get_usage() - $begin_memory); //输出int(8640),单位是byte, 就是8K左右。

既然创建一个协程,默认分配8K内存,假设我们在协程中执行的代码使用的栈内存,不超过8K,那么1G的内存大约可以创建多少个协程呢?1G= 1024MB = (1024 * 1024)KB, max_coroutine_num = 1024 * 1024 / 8 = 130072。也就是说1G内存就可以创建10w+的协程数量。相当的可观。但是实际情况,栈内存可能会超过。

笔者当前有个业务场景,从redis队列中pop数据,然后开协程写入mysql,我们知道mysql的写速度落后redis非常多,当业务高峰期,redis队列数据量猛增时,mysql达到瓶颈之后,协程的数量就会积压。高峰期持续时间达到一定程度,那么最终会因为内存资源不足,导致新的协程无法再创建,这时swoole会触发:PHP Warning: PHP Warning:  go(): exceed max number of coroutine ... 

所以得出一个经验:在生产消费模型中,最好对swoole 协程创建数量进行控制

swoole协程控制方案:

1、依赖swoole底层的max_coroutine配置。给出示例demo

<?php

set_error_handler(function () {
    throw new Exception("error happen\n", 500);
});
co::set(['max_coroutine' => 1]);
try {
    for ($i = 0; $i < 2; $i++) {
        go(function () {
            co::sleep(10);
        });
    }

} catch (\Throwable $e) {
    if ($e->getCode() == 500) {
        echo "协程数量超过限制!" . $e->getMessage();
    }
}

2、自己创建一个Context管理统计当前正在执行的协程数量,超过指定的数量,抛出异常或者自定义处理

<?php

define("APP_MAX_COROUTINE", 10);

$co_ctx = [];

go(function () use ($co_ctx) {
    if (count($co_ctx) >= APP_MAX_COROUTINE) {
        //超过限制,退出
        return;
    }
    $cid = co::getCid();
    defer(function () use ($cid, $co_ctx) {
        if (isset($co_ctx[$cid])) {
            unset($co_ctx[$cid]);
        }
    });
    $co_ctx[$cid] = $cid;
    
    //begin business ...
});

讨论结束,不正之处 ,多多指教!                     thks!!!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值